diff options
author | mrj <none@none> | 2007-01-19 08:10:06 -0800 |
---|---|---|
committer | mrj <none@none> | 2007-01-19 08:10:06 -0800 |
commit | ae115bc77f6fcde83175c75b4206dc2e50747966 (patch) | |
tree | 4cbe67724fffb4374fdef9af1e188357a20aad1d /usr/src | |
parent | 4fceebdf03eeac0d7c58a4f70cc19b00a8c40a73 (diff) | |
download | illumos-joyent-ae115bc77f6fcde83175c75b4206dc2e50747966.tar.gz |
PSARC 2006/469 EOF and removal of eeprom -I
PSARC 2006/568 direct boot (dboot) for x86
6219282 interrupt service routine called twice
6223946 potential infinite loop in fbt.c
6228819 tsc_gethrtimeunscaled resets to 0 on suspend
6342201 hat_unload() and cross call usage are needlessly slow on x86, x64
6378723 ctfconvert can't handle GCC empty struct C extension
6379124 ctfconvert can't handle C99 flexible array members
6401187 merging ip's CTF data into genunix introduces a race
6437553 shmat(2) fails on platforms that don't support large pages
6449286 eeprom -I should be torched
6464072 need support for firmware properties
6465816 need a debug record page
6467491 64-bit processes must point %fs or %gs to null selector to utilize [fs|gs]base
6475880 vestiges of old boot code on i386/amd64 should be purged
6475956 Interrupt handling code on x86 platforms should be easier to understand
6477828 pcplusmp psm module should be rearranged to allow multiple platforms to share the same apic code
6477867 x86 KDI should belong in the kernel
6477871 fix for 6232859 also needed for kmdb
6477872 MDB MMU commands need improvements
6477873 cpr debugging can be improved
6477877 mstate accounting should be reset when gethrtimef() is changed
6477915 32-bit x86 kernel should use interrupt gates for all traps
6477963 _update_sregs should be written in C
6477976 no longer need to capture [fs,gs]base in struct regs on every exception
6478642 Solaris needs to support multiple x86 platforms
6478648 ON could use an new & unencumbered xsvc driver
6478734 kernel lint not in C99 mode
6478826 swrand should have framework to lock individual pages
6480763 if interrupts can't be disabled, re-onlining an offline cpu fails
6481824 /dev/fb is not created if installation is done over tty
6483747 clock-tick processing should re-include threads waiting for I/O
6485872 use PTOU macro to access user area instead of old "u" from user.h
6486263 need way to extend kernel core dumps with pages that don't have page_t's
6486435 eeprom, prtdiag should only be platform specific where necessary
6486436 genunix mdb module makefiles duplicate list of files
6486437 intr_common.c should be common
6486445 /dev/mem needs support for page_t-less pages
6486451 cpu_pause() routine should be mach-specific
6486456 SIMULATOR_SUPPORT should die
6486832 x86 platform will need memlist/memseg locking
6486911 amd64 port not finished
6486972 platform TOD setting code may not have real TOD hdw to set
6492647 Better trap trace support for x-calls
6493613 apic_disable_intr() needs round robin fix
6497633 ctfmerge could allow for no ctf sections
6500637 floating point context switching is needlessly slow
6500656 move floating point configuration to C
6500666 need a means to override the setting of uname -m in the kernel build
6500669 update x86 defines
6502790 Files in the boot archive should be individually compressed
6503792 live upgrade environment + bfu + alternate root == incorrect menu.lst file
6504373 kmdb promif shouldn't needlessly busy-wait
6504374 ::interrupts could show level/edge
6506305 opteron erratum 123 should be enabled
6507629 porting x86 platform code to Xen
6510847 kobj.c is unaware of sparc hole between nucleus text and data (from dtrace)
--HG--
rename : usr/src/cmd/eeprom/common/Makefile => deleted_files/usr/src/cmd/eeprom/common/Makefile
rename : usr/src/cmd/eeprom/eeprom.xml => deleted_files/usr/src/cmd/eeprom/eeprom.xml
rename : usr/src/cmd/eeprom/i386/common/benv_sync.c => deleted_files/usr/src/cmd/eeprom/i386/common/benv_sync.c
rename : usr/src/cmd/eeprom/i386/i86pc/Makefile => deleted_files/usr/src/cmd/eeprom/i386/i86pc/Makefile
rename : usr/src/cmd/eeprom/sparc/sun4u/Makefile => deleted_files/usr/src/cmd/eeprom/sparc/sun4u/Makefile
rename : usr/src/cmd/eeprom/sparc/sun4v/Makefile => deleted_files/usr/src/cmd/eeprom/sparc/sun4v/Makefile
rename : usr/src/cmd/mdb/common/kmdb/kmdb_kdi_impl.h => deleted_files/usr/src/cmd/mdb/common/kmdb/kmdb_kdi_impl.h
rename : usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.h => deleted_files/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.h
rename : usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.s => deleted_files/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.s
rename : usr/src/cmd/mdb/intel/amd64/kmdb/kaif_resume.s => deleted_files/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_resume.s
rename : usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.h => deleted_files/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.h
rename : usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.s => deleted_files/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.s
rename : usr/src/cmd/mdb/intel/ia32/kmdb/kaif_resume.s => deleted_files/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_resume.s
rename : usr/src/cmd/mdb/intel/kmdb/kaif_activate.c => deleted_files/usr/src/cmd/mdb/intel/kmdb/kaif_activate.c
rename : usr/src/cmd/mdb/intel/kmdb/kaif_start_isadep.c => deleted_files/usr/src/cmd/mdb/intel/kmdb/kaif_start_isadep.c
rename : usr/src/cmd/mdb/sparc/kmdb/kaif_enter.s => deleted_files/usr/src/cmd/mdb/sparc/kmdb/kaif_enter.s
rename : usr/src/cmd/prtdiag/i386/i86pc/Makefile => deleted_files/usr/src/cmd/prtdiag/i386/i86pc/Makefile
rename : usr/src/cmd/svc/profile/platform_i86pc.xml => deleted_files/usr/src/cmd/svc/profile/platform_i86pc.xml
rename : usr/src/psm/stand/boot/amd64/alloc.c => deleted_files/usr/src/psm/stand/boot/amd64/alloc.c
rename : usr/src/psm/stand/boot/amd64/amd64/alloc.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/alloc.h
rename : usr/src/psm/stand/boot/amd64/amd64/amd64.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/amd64.h
rename : usr/src/psm/stand/boot/amd64/amd64/amd64_page.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/amd64_page.h
rename : usr/src/psm/stand/boot/amd64/amd64/auxv64.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/auxv64.h
rename : usr/src/psm/stand/boot/amd64/amd64/boothooks.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/boothooks.h
rename : usr/src/psm/stand/boot/amd64/amd64/bootops64.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/bootops64.h
rename : usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h
rename : usr/src/psm/stand/boot/amd64/amd64/cpu.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/cpu.h
rename : usr/src/psm/stand/boot/amd64/amd64/debug.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/debug.h
rename : usr/src/psm/stand/boot/amd64/amd64/machregs.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/machregs.h
rename : usr/src/psm/stand/boot/amd64/amd64/memlist64.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/memlist64.h
rename : usr/src/psm/stand/boot/amd64/amd64/msr.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/msr.h
rename : usr/src/psm/stand/boot/amd64/amd64/print.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/print.h
rename : usr/src/psm/stand/boot/amd64/amd64/segments.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/segments.h
rename : usr/src/psm/stand/boot/amd64/amd64/tss.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/tss.h
rename : usr/src/psm/stand/boot/amd64/amd64/types.h => deleted_files/usr/src/psm/stand/boot/amd64/amd64/types.h
rename : usr/src/psm/stand/boot/amd64/context.c => deleted_files/usr/src/psm/stand/boot/amd64/context.c
rename : usr/src/psm/stand/boot/amd64/cpu.c => deleted_files/usr/src/psm/stand/boot/amd64/cpu.c
rename : usr/src/psm/stand/boot/amd64/exception.s => deleted_files/usr/src/psm/stand/boot/amd64/exception.s
rename : usr/src/psm/stand/boot/amd64/genassym.c => deleted_files/usr/src/psm/stand/boot/amd64/genassym.c
rename : usr/src/psm/stand/boot/amd64/handoff.c => deleted_files/usr/src/psm/stand/boot/amd64/handoff.c
rename : usr/src/psm/stand/boot/amd64/i386_subr.s => deleted_files/usr/src/psm/stand/boot/amd64/i386_subr.s
rename : usr/src/psm/stand/boot/amd64/locore.s => deleted_files/usr/src/psm/stand/boot/amd64/locore.s
rename : usr/src/psm/stand/boot/amd64/memlist.c => deleted_files/usr/src/psm/stand/boot/amd64/memlist.c
rename : usr/src/psm/stand/boot/amd64/offsets.in => deleted_files/usr/src/psm/stand/boot/amd64/offsets.in
rename : usr/src/psm/stand/boot/amd64/print.c => deleted_files/usr/src/psm/stand/boot/amd64/print.c
rename : usr/src/psm/stand/boot/amd64/ptops.c => deleted_files/usr/src/psm/stand/boot/amd64/ptops.c
rename : usr/src/psm/stand/boot/amd64/ptxlate.c => deleted_files/usr/src/psm/stand/boot/amd64/ptxlate.c
rename : usr/src/psm/stand/boot/amd64/segments.c => deleted_files/usr/src/psm/stand/boot/amd64/segments.c
rename : usr/src/psm/stand/boot/amd64/vtrap.c => deleted_files/usr/src/psm/stand/boot/amd64/vtrap.c
rename : usr/src/psm/stand/boot/i386/Makefile => deleted_files/usr/src/psm/stand/boot/i386/Makefile
rename : usr/src/psm/stand/boot/i386/Makefile.com => deleted_files/usr/src/psm/stand/boot/i386/Makefile.com
rename : usr/src/psm/stand/boot/i386/common/bios.c => deleted_files/usr/src/psm/stand/boot/i386/common/bios.c
rename : usr/src/psm/stand/boot/i386/common/biosint.h => deleted_files/usr/src/psm/stand/boot/i386/common/biosint.h
rename : usr/src/psm/stand/boot/i386/common/biosint.map => deleted_files/usr/src/psm/stand/boot/i386/common/biosint.map
rename : usr/src/psm/stand/boot/i386/common/biosutil.c => deleted_files/usr/src/psm/stand/boot/i386/common/biosutil.c
rename : usr/src/psm/stand/boot/i386/common/boot_plat.c => deleted_files/usr/src/psm/stand/boot/i386/common/boot_plat.c
rename : usr/src/psm/stand/boot/i386/common/boot_ramdisk.c => deleted_files/usr/src/psm/stand/boot/i386/common/boot_ramdisk.c
rename : usr/src/psm/stand/boot/i386/common/bootenv.c => deleted_files/usr/src/psm/stand/boot/i386/common/bootenv.c
rename : usr/src/psm/stand/boot/i386/common/bootflags.c => deleted_files/usr/src/psm/stand/boot/i386/common/bootflags.c
rename : usr/src/psm/stand/boot/i386/common/bootops.c => deleted_files/usr/src/psm/stand/boot/i386/common/bootops.c
rename : usr/src/psm/stand/boot/i386/common/bootprop.c => deleted_files/usr/src/psm/stand/boot/i386/common/bootprop.c
rename : usr/src/psm/stand/boot/i386/common/bootprop.h => deleted_files/usr/src/psm/stand/boot/i386/common/bootprop.h
rename : usr/src/psm/stand/boot/i386/common/chario.h => deleted_files/usr/src/psm/stand/boot/i386/common/chario.h
rename : usr/src/psm/stand/boot/i386/common/check_iopath.c => deleted_files/usr/src/psm/stand/boot/i386/common/check_iopath.c
rename : usr/src/psm/stand/boot/i386/common/cpu_id.h => deleted_files/usr/src/psm/stand/boot/i386/common/cpu_id.h
rename : usr/src/psm/stand/boot/i386/common/debug.h => deleted_files/usr/src/psm/stand/boot/i386/common/debug.h
rename : usr/src/psm/stand/boot/i386/common/i86.il => deleted_files/usr/src/psm/stand/boot/i386/common/i86.il
rename : usr/src/psm/stand/boot/i386/common/machine.h => deleted_files/usr/src/psm/stand/boot/i386/common/machine.h
rename : usr/src/psm/stand/boot/i386/common/mapfile => deleted_files/usr/src/psm/stand/boot/i386/common/mapfile
rename : usr/src/psm/stand/boot/i386/common/memory.c => deleted_files/usr/src/psm/stand/boot/i386/common/memory.c
rename : usr/src/psm/stand/boot/i386/common/mkbin.c => deleted_files/usr/src/psm/stand/boot/i386/common/mkbin.c
rename : usr/src/psm/stand/boot/i386/common/multiboot.c => deleted_files/usr/src/psm/stand/boot/i386/common/multiboot.c
rename : usr/src/psm/stand/boot/i386/common/multiboot.h => deleted_files/usr/src/psm/stand/boot/i386/common/multiboot.h
rename : usr/src/psm/stand/boot/i386/common/standalloc.c => deleted_files/usr/src/psm/stand/boot/i386/common/standalloc.c
rename : usr/src/psm/stand/boot/i386/common/standalloc.h => deleted_files/usr/src/psm/stand/boot/i386/common/standalloc.h
rename : usr/src/psm/stand/boot/i386/common/util.h => deleted_files/usr/src/psm/stand/boot/i386/common/util.h
rename : usr/src/psm/stand/boot/i386/common/vgaprobe.c => deleted_files/usr/src/psm/stand/boot/i386/common/vgaprobe.c
rename : usr/src/psm/stand/boot/i386/i86pc/Makefile => deleted_files/usr/src/psm/stand/boot/i386/i86pc/Makefile
rename : usr/src/psm/stand/boot/i386/i86pc/asm.s => deleted_files/usr/src/psm/stand/boot/i386/i86pc/asm.s
rename : usr/src/psm/stand/boot/i386/i86pc/biosint.s => deleted_files/usr/src/psm/stand/boot/i386/i86pc/biosint.s
rename : usr/src/psm/stand/boot/i386/i86pc/cpu_id.s => deleted_files/usr/src/psm/stand/boot/i386/i86pc/cpu_id.s
rename : usr/src/psm/stand/boot/i386/i86pc/idttab.s => deleted_files/usr/src/psm/stand/boot/i386/i86pc/idttab.s
rename : usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s => deleted_files/usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s
rename : usr/src/uts/common/zmod/mapfile => deleted_files/usr/src/uts/common/zmod/mapfile
rename : usr/src/uts/intel/amd64/Makefile.rules => deleted_files/usr/src/uts/intel/amd64/Makefile.rules
rename : usr/src/uts/intel/ia32/Makefile.rules => deleted_files/usr/src/uts/intel/ia32/Makefile.rules
rename : usr/src/uts/intel/ia32/os/arch_kdi.c => deleted_files/usr/src/uts/intel/ia32/os/arch_kdi.c
rename : usr/src/uts/intel/ia32/sys/mmu.h => deleted_files/usr/src/uts/intel/ia32/sys/mmu.h
rename : usr/src/uts/intel/krtld/Makefile => deleted_files/usr/src/uts/intel/krtld/Makefile
rename : usr/src/uts/intel/sys/immu.h => deleted_files/usr/src/uts/intel/sys/immu.h
rename : usr/src/uts/intel/sys/mmu.h => deleted_files/usr/src/uts/intel/sys/mmu.h
rename : usr/src/uts/intel/zmod/Makefile => deleted_files/usr/src/uts/intel/zmod/Makefile
rename : usr/src/uts/sparc/zmod/Makefile => deleted_files/usr/src/uts/sparc/zmod/Makefile
rename : usr/src/cmd/eeprom/i386/common/benv.c => usr/src/cmd/eeprom/i386/benv.c
rename : usr/src/cmd/eeprom/i386/common/benv.h => usr/src/cmd/eeprom/i386/benv.h
rename : usr/src/cmd/eeprom/i386/common/benv_kvm.c => usr/src/cmd/eeprom/i386/benv_kvm.c
rename : usr/src/cmd/eeprom/common/loadlogo.c => usr/src/cmd/eeprom/sparc/loadlogo.c
rename : usr/src/cmd/eeprom/common/openprom.c => usr/src/cmd/eeprom/sparc/openprom.c
rename : usr/src/cmd/mdb/i86pc/modules/uppc/intr_common.c => usr/src/cmd/mdb/i86pc/modules/common/intr_common.c
rename : usr/src/cmd/mdb/i86pc/modules/uppc/intr_common.h => usr/src/cmd/mdb/i86pc/modules/common/intr_common.h
rename : usr/src/cmd/prtdiag/i386/i86pc/smbios.c => usr/src/cmd/prtdiag/i386/smbios.c
rename : usr/src/cmd/prtdiag/Makefile.targ => usr/src/cmd/prtdiag/sparc/Makefile.targ
rename : usr/src/psm/stand/boot/i386/common/console.c => usr/src/uts/i86pc/boot/boot_console.c
rename : usr/src/psm/stand/boot/i386/common/keyboard.c => usr/src/uts/i86pc/boot/boot_keyboard.c
rename : usr/src/psm/stand/boot/i386/common/keyboard_table.c => usr/src/uts/i86pc/boot/boot_keyboard_table.c
rename : usr/src/psm/stand/boot/i386/common/keyboard_table.h => usr/src/uts/i86pc/boot/boot_keyboard_table.h
rename : usr/src/psm/stand/boot/i386/common/serial.h => usr/src/uts/i86pc/boot/boot_serial.h
rename : usr/src/psm/stand/boot/i386/common/vga.c => usr/src/uts/i86pc/boot/boot_vga.c
rename : usr/src/psm/stand/boot/i386/common/vga.h => usr/src/uts/i86pc/boot/boot_vga.h
rename : usr/src/uts/intel/consconfig_dacf/Makefile => usr/src/uts/i86pc/consconfig_dacf/Makefile
rename : usr/src/uts/intel/io/consplat.c => usr/src/uts/i86pc/io/consplat.c
rename : usr/src/uts/common/io/pit.c => usr/src/uts/i86pc/io/hardclk.c
rename : usr/src/uts/common/io/hardclk.c => usr/src/uts/i86pc/io/todpc_subr.c
rename : usr/src/uts/i86pc/io/pcplusmp/apic.h => usr/src/uts/i86pc/sys/apic.h
rename : usr/src/psm/stand/boot/i386/common/console.h => usr/src/uts/i86pc/sys/boot_console.h
rename : usr/src/uts/i86pc/vm/mach_i86mmu.c => usr/src/uts/i86pc/vm/i86_mmu.c
rename : usr/src/uts/i86pc/acpica/Makefile => usr/src/uts/intel/acpica/Makefile
rename : usr/src/uts/i86pc/agpgart/Makefile => usr/src/uts/intel/agpgart/Makefile
rename : usr/src/uts/i86pc/agpmaster/Makefile => usr/src/uts/intel/agpmaster/Makefile
rename : usr/src/uts/i86pc/agptarget/Makefile => usr/src/uts/intel/agptarget/Makefile
rename : usr/src/uts/i86pc/amd64_gart/Makefile => usr/src/uts/intel/amd64_gart/Makefile
rename : usr/src/uts/i86pc/ata/Makefile => usr/src/uts/intel/ata/Makefile
rename : usr/src/uts/i86pc/audio810/Makefile => usr/src/uts/intel/audio810/Makefile
rename : usr/src/uts/i86pc/audiohd/Makefile => usr/src/uts/intel/audiohd/Makefile
rename : usr/src/uts/i86pc/audioixp/Makefile => usr/src/uts/intel/audioixp/Makefile
rename : usr/src/uts/i86pc/bootdev/Makefile => usr/src/uts/intel/bootdev/Makefile
rename : usr/src/uts/i86pc/dnet/Makefile => usr/src/uts/intel/dnet/Makefile
rename : usr/src/uts/i86pc/drm/Makefile => usr/src/uts/intel/drm/Makefile
rename : usr/src/uts/i86pc/fd/Makefile => usr/src/uts/intel/fd/Makefile
rename : usr/src/uts/i86pc/fdc/Makefile => usr/src/uts/intel/fdc/Makefile
rename : usr/src/uts/i86pc/i915/Makefile => usr/src/uts/intel/i915/Makefile
rename : usr/src/uts/i86pc/io/acpica/README.txt => usr/src/uts/intel/io/acpica/README.txt
rename : usr/src/uts/i86pc/io/acpica/acpi_enum.c => usr/src/uts/intel/io/acpica/acpi_enum.c
rename : usr/src/uts/i86pc/io/acpica/acpica.c => usr/src/uts/intel/io/acpica/acpica.c
rename : usr/src/uts/i86pc/io/acpica/acpica_ec.c => usr/src/uts/intel/io/acpica/acpica_ec.c
rename : usr/src/uts/i86pc/io/acpica/changes.txt => usr/src/uts/intel/io/acpica/changes.txt
rename : usr/src/uts/i86pc/io/acpica/cmp_ca.sh => usr/src/uts/intel/io/acpica/cmp_ca.sh
rename : usr/src/uts/i86pc/io/acpica/debugger/dbcmds.c => usr/src/uts/intel/io/acpica/debugger/dbcmds.c
rename : usr/src/uts/i86pc/io/acpica/debugger/dbdisply.c => usr/src/uts/intel/io/acpica/debugger/dbdisply.c
rename : usr/src/uts/i86pc/io/acpica/debugger/dbexec.c => usr/src/uts/intel/io/acpica/debugger/dbexec.c
rename : usr/src/uts/i86pc/io/acpica/debugger/dbfileio.c => usr/src/uts/intel/io/acpica/debugger/dbfileio.c
rename : usr/src/uts/i86pc/io/acpica/debugger/dbhistry.c => usr/src/uts/intel/io/acpica/debugger/dbhistry.c
rename : usr/src/uts/i86pc/io/acpica/debugger/dbinput.c => usr/src/uts/intel/io/acpica/debugger/dbinput.c
rename : usr/src/uts/i86pc/io/acpica/debugger/dbstats.c => usr/src/uts/intel/io/acpica/debugger/dbstats.c
rename : usr/src/uts/i86pc/io/acpica/debugger/dbutils.c => usr/src/uts/intel/io/acpica/debugger/dbutils.c
rename : usr/src/uts/i86pc/io/acpica/debugger/dbxface.c => usr/src/uts/intel/io/acpica/debugger/dbxface.c
rename : usr/src/uts/i86pc/io/acpica/disassembler/dmbuffer.c => usr/src/uts/intel/io/acpica/disassembler/dmbuffer.c
rename : usr/src/uts/i86pc/io/acpica/disassembler/dmnames.c => usr/src/uts/intel/io/acpica/disassembler/dmnames.c
rename : usr/src/uts/i86pc/io/acpica/disassembler/dmobject.c => usr/src/uts/intel/io/acpica/disassembler/dmobject.c
rename : usr/src/uts/i86pc/io/acpica/disassembler/dmopcode.c => usr/src/uts/intel/io/acpica/disassembler/dmopcode.c
rename : usr/src/uts/i86pc/io/acpica/disassembler/dmresrc.c => usr/src/uts/intel/io/acpica/disassembler/dmresrc.c
rename : usr/src/uts/i86pc/io/acpica/disassembler/dmresrcl.c => usr/src/uts/intel/io/acpica/disassembler/dmresrcl.c
rename : usr/src/uts/i86pc/io/acpica/disassembler/dmresrcs.c => usr/src/uts/intel/io/acpica/disassembler/dmresrcs.c
rename : usr/src/uts/i86pc/io/acpica/disassembler/dmutils.c => usr/src/uts/intel/io/acpica/disassembler/dmutils.c
rename : usr/src/uts/i86pc/io/acpica/disassembler/dmwalk.c => usr/src/uts/intel/io/acpica/disassembler/dmwalk.c
rename : usr/src/uts/i86pc/io/acpica/events/evevent.c => usr/src/uts/intel/io/acpica/events/evevent.c
rename : usr/src/uts/i86pc/io/acpica/events/evgpe.c => usr/src/uts/intel/io/acpica/events/evgpe.c
rename : usr/src/uts/i86pc/io/acpica/events/evgpeblk.c => usr/src/uts/intel/io/acpica/events/evgpeblk.c
rename : usr/src/uts/i86pc/io/acpica/events/evmisc.c => usr/src/uts/intel/io/acpica/events/evmisc.c
rename : usr/src/uts/i86pc/io/acpica/events/evregion.c => usr/src/uts/intel/io/acpica/events/evregion.c
rename : usr/src/uts/i86pc/io/acpica/events/evrgnini.c => usr/src/uts/intel/io/acpica/events/evrgnini.c
rename : usr/src/uts/i86pc/io/acpica/events/evsci.c => usr/src/uts/intel/io/acpica/events/evsci.c
rename : usr/src/uts/i86pc/io/acpica/events/evxface.c => usr/src/uts/intel/io/acpica/events/evxface.c
rename : usr/src/uts/i86pc/io/acpica/events/evxfevnt.c => usr/src/uts/intel/io/acpica/events/evxfevnt.c
rename : usr/src/uts/i86pc/io/acpica/events/evxfregn.c => usr/src/uts/intel/io/acpica/events/evxfregn.c
rename : usr/src/uts/i86pc/io/acpica/hardware/hwacpi.c => usr/src/uts/intel/io/acpica/hardware/hwacpi.c
rename : usr/src/uts/i86pc/io/acpica/hardware/hwgpe.c => usr/src/uts/intel/io/acpica/hardware/hwgpe.c
rename : usr/src/uts/i86pc/io/acpica/hardware/hwregs.c => usr/src/uts/intel/io/acpica/hardware/hwregs.c
rename : usr/src/uts/i86pc/io/acpica/hardware/hwsleep.c => usr/src/uts/intel/io/acpica/hardware/hwsleep.c
rename : usr/src/uts/i86pc/io/acpica/hardware/hwtimer.c => usr/src/uts/intel/io/acpica/hardware/hwtimer.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsfield.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsfield.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsinit.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsinit.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsmethod.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsmethod.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsmthdat.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsmthdat.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsobject.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsobject.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsopcode.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsopcode.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsutils.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsutils.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswexec.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswexec.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswload.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswload.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswscope.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswscope.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswstate.c => usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswstate.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exconfig.c => usr/src/uts/intel/io/acpica/interpreter/executer/exconfig.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exconvrt.c => usr/src/uts/intel/io/acpica/interpreter/executer/exconvrt.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/excreate.c => usr/src/uts/intel/io/acpica/interpreter/executer/excreate.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exdump.c => usr/src/uts/intel/io/acpica/interpreter/executer/exdump.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exfield.c => usr/src/uts/intel/io/acpica/interpreter/executer/exfield.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exfldio.c => usr/src/uts/intel/io/acpica/interpreter/executer/exfldio.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exmisc.c => usr/src/uts/intel/io/acpica/interpreter/executer/exmisc.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exmutex.c => usr/src/uts/intel/io/acpica/interpreter/executer/exmutex.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exnames.c => usr/src/uts/intel/io/acpica/interpreter/executer/exnames.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg1.c => usr/src/uts/intel/io/acpica/interpreter/executer/exoparg1.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg2.c => usr/src/uts/intel/io/acpica/interpreter/executer/exoparg2.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg3.c => usr/src/uts/intel/io/acpica/interpreter/executer/exoparg3.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg6.c => usr/src/uts/intel/io/acpica/interpreter/executer/exoparg6.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exprep.c => usr/src/uts/intel/io/acpica/interpreter/executer/exprep.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exregion.c => usr/src/uts/intel/io/acpica/interpreter/executer/exregion.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exresnte.c => usr/src/uts/intel/io/acpica/interpreter/executer/exresnte.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exresolv.c => usr/src/uts/intel/io/acpica/interpreter/executer/exresolv.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exresop.c => usr/src/uts/intel/io/acpica/interpreter/executer/exresop.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exstore.c => usr/src/uts/intel/io/acpica/interpreter/executer/exstore.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exstoren.c => usr/src/uts/intel/io/acpica/interpreter/executer/exstoren.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exstorob.c => usr/src/uts/intel/io/acpica/interpreter/executer/exstorob.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exsystem.c => usr/src/uts/intel/io/acpica/interpreter/executer/exsystem.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/executer/exutils.c => usr/src/uts/intel/io/acpica/interpreter/executer/exutils.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/psargs.c => usr/src/uts/intel/io/acpica/interpreter/parser/psargs.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/psloop.c => usr/src/uts/intel/io/acpica/interpreter/parser/psloop.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/psopcode.c => usr/src/uts/intel/io/acpica/interpreter/parser/psopcode.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/psparse.c => usr/src/uts/intel/io/acpica/interpreter/parser/psparse.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/psscope.c => usr/src/uts/intel/io/acpica/interpreter/parser/psscope.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/pstree.c => usr/src/uts/intel/io/acpica/interpreter/parser/pstree.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/psutils.c => usr/src/uts/intel/io/acpica/interpreter/parser/psutils.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/pswalk.c => usr/src/uts/intel/io/acpica/interpreter/parser/pswalk.c
rename : usr/src/uts/i86pc/io/acpica/interpreter/parser/psxface.c => usr/src/uts/intel/io/acpica/interpreter/parser/psxface.c
rename : usr/src/uts/i86pc/io/acpica/master_ops.c => usr/src/uts/intel/io/acpica/master_ops.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nsaccess.c => usr/src/uts/intel/io/acpica/namespace/nsaccess.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nsalloc.c => usr/src/uts/intel/io/acpica/namespace/nsalloc.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nsdump.c => usr/src/uts/intel/io/acpica/namespace/nsdump.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nsdumpdv.c => usr/src/uts/intel/io/acpica/namespace/nsdumpdv.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nseval.c => usr/src/uts/intel/io/acpica/namespace/nseval.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nsinit.c => usr/src/uts/intel/io/acpica/namespace/nsinit.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nsload.c => usr/src/uts/intel/io/acpica/namespace/nsload.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nsnames.c => usr/src/uts/intel/io/acpica/namespace/nsnames.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nsobject.c => usr/src/uts/intel/io/acpica/namespace/nsobject.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nsparse.c => usr/src/uts/intel/io/acpica/namespace/nsparse.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nssearch.c => usr/src/uts/intel/io/acpica/namespace/nssearch.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nsutils.c => usr/src/uts/intel/io/acpica/namespace/nsutils.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nswalk.c => usr/src/uts/intel/io/acpica/namespace/nswalk.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nsxfeval.c => usr/src/uts/intel/io/acpica/namespace/nsxfeval.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nsxfname.c => usr/src/uts/intel/io/acpica/namespace/nsxfname.c
rename : usr/src/uts/i86pc/io/acpica/namespace/nsxfobj.c => usr/src/uts/intel/io/acpica/namespace/nsxfobj.c
rename : usr/src/uts/i86pc/io/acpica/osl.c => usr/src/uts/intel/io/acpica/osl.c
rename : usr/src/uts/i86pc/io/acpica/osl_ml.s => usr/src/uts/intel/io/acpica/osl_ml.s
rename : usr/src/uts/i86pc/io/acpica/resources/rsaddr.c => usr/src/uts/intel/io/acpica/resources/rsaddr.c
rename : usr/src/uts/i86pc/io/acpica/resources/rscalc.c => usr/src/uts/intel/io/acpica/resources/rscalc.c
rename : usr/src/uts/i86pc/io/acpica/resources/rscreate.c => usr/src/uts/intel/io/acpica/resources/rscreate.c
rename : usr/src/uts/i86pc/io/acpica/resources/rsdump.c => usr/src/uts/intel/io/acpica/resources/rsdump.c
rename : usr/src/uts/i86pc/io/acpica/resources/rsinfo.c => usr/src/uts/intel/io/acpica/resources/rsinfo.c
rename : usr/src/uts/i86pc/io/acpica/resources/rsio.c => usr/src/uts/intel/io/acpica/resources/rsio.c
rename : usr/src/uts/i86pc/io/acpica/resources/rsirq.c => usr/src/uts/intel/io/acpica/resources/rsirq.c
rename : usr/src/uts/i86pc/io/acpica/resources/rslist.c => usr/src/uts/intel/io/acpica/resources/rslist.c
rename : usr/src/uts/i86pc/io/acpica/resources/rsmemory.c => usr/src/uts/intel/io/acpica/resources/rsmemory.c
rename : usr/src/uts/i86pc/io/acpica/resources/rsmisc.c => usr/src/uts/intel/io/acpica/resources/rsmisc.c
rename : usr/src/uts/i86pc/io/acpica/resources/rsutils.c => usr/src/uts/intel/io/acpica/resources/rsutils.c
rename : usr/src/uts/i86pc/io/acpica/resources/rsxface.c => usr/src/uts/intel/io/acpica/resources/rsxface.c
rename : usr/src/uts/i86pc/io/acpica/tables/tbconvrt.c => usr/src/uts/intel/io/acpica/tables/tbconvrt.c
rename : usr/src/uts/i86pc/io/acpica/tables/tbget.c => usr/src/uts/intel/io/acpica/tables/tbget.c
rename : usr/src/uts/i86pc/io/acpica/tables/tbgetall.c => usr/src/uts/intel/io/acpica/tables/tbgetall.c
rename : usr/src/uts/i86pc/io/acpica/tables/tbinstal.c => usr/src/uts/intel/io/acpica/tables/tbinstal.c
rename : usr/src/uts/i86pc/io/acpica/tables/tbrsdt.c => usr/src/uts/intel/io/acpica/tables/tbrsdt.c
rename : usr/src/uts/i86pc/io/acpica/tables/tbutils.c => usr/src/uts/intel/io/acpica/tables/tbutils.c
rename : usr/src/uts/i86pc/io/acpica/tables/tbxface.c => usr/src/uts/intel/io/acpica/tables/tbxface.c
rename : usr/src/uts/i86pc/io/acpica/tables/tbxfroot.c => usr/src/uts/intel/io/acpica/tables/tbxfroot.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utalloc.c => usr/src/uts/intel/io/acpica/utilities/utalloc.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utcache.c => usr/src/uts/intel/io/acpica/utilities/utcache.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utclib.c => usr/src/uts/intel/io/acpica/utilities/utclib.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utcopy.c => usr/src/uts/intel/io/acpica/utilities/utcopy.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utdebug.c => usr/src/uts/intel/io/acpica/utilities/utdebug.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utdelete.c => usr/src/uts/intel/io/acpica/utilities/utdelete.c
rename : usr/src/uts/i86pc/io/acpica/utilities/uteval.c => usr/src/uts/intel/io/acpica/utilities/uteval.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utglobal.c => usr/src/uts/intel/io/acpica/utilities/utglobal.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utinit.c => usr/src/uts/intel/io/acpica/utilities/utinit.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utmath.c => usr/src/uts/intel/io/acpica/utilities/utmath.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utmisc.c => usr/src/uts/intel/io/acpica/utilities/utmisc.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utmutex.c => usr/src/uts/intel/io/acpica/utilities/utmutex.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utobject.c => usr/src/uts/intel/io/acpica/utilities/utobject.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utresrc.c => usr/src/uts/intel/io/acpica/utilities/utresrc.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utstate.c => usr/src/uts/intel/io/acpica/utilities/utstate.c
rename : usr/src/uts/i86pc/io/acpica/utilities/uttrack.c => usr/src/uts/intel/io/acpica/utilities/uttrack.c
rename : usr/src/uts/i86pc/io/acpica/utilities/utxface.c => usr/src/uts/intel/io/acpica/utilities/utxface.c
rename : usr/src/uts/i86pc/io/agpgart/agp_kstat.c => usr/src/uts/intel/io/agpgart/agp_kstat.c
rename : usr/src/uts/i86pc/io/agpgart/agpgart.c => usr/src/uts/intel/io/agpgart/agpgart.c
rename : usr/src/uts/i86pc/io/agpgart/agpgart.conf => usr/src/uts/intel/io/agpgart/agpgart.conf
rename : usr/src/uts/i86pc/io/agpgart/agptarget.c => usr/src/uts/intel/io/agpgart/agptarget.c
rename : usr/src/uts/i86pc/io/agpgart/amd64_gart.c => usr/src/uts/intel/io/agpgart/amd64_gart.c
rename : usr/src/uts/i86pc/io/agpmaster/agpmaster.c => usr/src/uts/intel/io/agpmaster/agpmaster.c
rename : usr/src/uts/i86pc/io/dnet.c => usr/src/uts/intel/io/dnet.c
rename : usr/src/uts/i86pc/io/dnet.conf => usr/src/uts/intel/io/dnet.conf
rename : usr/src/uts/i86pc/io/drm/drm_asm.s => usr/src/uts/intel/io/drm/drm_asm.s
rename : usr/src/uts/i86pc/io/drm/i915_dma.c => usr/src/uts/intel/io/drm/i915_dma.c
rename : usr/src/uts/i86pc/io/drm/i915_drm.h => usr/src/uts/intel/io/drm/i915_drm.h
rename : usr/src/uts/i86pc/io/drm/i915_drv.c => usr/src/uts/intel/io/drm/i915_drv.c
rename : usr/src/uts/i86pc/io/drm/i915_drv.h => usr/src/uts/intel/io/drm/i915_drv.h
rename : usr/src/uts/i86pc/io/drm/i915_irq.c => usr/src/uts/intel/io/drm/i915_irq.c
rename : usr/src/uts/i86pc/io/drm/i915_mem.c => usr/src/uts/intel/io/drm/i915_mem.c
rename : usr/src/uts/i86pc/io/drm/i915_sundrv.c => usr/src/uts/intel/io/drm/i915_sundrv.c
rename : usr/src/uts/i86pc/io/fd.conf => usr/src/uts/intel/io/fd.conf
rename : usr/src/uts/common/io/i8254.c => usr/src/uts/intel/io/i8254.c
rename : usr/src/uts/i86pc/io/logi.c => usr/src/uts/intel/io/logi.c
rename : usr/src/uts/i86pc/io/mii.c => usr/src/uts/intel/io/mii.c
rename : usr/src/uts/i86pc/io/mscsi.c => usr/src/uts/intel/io/mscsi.c
rename : usr/src/uts/i86pc/io/mscsi.conf => usr/src/uts/intel/io/mscsi.conf
rename : usr/src/uts/i86pc/io/msm.c => usr/src/uts/intel/io/msm.c
rename : usr/src/uts/i86pc/io/pci/mps_table.h => usr/src/uts/intel/io/pci/mps_table.h
rename : usr/src/uts/i86pc/io/pci/pci_autoconfig.c => usr/src/uts/intel/io/pci/pci_autoconfig.c
rename : usr/src/uts/i86pc/io/pci/pci_boot.c => usr/src/uts/intel/io/pci/pci_boot.c
rename : usr/src/uts/i86pc/io/pci/pci_memlist.c => usr/src/uts/intel/io/pci/pci_memlist.c
rename : usr/src/uts/i86pc/io/pci/pci_pci.c => usr/src/uts/intel/io/pci/pci_pci.c
rename : usr/src/uts/i86pc/io/pci/pci_resource.c => usr/src/uts/intel/io/pci/pci_resource.c
rename : usr/src/uts/i86pc/io/pci/pcihrt.h => usr/src/uts/intel/io/pci/pcihrt.h
rename : usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_acpi.c => usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_acpi.c
rename : usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_acpi.h => usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_acpi.h
rename : usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_nvidia.c => usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_nvidia.c
rename : usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_nvidia.h => usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_nvidia.h
rename : usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_x86.c => usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_x86.c
rename : usr/src/uts/i86pc/io/pciex/pcie_error.c => usr/src/uts/intel/io/pciex/pcie_error.c
rename : usr/src/uts/i86pc/io/pciex/pcie_error.h => usr/src/uts/intel/io/pciex/pcie_error.h
rename : usr/src/uts/i86pc/io/pciex/pcie_nvidia.c => usr/src/uts/intel/io/pciex/pcie_nvidia.c
rename : usr/src/uts/i86pc/io/pciex/pcie_nvidia.h => usr/src/uts/intel/io/pciex/pcie_nvidia.h
rename : usr/src/uts/i86pc/io/pciex/pcie_pci.c => usr/src/uts/intel/io/pciex/pcie_pci.c
rename : usr/src/uts/i86pc/io/pciex/pcie_pci.conf => usr/src/uts/intel/io/pciex/pcie_pci.conf
rename : usr/src/uts/i86pc/io/smcp/smcp.c => usr/src/uts/intel/io/smcp/smcp.c
rename : usr/src/uts/i86pc/io/smcp/smcp.h => usr/src/uts/intel/io/smcp/smcp.h
rename : usr/src/uts/i86pc/kb8042/Makefile => usr/src/uts/intel/kb8042/Makefile
rename : usr/src/cmd/mdb/intel/amd64/kmdb/kaif_startup.s => usr/src/uts/intel/kdi/amd64/kdi_asm.s
rename : usr/src/cmd/mdb/intel/ia32/kmdb/kaif_startup.s => usr/src/uts/intel/kdi/ia32/kdi_asm.s
rename : usr/src/cmd/mdb/intel/kmdb/kaif_idt.c => usr/src/uts/intel/kdi/kdi_idt.c
rename : usr/src/cmd/mdb/intel/kmdb/kaif_idthdl.s => usr/src/uts/intel/kdi/kdi_idthdl.s
rename : usr/src/cmd/mdb/intel/kmdb/kaif_off.in => usr/src/uts/intel/kdi/kdi_offsets.in
rename : usr/src/uts/i86pc/logi/Makefile => usr/src/uts/intel/logi/Makefile
rename : usr/src/uts/i86pc/mscsi/Makefile => usr/src/uts/intel/mscsi/Makefile
rename : usr/src/uts/i86pc/msm/Makefile => usr/src/uts/intel/msm/Makefile
rename : usr/src/uts/i86pc/pci_autoconfig/Makefile => usr/src/uts/intel/pci_autoconfig/Makefile
rename : usr/src/uts/i86pc/pci_pci/Makefile => usr/src/uts/intel/pci_pci/Makefile
rename : usr/src/uts/i86pc/pcic/Makefile => usr/src/uts/intel/pcic/Makefile
rename : usr/src/uts/i86pc/pcie_pci/Makefile => usr/src/uts/intel/pcie_pci/Makefile
rename : usr/src/uts/i86pc/pciehpc/Makefile => usr/src/uts/intel/pciehpc/Makefile
rename : usr/src/uts/i86pc/power/Makefile => usr/src/uts/intel/power/Makefile
rename : usr/src/cmd/mdb/intel/kmdb/kaif_regs.h => usr/src/uts/intel/sys/kdi_regs.h
rename : usr/src/uts/i86pc/sys/pmem.h => usr/src/uts/intel/sys/pmem.h
rename : usr/src/uts/i86pc/vuid2ps2/Makefile => usr/src/uts/intel/vuid2ps2/Makefile
rename : usr/src/uts/i86pc/vuid3ps2/Makefile => usr/src/uts/intel/vuid3ps2/Makefile
rename : usr/src/uts/i86pc/vuidm3p/Makefile => usr/src/uts/intel/vuidm3p/Makefile
rename : usr/src/uts/i86pc/vuidm4p/Makefile => usr/src/uts/intel/vuidm4p/Makefile
rename : usr/src/uts/i86pc/vuidm5p/Makefile => usr/src/uts/intel/vuidm5p/Makefile
Diffstat (limited to 'usr/src')
766 files changed, 30785 insertions, 34824 deletions
diff --git a/usr/src/Makefile.master b/usr/src/Makefile.master index e43a36e3b7..a433e01aa7 100644 --- a/usr/src/Makefile.master +++ b/usr/src/Makefile.master @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -132,6 +132,8 @@ SFWLIBDIR64= $(SFW_ROOT)/lib/$(MACH64) RPCGEN= /usr/bin/rpcgen STABS= $(ONBLD_TOOLS)/bin/$(MACH)/stabs +ELFEXTRACT= $(ONBLD_TOOLS)/bin/$(MACH)/elfextract +MBH_PATCH= $(ONBLD_TOOLS)/bin/$(MACH)/mbh_patch ECHO= echo INS= install TRUE= true diff --git a/usr/src/Makefile.psm b/usr/src/Makefile.psm index 7528b5af60..dfcb70c8eb 100644 --- a/usr/src/Makefile.psm +++ b/usr/src/Makefile.psm @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -180,6 +179,8 @@ ROOT_US3_CRYPTO_DIR_64 = $(ROOT_US3_MOD_DIR)/crypto/$(SUBDIR64) ROOT_US3_CRYPTO_DIR = $(ROOT_US3_CRYPTO_DIR_$(CLASS)) ROOT_US3_CRYPTO_LINK = $(ROOT_US3_CRYPTO_DIR_64:$(ROOT_PLAT_DIR)%=../../../..%) +ROOT_BOOT_PSM_KERN_DIR = $(ROOT)/boot/platform/$(PLATFORM)/kernel + # # The following are for the installation of objects in PSM directories. # diff --git a/usr/src/Makefile.psm.targ b/usr/src/Makefile.psm.targ index 5c70a081ef..fce4f698e0 100644 --- a/usr/src/Makefile.psm.targ +++ b/usr/src/Makefile.psm.targ @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -36,6 +35,9 @@ $(ROOT_PLAT_DIR) $(USR_PLAT_DIR): $(ROOT_PSM_DIR): $(ROOT_PLAT_DIR) -$(INS.dir.root.sys) +$(ROOT_BOOT_PSM_KERN_DIR): + -$(INS.dir.root.sys) + $(ROOT_PSM_LIB_DIR) \ $(ROOT_PSM_SBIN_DIR): $(ROOT_PSM_DIR) -$(INS.dir.root.sys) diff --git a/usr/src/Targetdirs b/usr/src/Targetdirs index bba9d08d16..0872287d8a 100644 --- a/usr/src/Targetdirs +++ b/usr/src/Targetdirs @@ -54,7 +54,8 @@ i386_ROOT.SYS= \ /boot/grub \ /boot/grub/bin \ /boot/solaris \ - /boot/solaris/bin + /boot/solaris/bin \ + /platform/i86pc sparc_ROOT.SYS= @@ -173,7 +174,6 @@ ROOT.SYS= \ /var/svc/manifest/application/security \ /var/svc/manifest/application/print \ /var/svc/manifest/platform \ - /var/svc/manifest/platform/i86pc \ /var/svc/manifest/platform/sun4u \ /var/svc/manifest/platform/sun4v \ /var/svc/manifest/site \ @@ -320,7 +320,8 @@ sparcv9_ROOT.BIN64= \ /usr/platform/sun4u-us3/lib \ /usr/platform/sun4u-opl/lib -amd64_ROOT.BIN64= +amd64_ROOT.BIN64= \ + /platform/i86pc/amd64 ROOT.BIN64= \ $($(MACH64)_ROOT.BIN64) \ diff --git a/usr/src/cmd/Makefile.cmd b/usr/src/cmd/Makefile.cmd index 791f10dbbd..4730cb6506 100644 --- a/usr/src/cmd/Makefile.cmd +++ b/usr/src/cmd/Makefile.cmd @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -208,7 +208,6 @@ ROOTSVCNETWORKSECURITY= $(ROOTSVCNETWORK)/security ROOTSVCNETWORKSSL= $(ROOTSVCNETWORK)/ssl ROOTSVCNETWORKSHARES= $(ROOTSVCNETWORK)/shares ROOTSVCPLATFORM= $(ROOTVARSVCMANIFEST)/platform -ROOTSVCPLATFORMI86PC= $(ROOTSVCPLATFORM)/i86pc ROOTSVCPLATFORMSUN4U= $(ROOTSVCPLATFORM)/sun4u ROOTSVCPLATFORMSUN4V= $(ROOTSVCPLATFORM)/sun4v ROOTSVCAPPLICATION= $(ROOTVARSVCMANIFEST)/application @@ -385,9 +384,6 @@ $(ROOTSVCAPPLICATIONPRINT)/%: % $(ROOTSVCPLATFORM)/%: % $(INS.file) -$(ROOTSVCPLATFORMI86PC)/%: % - $(INS.file) - $(ROOTSVCPLATFORMSUN4U)/%: % $(INS.file) diff --git a/usr/src/cmd/boot/Makefile b/usr/src/cmd/boot/Makefile index a1dcfd5a18..51b1ebf3d8 100644 --- a/usr/src/cmd/boot/Makefile +++ b/usr/src/cmd/boot/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -35,7 +35,8 @@ COMMON_SUBDIRS= \ i386_SUBDIRS= \ installgrub \ - mbr + mbr \ + symdef sparc_SUBDIRS= @@ -43,7 +44,8 @@ COMMON_LINTSUBDIRS= \ bootadm i386_LINTSUBDIRS= \ - installgrub + installgrub \ + symdef sparc_LINTSUBDIRS= diff --git a/usr/src/cmd/boot/bootadm/Makefile b/usr/src/cmd/boot/bootadm/Makefile index a71f5bf32a..fc4a370cef 100644 --- a/usr/src/cmd/boot/bootadm/Makefile +++ b/usr/src/cmd/boot/bootadm/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -31,7 +31,7 @@ i386_DATA= filelist.ramdisk filelist.safe SBINLINKS= $(PROG) -OBJS = bootadm.o +OBJS= bootadm.o bootadm_upgrade.o SRCS = $(OBJS:.o=.c) include ../Makefile.com @@ -52,9 +52,13 @@ LDLIBS += -lnvpair CFLAGS += $(XSTRCONST) CPPFLAGS += -D_FILE_OFFSET_BITS=64 +# Add paths to pick up headers +CFLAGS += -I../../../uts/common +LINTFLAGS += -I../../../uts/common + all: $(PROG) -$(PROG): $(OBJS) +$(PROG): $(OBJS) bootadm.h $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(POST_PROCESS) @@ -64,9 +68,10 @@ $(ROOTUSRSBINLINKS): install: all $(ROOTSBINPROG) $(ROOTBOOTSOLARISDATA) .WAIT $(ROOTUSRSBINLINKS) clean: + -$(RM) $(OBJS) _msg: -lint: lint_PROG +lint: lint_SRCS include ../Makefile.targ diff --git a/usr/src/cmd/boot/bootadm/bootadm.c b/usr/src/cmd/boot/bootadm/bootadm.c index 80c2b75592..2475aba1d3 100644 --- a/usr/src/cmd/boot/bootadm/bootadm.c +++ b/usr/src/cmd/boot/bootadm/bootadm.c @@ -58,12 +58,12 @@ #include <grp.h> #include <device_info.h> -#include <libintl.h> #include <locale.h> #include <assert.h> #include "message.h" +#include "bootadm.h" #ifndef TEXT_DOMAIN #define TEXT_DOMAIN "SUNW_OST_OSCMD" @@ -77,56 +77,12 @@ typedef enum { BAM_ARCHIVE } subcmd_t; -/* GRUB menu per-line classification */ -typedef enum { - BAM_INVALID = 0, - BAM_EMPTY, - BAM_COMMENT, - BAM_GLOBAL, - BAM_ENTRY, - BAM_TITLE -} menu_flag_t; - -/* struct for menu.lst contents */ -typedef struct line { - int lineNum; /* Line number in menu.lst */ - int entryNum; /* menu boot entry #. ENTRY_INIT if not applicable */ - char *cmd; - char *sep; - char *arg; - char *line; - menu_flag_t flags; - struct line *next; - struct line *prev; -} line_t; - -typedef struct entry { - struct entry *next; - struct entry *prev; - line_t *start; - line_t *end; -} entry_t; - -typedef struct { - line_t *start; - line_t *end; - line_t *curdefault; /* line containing default */ - line_t *olddefault; /* old default line (commented) */ - entry_t *entries; /* os entries */ -} menu_t; - typedef enum { OPT_ABSENT = 0, /* No option */ OPT_REQ, /* option required */ OPT_OPTIONAL /* option may or may not be present */ } option_t; -typedef enum { - BAM_ERROR = -1, /* Must be negative. add_boot_entry() depends on it */ - BAM_SUCCESS = 0, - BAM_WRITE = 2 -} error_t; - typedef struct { char *subcmd; option_t option; @@ -134,16 +90,11 @@ typedef struct { int unpriv; /* is this an unprivileged command */ } subcmd_defn_t; - -#define BAM_MAXLINE 8192 - #define LINE_INIT 0 /* lineNum initial value */ #define ENTRY_INIT -1 /* entryNum initial value */ #define ALL_ENTRIES -2 /* selects all boot entries */ #define GRUB_DIR "/boot/grub" -#define MULTI_BOOT "/platform/i86pc/multiboot" -#define BOOT_ARCHIVE "/platform/i86pc/boot_archive" #define GRUB_MENU "/boot/grub/menu.lst" #define MENU_TMP "/boot/grub/menu.lst.tmp" #define RAMDISK_SPECIAL "/ramdisk" @@ -180,26 +131,19 @@ typedef struct { * Menu related * menu_cmd_t and menu_cmds must be kept in sync */ -typedef enum { - DEFAULT_CMD = 0, - TIMEOUT_CMD, - TITLE_CMD, - ROOT_CMD, - KERNEL_CMD, - MODULE_CMD, - SEP_CMD, - COMMENT_CMD -} menu_cmd_t; - -static char *menu_cmds[] = { +char *menu_cmds[] = { "default", /* DEFAULT_CMD */ "timeout", /* TIMEOUT_CMD */ "title", /* TITLE_CMD */ "root", /* ROOT_CMD */ "kernel", /* KERNEL_CMD */ + "kernel$", /* KERNEL_DOLLAR_CMD */ "module", /* MODULE_CMD */ + "module$", /* MODULE_DOLLAR_CMD */ " ", /* SEP_CMD */ "#", /* COMMENT_CMD */ + "chainloader", /* CHAINLOADER_CMD */ + "args", /* ARGS_CMD */ NULL }; @@ -221,11 +165,9 @@ typedef struct { #define DIR_PERMS (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) #define FILE_STAT_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) -#define BAM_HDR "---------- ADDED BY BOOTADM - DO NOT EDIT ----------" -#define BAM_FTR "---------------------END BOOTADM--------------------" -#define BAM_OLDDEF "BOOTADM SAVED DEFAULT: " - /* Globals */ +int bam_verbose; +int bam_force; static char *prog; static subcmd_t bam_cmd; static char *bam_root; @@ -237,8 +179,6 @@ static char *bam_opt; static int bam_debug; static char **bam_argv; static int bam_argc; -static int bam_force; -static int bam_verbose; static int bam_check; static int bam_smf_check; static int bam_lock_fd = -1; @@ -251,7 +191,6 @@ static void parse_args(int argc, char *argv[]); static error_t bam_menu(char *subcmd, char *opt, int argc, char *argv[]); static error_t bam_archive(char *subcmd, char *opt); -static void bam_error(char *format, ...); static void bam_print(char *format, ...); static void bam_exit(int excode); static void bam_lock(void); @@ -280,12 +219,13 @@ static error_t update_all(char *root, char *opt); static error_t read_list(char *root, filelist_t *flistp); static error_t set_global(menu_t *mp, char *globalcmd, int val); static error_t set_option(menu_t *mp, char *globalcmd, char *opt); +static error_t set_kernel(menu_t *mp, menu_cmd_t optnum, char *path, + char *buf, size_t bufsize); +static char *expand_path(const char *partial_path); static long s_strtol(char *str); -static char *s_fgets(char *buf, int n, FILE *fp); static int s_fputs(char *str, FILE *fp); -static void *s_calloc(size_t nelem, size_t sz); static char *s_strdup(char *str); static int is_readonly(char *); static int is_amd64(void); @@ -302,6 +242,7 @@ static subcmd_defn_t menu_subcmds[] = { "delete_all_entries", OPT_ABSENT, delete_all_entries, 0, /* PVT */ "update_entry", OPT_REQ, update_entry, 0, /* menu */ "update_temp", OPT_OPTIONAL, update_temp, 0, /* reboot */ + "upgrade", OPT_ABSENT, upgrade_menu, 0, /* menu */ NULL, 0, NULL, 0 /* must be last */ }; @@ -325,7 +266,7 @@ struct safefile { struct safefile *next; }; -struct safefile *safefiles = NULL; +static struct safefile *safefiles = NULL; #define NEED_UPDATE_FILE "/etc/svc/volatile/boot_archive_needs_update" static void @@ -487,7 +428,7 @@ parse_args_internal(int argc, char *argv[]) opterr = 0; error = 0; - while ((c = getopt(argc, argv, "a:d:fm:no:vCR:")) != -1) { + while ((c = getopt(argc, argv, "a:d:fm:no:vCR:xX")) != -1) { switch (c) { case 'a': if (bam_cmd) { @@ -942,6 +883,7 @@ bam_menu(char *subcmd, char *opt, int largc, char *largv[]) { error_t ret; char menu_path[PATH_MAX]; + char path[PATH_MAX]; menu_t *menu; char *mntpt, *menu_root, *logslice, *fstype; struct stat sb; @@ -961,17 +903,26 @@ bam_menu(char *subcmd, char *opt, int largc, char *largv[]) logslice = fstype = NULL; /* - * If the user provides an alternate root, we - * assume they know what they are doing and we - * use it. Else we check if there is an - * alternate location (other than /boot/grub) - * for the GRUB menu + * Check for the menu.list file: + * + * 1. Check for a GRUB_slice file, be it on / or + * on the user-provided alternate root. + * 2. Use the alternate root, if given. + * 3. Check /stubboot + * 4. Use / */ if (bam_alt_root) { - menu_root = bam_root; - } else if (stat(GRUB_slice, &sb) == 0) { + (void) snprintf(path, sizeof (path), "%s%s", bam_root, + GRUB_slice); + } else { + (void) snprintf(path, sizeof (path), "%s", GRUB_slice); + } + + if (stat(path, &sb) == 0) { mntpt = mount_grub_slice(&mnted, NULL, &logslice, &fstype); menu_root = mntpt; + } else if (bam_alt_root) { + menu_root = bam_root; } else if (stat(STUBBOOT, &sb) == 0) { menu_root = use_stubboot(); } else { @@ -1015,11 +966,16 @@ bam_menu(char *subcmd, char *opt, int largc, char *largv[]) return (BAM_ERROR); } + ret = dboot_or_multiboot(bam_root); + if (ret != BAM_SUCCESS) + return (ret); + /* * Once the sub-cmd handler has run * only the line field is guaranteed to have valid values */ - if (strcmp(subcmd, "update_entry") == 0) + if ((strcmp(subcmd, "update_entry") == 0) || + (strcmp(subcmd, "upgrade") == 0)) ret = f(menu, bam_root, opt); else ret = f(menu, menu_path, opt); @@ -1068,6 +1024,10 @@ bam_archive( sparc_abort(); #endif + ret = dboot_or_multiboot(rootbuf); + if (ret != BAM_SUCCESS) + return (ret); + /* * Check archive not supported with update_all * since it is awkward to display out-of-sync @@ -1089,7 +1049,7 @@ bam_archive( } /*PRINTFLIKE1*/ -static void +void bam_error(char *format, ...) { va_list ap; @@ -1111,6 +1071,17 @@ bam_print(char *format, ...) va_end(ap); } +/*PRINTFLIKE1*/ +void +bam_print_stderr(char *format, ...) +{ + va_list ap; + + va_start(ap, format); + (void) vfprintf(stderr, format, ap); + va_end(ap); +} + static void bam_exit(int excode) { @@ -1501,13 +1472,24 @@ check_flags_and_files(char *root) /* * If archive is missing, create archive */ - (void) snprintf(path, sizeof (path), "%s%s", root, BOOT_ARCHIVE); + (void) snprintf(path, sizeof (path), "%s%s", root, + DIRECT_BOOT_ARCHIVE_32); if (stat(path, &sb) != 0) { if (bam_verbose && !bam_check) bam_print(UPDATE_ARCH_MISS, path); walk_arg.need_update = 1; return; } + if (bam_direct == BAM_DIRECT_DBOOT) { + (void) snprintf(path, sizeof (path), "%s%s", root, + DIRECT_BOOT_ARCHIVE_64); + if (stat(path, &sb) != 0) { + if (bam_verbose && !bam_check) + bam_print(UPDATE_ARCH_MISS, path); + walk_arg.need_update = 1; + return; + } + } } static error_t @@ -1891,11 +1873,20 @@ create_ramdisk(char *root) /* * Verify that the archive has been created */ - (void) snprintf(path, sizeof (path), "%s%s", root, BOOT_ARCHIVE); + (void) snprintf(path, sizeof (path), "%s%s", root, + DIRECT_BOOT_ARCHIVE_32); if (stat(path, &sb) != 0) { bam_error(ARCHIVE_NOT_CREATED, path); return (BAM_ERROR); } + if (bam_direct == BAM_DIRECT_DBOOT) { + (void) snprintf(path, sizeof (path), "%s%s", root, + DIRECT_BOOT_ARCHIVE_64); + if (stat(path, &sb) != 0) { + bam_error(ARCHIVE_NOT_CREATED, path); + return (BAM_ERROR); + } + } return (BAM_SUCCESS); } @@ -2248,7 +2239,13 @@ update_all(char *root, char *opt) (void) snprintf(rootbuf, sizeof (rootbuf), "%s/", mnt.mnt_mountp); bam_rootlen = strlen(rootbuf); - if (update_archive(rootbuf, opt) != BAM_SUCCESS) + + /* + * It's possible that other mounts may be an alternate boot + * architecture, so check it again. + */ + if ((dboot_or_multiboot(rootbuf) != BAM_SUCCESS) || + (update_archive(rootbuf, opt) != BAM_SUCCESS)) ret = BAM_ERROR; } @@ -2352,6 +2349,7 @@ line_parser(menu_t *mp, char *str, int *lineNum, int *entryNum) */ static line_t *prev = NULL; static entry_t *curr_ent = NULL; + static int in_liveupgrade = 0; line_t *lp; char *cmd, *sep, *arg; @@ -2377,6 +2375,11 @@ line_parser(menu_t *mp, char *str, int *lineNum, int *entryNum) sep = NULL; arg = s_strdup(str + 1); flag = BAM_COMMENT; + if (strstr(arg, BAM_LU_HDR) != NULL) { + in_liveupgrade = 1; + } else if (strstr(arg, BAM_LU_FTR) != NULL) { + in_liveupgrade = 0; + } } else if (*str == '\0') { /* blank line */ cmd = sep = arg = NULL; flag = BAM_EMPTY; @@ -2429,12 +2432,17 @@ line_parser(menu_t *mp, char *str, int *lineNum, int *entryNum) lp->entryNum = ++(*entryNum); lp->flags = BAM_TITLE; if (prev && prev->flags == BAM_COMMENT && - prev->arg && strcmp(prev->arg, BAM_HDR) == 0) { + prev->arg && strcmp(prev->arg, BAM_BOOTADM_HDR) == 0) { prev->entryNum = lp->entryNum; curr_ent = boot_entry_new(mp, prev, lp); + curr_ent->flags = BAM_ENTRY_BOOTADM; } else { curr_ent = boot_entry_new(mp, lp, lp); + if (in_liveupgrade) { + curr_ent->flags = BAM_ENTRY_LU; + } } + curr_ent->entryNum = *entryNum; } else if (flag != BAM_INVALID) { /* * For header comments, the entry# is "fixed up" @@ -2444,7 +2452,29 @@ line_parser(menu_t *mp, char *str, int *lineNum, int *entryNum) lp->flags = flag; } else { lp->entryNum = *entryNum; - lp->flags = (*entryNum == ENTRY_INIT) ? BAM_GLOBAL : BAM_ENTRY; + + if (*entryNum == ENTRY_INIT) { + lp->flags = BAM_GLOBAL; + } else { + lp->flags = BAM_ENTRY; + + if (cmd && arg) { + /* + * We only compare for the length of "module" + * so that "module$" will also match. + */ + if ((strncmp(cmd, menu_cmds[MODULE_CMD], + strlen(menu_cmds[MODULE_CMD])) == 0) && + (strcmp(arg, MINIROOT) == 0)) + curr_ent->flags |= BAM_ENTRY_MINIROOT; + else if (strcmp(cmd, menu_cmds[ROOT_CMD]) == 0) + curr_ent->flags |= BAM_ENTRY_ROOT; + else if (strcmp(cmd, + menu_cmds[CHAINLOADER_CMD]) == 0) + curr_ent->flags |= + BAM_ENTRY_CHAINLOADER; + } + } } /* record default, old default, and entry line ranges */ @@ -2454,8 +2484,12 @@ line_parser(menu_t *mp, char *str, int *lineNum, int *entryNum) } else if (lp->flags == BAM_COMMENT && strncmp(lp->arg, BAM_OLDDEF, strlen(BAM_OLDDEF)) == 0) { mp->olddefault = lp; + } else if (lp->flags == BAM_COMMENT && + strncmp(lp->arg, BAM_OLD_RC_DEF, strlen(BAM_OLD_RC_DEF)) == 0) { + mp->old_rc_default = lp; } else if (lp->flags == BAM_ENTRY || - (lp->flags == BAM_COMMENT && strcmp(lp->arg, BAM_FTR) == 0)) { + (lp->flags == BAM_COMMENT && + strcmp(lp->arg, BAM_BOOTADM_FTR) == 0)) { boot_entry_addline(curr_ent, lp); } append_line(mp, lp); @@ -2522,7 +2556,8 @@ update_numbering(menu_t *mp) lp->entryNum = ++entryNum; /* fixup the bootadm header */ if (prev && prev->flags == BAM_COMMENT && - prev->arg && strcmp(prev->arg, BAM_HDR) == 0) { + prev->arg && + strcmp(prev->arg, BAM_BOOTADM_HDR) == 0) { prev->entryNum = lp->entryNum; } } else { @@ -2727,6 +2762,7 @@ add_boot_entry(menu_t *mp, { int lineNum, entryNum; char linebuf[BAM_MAXLINE]; + menu_cmd_t k_cmd, m_cmd; assert(mp); @@ -2738,8 +2774,36 @@ add_boot_entry(menu_t *mp, return (BAM_ERROR); } if (module == NULL) { - bam_error(SUBOPT_MISS, menu_cmds[MODULE_CMD]); - return (BAM_ERROR); + if (bam_direct != BAM_DIRECT_DBOOT) { + bam_error(SUBOPT_MISS, menu_cmds[MODULE_CMD]); + return (BAM_ERROR); + } + + /* Figure the commands out from the kernel line */ + if (strstr(kernel, "$ISADIR") != NULL) { + module = DIRECT_BOOT_ARCHIVE; + k_cmd = KERNEL_DOLLAR_CMD; + m_cmd = MODULE_DOLLAR_CMD; + } else if (strstr(kernel, "amd64") != NULL) { + module = DIRECT_BOOT_ARCHIVE_64; + k_cmd = KERNEL_CMD; + m_cmd = MODULE_CMD; + } else { + module = DIRECT_BOOT_ARCHIVE_32; + k_cmd = KERNEL_CMD; + m_cmd = MODULE_CMD; + } + } else if ((bam_direct == BAM_DIRECT_DBOOT) && + (strstr(kernel, "$ISADIR") != NULL)) { + /* + * If it's a non-failsafe dboot kernel, use the "kernel$" + * command. Otherwise, use "kernel". + */ + k_cmd = KERNEL_DOLLAR_CMD; + m_cmd = MODULE_DOLLAR_CMD; + } else { + k_cmd = KERNEL_CMD; + m_cmd = MODULE_CMD; } if (mp->start) { @@ -2755,7 +2819,7 @@ add_boot_entry(menu_t *mp, * The syntax for comments is #<comment> */ (void) snprintf(linebuf, sizeof (linebuf), "%s%s", - menu_cmds[COMMENT_CMD], BAM_HDR); + menu_cmds[COMMENT_CMD], BAM_BOOTADM_HDR); line_parser(mp, linebuf, &lineNum, &entryNum); (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", @@ -2769,15 +2833,15 @@ add_boot_entry(menu_t *mp, } (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", - menu_cmds[KERNEL_CMD], menu_cmds[SEP_CMD], kernel); + menu_cmds[k_cmd], menu_cmds[SEP_CMD], kernel); line_parser(mp, linebuf, &lineNum, &entryNum); (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", - menu_cmds[MODULE_CMD], menu_cmds[SEP_CMD], module); + menu_cmds[m_cmd], menu_cmds[SEP_CMD], module); line_parser(mp, linebuf, &lineNum, &entryNum); (void) snprintf(linebuf, sizeof (linebuf), "%s%s", - menu_cmds[COMMENT_CMD], BAM_FTR); + menu_cmds[COMMENT_CMD], BAM_BOOTADM_FTR); line_parser(mp, linebuf, &lineNum, &entryNum); return (entryNum); @@ -2797,7 +2861,7 @@ do_delete(menu_t *mp, int entryNum) lp = ent->start; /* check entry number and make sure it's a bootadm entry */ if (lp->flags != BAM_COMMENT || - strcmp(lp->arg, BAM_HDR) != 0 || + strcmp(lp->arg, BAM_BOOTADM_HDR) != 0 || (entryNum != ALL_ENTRIES && lp->entryNum != entryNum)) { ent = ent->next; continue; @@ -3003,7 +3067,7 @@ get_title(char *rootdir) return (cp == NULL ? "Solaris" : cp); } -static char * +char * get_special(char *mountp) { FILE *mntfp; @@ -3027,7 +3091,7 @@ get_special(char *mountp) return (s_strdup(mp.mnt_special)); } -static char * +char * os_to_grubdisk(char *osdisk, int on_bootdev) { FILE *fp; @@ -3092,7 +3156,8 @@ find_boot_entry(menu_t *mp, char *title, char *root, char *module, /* first line of entry must be bootadm comment */ lp = ent->start; - if (lp->flags != BAM_COMMENT || strcmp(lp->arg, BAM_HDR) != 0) { + if (lp->flags != BAM_COMMENT || + strcmp(lp->arg, BAM_BOOTADM_HDR) != 0) { continue; } @@ -3125,8 +3190,9 @@ find_boot_entry(menu_t *mp, char *title, char *root, char *module, /* check for matching module entry (failsafe or normal) */ lp = lp->next; /* advance to module line */ - if (strcmp(lp->cmd, menu_cmds[MODULE_CMD]) != 0 || - strcmp(lp->arg, module) != 0) { + if ((strncmp(lp->cmd, menu_cmds[MODULE_CMD], + strlen(menu_cmds[MODULE_CMD])) != 0) || + (strcmp(lp->arg, module) != 0)) { continue; } break; /* match found */ @@ -3140,13 +3206,24 @@ static int update_boot_entry(menu_t *mp, char *title, char *root, char *kernel, char *module, int root_opt) { - int i; + int i, change_kernel = 0; entry_t *ent; line_t *lp; char linebuf[BAM_MAXLINE]; /* note: don't match on title, it's updated on upgrade */ ent = find_boot_entry(mp, NULL, root, module, root_opt, &i); + if ((ent == NULL) && (bam_direct == BAM_DIRECT_DBOOT)) { + /* + * We may be upgrading a kernel from multiboot to + * directboot. Look for a multiboot entry. + */ + ent = find_boot_entry(mp, NULL, root, MULTI_BOOT_ARCHIVE, + root_opt, &i); + if (ent != NULL) { + change_kernel = 1; + } + } if (ent == NULL) return (add_boot_entry(mp, title, root_opt ? NULL : root, kernel, module)); @@ -3171,6 +3248,32 @@ update_boot_entry(menu_t *mp, char *title, char *root, char *kernel, } else lp = lp->next; } + + if (change_kernel) { + /* + * We're upgrading from multiboot to directboot. + */ + if (strcmp(lp->cmd, menu_cmds[KERNEL_CMD]) == 0) { + (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", + menu_cmds[KERNEL_DOLLAR_CMD], menu_cmds[SEP_CMD], + kernel); + free(lp->arg); + free(lp->line); + lp->arg = s_strdup(kernel); + lp->line = s_strdup(linebuf); + lp = lp->next; + } + if (strcmp(lp->cmd, menu_cmds[MODULE_CMD]) == 0) { + (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", + menu_cmds[MODULE_DOLLAR_CMD], menu_cmds[SEP_CMD], + module); + free(lp->arg); + free(lp->line); + lp->arg = s_strdup(module); + lp->line = s_strdup(linebuf); + lp = lp->next; + } + } return (i); } @@ -3207,19 +3310,24 @@ update_entry(menu_t *mp, char *menu_root, char *opt) } /* add the entry for normal Solaris */ - entry = update_boot_entry(mp, title, grubdisk, - "/platform/i86pc/multiboot", - "/platform/i86pc/boot_archive", - osroot == menu_root); + if (bam_direct == BAM_DIRECT_DBOOT) { + entry = update_boot_entry(mp, title, grubdisk, + DIRECT_BOOT_KERNEL, DIRECT_BOOT_ARCHIVE, + osroot == menu_root); + } else { + entry = update_boot_entry(mp, title, grubdisk, + MULTI_BOOT, MULTI_BOOT_ARCHIVE, + osroot == menu_root); + } /* add the entry for failsafe archive */ - (void) snprintf(failsafe, sizeof (failsafe), - "%s/boot/x86.miniroot-safe", osroot); - if (stat(failsafe, &sbuf) == 0) - (void) update_boot_entry(mp, "Solaris failsafe", grubdisk, - "/boot/multiboot kernel/unix -s", - "/boot/x86.miniroot-safe", - osroot == menu_root); + (void) snprintf(failsafe, sizeof (failsafe), "%s%s", osroot, MINIROOT); + if (stat(failsafe, &sbuf) == 0) { + (void) update_boot_entry(mp, FAILSAFE_TITLE, grubdisk, + (bam_direct == BAM_DIRECT_DBOOT) ? + DIRECT_BOOT_FAILSAFE_LINE : MULTI_BOOT_FAILSAFE_LINE, + MINIROOT, osroot == menu_root); + } free(grubdisk); if (entry == BAM_ERROR) { @@ -3276,7 +3384,7 @@ read_grub_root(void) } static void -save_default_entry(menu_t *mp) +save_default_entry(menu_t *mp, const char *which) { int lineNum, entryNum; int entry = 0; /* default is 0 */ @@ -3294,26 +3402,24 @@ save_default_entry(menu_t *mp) if (lp) entry = s_strtol(lp->arg); - (void) snprintf(linebuf, sizeof (linebuf), "#%s%d", BAM_OLDDEF, entry); + (void) snprintf(linebuf, sizeof (linebuf), "#%s%d", which, entry); line_parser(mp, linebuf, &lineNum, &entryNum); } static void -restore_default_entry(menu_t *mp) +restore_default_entry(menu_t *mp, const char *which, line_t *lp) { int entry; char *str; - line_t *lp = mp->olddefault; if (lp == NULL) return; /* nothing to restore */ - str = lp->arg + strlen(BAM_OLDDEF); + str = lp->arg + strlen(which); entry = s_strtol(str); (void) set_global(mp, menu_cmds[DEFAULT_CMD], entry); /* delete saved old default line */ - mp->olddefault = NULL; unlink_line(mp, lp); line_free(lp); } @@ -3333,8 +3439,9 @@ static error_t update_temp(menu_t *mp, char *menupath, char *opt) { int entry; - char *grubdisk, *rootdev; - char kernbuf[1024]; + char *grubdisk, *rootdev, *path; + char kernbuf[BUFSIZ]; + char args_buf[BUFSIZ]; struct stat sb; assert(mp); @@ -3346,7 +3453,8 @@ update_temp(menu_t *mp, char *menupath, char *opt) if (ent == NULL) /* not found is ok */ return (BAM_SUCCESS); (void) do_delete(mp, entry); - restore_default_entry(mp); + restore_default_entry(mp, BAM_OLDDEF, mp->olddefault); + mp->olddefault = NULL; return (BAM_WRITE); } @@ -3385,10 +3493,47 @@ update_temp(menu_t *mp, char *menupath, char *opt) } /* add an entry for Solaris reboot */ - (void) snprintf(kernbuf, sizeof (kernbuf), - "/platform/i86pc/multiboot %s", opt); - entry = add_boot_entry(mp, REBOOT_TITLE, grubdisk, kernbuf, - "/platform/i86pc/boot_archive"); + if (bam_direct == BAM_DIRECT_DBOOT) { + if (opt[0] == '-') { + /* It's an option - first see if boot-file is set */ + if (set_kernel(mp, KERNEL_CMD, NULL, kernbuf, BUFSIZ) + != BAM_SUCCESS) + return (BAM_ERROR); + if (kernbuf[0] == '\0') + (void) strncpy(kernbuf, DIRECT_BOOT_KERNEL, + BUFSIZ); + (void) strlcat(kernbuf, " ", BUFSIZ); + (void) strlcat(kernbuf, opt, BUFSIZ); + } else if (opt[0] == '/') { + /* It's a full path - write it out and go home */ + (void) strlcpy(kernbuf, opt, BUFSIZ); + } else { + path = expand_path(opt); + if (path != NULL) { + (void) strlcpy(kernbuf, path, BUFSIZ); + free(path); + if (strcmp(opt, "kmdb") == 0) { + if (set_kernel(mp, ARGS_CMD, NULL, + args_buf, BUFSIZ) != BAM_SUCCESS) + return (BAM_ERROR); + + if (args_buf[0] != '\0') { + (void) strlcat(kernbuf, " ", + BUFSIZ); + (void) strlcat(kernbuf, + args_buf, BUFSIZ); + } + } + } + } + entry = add_boot_entry(mp, REBOOT_TITLE, grubdisk, kernbuf, + NULL); + } else { + (void) snprintf(kernbuf, sizeof (kernbuf), "%s %s", + MULTI_BOOT, opt); + entry = add_boot_entry(mp, REBOOT_TITLE, grubdisk, kernbuf, + MULTI_BOOT_ARCHIVE); + } free(grubdisk); if (entry == BAM_ERROR) { @@ -3396,7 +3541,7 @@ update_temp(menu_t *mp, char *menupath, char *opt) return (BAM_ERROR); } - save_default_entry(mp); + save_default_entry(mp, BAM_OLDDEF); (void) set_global(mp, menu_cmds[DEFAULT_CMD], entry); return (BAM_WRITE); } @@ -3482,35 +3627,418 @@ set_global(menu_t *mp, char *globalcmd, int val) return (BAM_WRITE); /* need a write to menu */ } +/* + * partial_path may be anything like "kernel/unix" or "kmdb". Try to + * expand it to a full unix path. + */ +static char * +expand_path(const char *partial_path) +{ + int new_path_len; + char *new_path, new_path2[PATH_MAX]; + struct stat sb; + + new_path_len = strlen(partial_path) + 64; + new_path = s_calloc(1, new_path_len); + + /* First, try the simplest case - something like "kernel/unix" */ + (void) snprintf(new_path, new_path_len, "/platform/i86pc/%s", + partial_path); + if (stat(new_path, &sb) == 0) { + return (new_path); + } + + if (strcmp(partial_path, "kmdb") == 0) { + (void) snprintf(new_path, new_path_len, "%s -k", + DIRECT_BOOT_KERNEL); + return (new_path); + } + + /* + * We've quickly reached unsupported usage. Try once more to + * see if we were just given a glom name. + */ + (void) snprintf(new_path, new_path_len, "/platform/i86pc/%s/unix", + partial_path); + (void) snprintf(new_path2, PATH_MAX, "/platform/i86pc/%s/amd64/unix", + partial_path); + if (stat(new_path, &sb) == 0) { + if (stat(new_path2, &sb) == 0) { + /* + * We matched both, so we actually + * want to write the $ISADIR version. + */ + (void) snprintf(new_path, new_path_len, + "/platform/i86pc/kernel/%s/$ISADIR/unix", + partial_path); + } + return (new_path); + } + + bam_error(UNKNOWN_KERNEL, partial_path); + free(new_path); + return (NULL); +} + +/* + * The kernel cmd and arg have been changed, so + * check whether the archive line needs to change. + */ +static void +set_archive_line(entry_t *entryp, line_t *kernelp) +{ + line_t *lp = entryp->start; + char *new_archive; + menu_cmd_t m_cmd; + + for (; lp != NULL; lp = lp->next) { + if (strncmp(lp->cmd, menu_cmds[MODULE_CMD], + sizeof (menu_cmds[MODULE_CMD]) - 1) == 0) { + break; + } + if (lp == entryp->end) + return; + } + if (lp == NULL) + return; + + if (strstr(kernelp->arg, "$ISADIR") != NULL) { + new_archive = DIRECT_BOOT_ARCHIVE; + m_cmd = MODULE_DOLLAR_CMD; + } else if (strstr(kernelp->arg, "amd64") != NULL) { + new_archive = DIRECT_BOOT_ARCHIVE_64; + m_cmd = MODULE_CMD; + } else { + new_archive = DIRECT_BOOT_ARCHIVE_32; + m_cmd = MODULE_CMD; + } + + if (strcmp(lp->arg, new_archive) == 0) + return; + + if (strcmp(lp->cmd, menu_cmds[m_cmd]) != 0) { + free(lp->cmd); + lp->cmd = s_strdup(menu_cmds[m_cmd]); + } + + free(lp->arg); + lp->arg = s_strdup(new_archive); + update_line(lp); +} + +/* + * Title for an entry to set properties that once went in bootenv.rc. + */ +#define BOOTENV_RC_TITLE "Solaris bootenv rc" + +/* + * If path is NULL, return the kernel (optnum == KERNEL_CMD) or arguments + * (optnum == ARGS_CMD) in the argument buf. If path is a zero-length + * string, reset the value to the default. If path is a non-zero-length + * string, set the kernel or arguments. + */ +static error_t +set_kernel(menu_t *mp, menu_cmd_t optnum, char *path, char *buf, size_t bufsize) +{ + int entryNum, rv = BAM_SUCCESS, free_new_path = 0; + entry_t *entryp; + line_t *ptr, *kernelp; + char *new_arg, *old_args, *space; + char *grubdisk, *rootdev, *new_path; + char old_space; + size_t old_kernel_len, new_str_len; + struct stat sb; + + assert(bufsize > 0); + + ptr = kernelp = NULL; + new_arg = old_args = space = NULL; + grubdisk = rootdev = new_path = NULL; + buf[0] = '\0'; + + if (bam_direct != BAM_DIRECT_DBOOT) { + bam_error(NOT_DBOOT, optnum == KERNEL_CMD ? "kernel" : "args"); + return (BAM_ERROR); + } + + /* + * If a user changed the default entry to a non-bootadm controlled + * one, we don't want to mess with it. Just print an error and + * return. + */ + if (mp->curdefault) { + entryNum = s_strtol(mp->curdefault->arg); + for (entryp = mp->entries; entryp; entryp = entryp->next) { + if (entryp->entryNum == entryNum) + break; + } + if ((entryp != NULL) && + ((entryp->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU)) == 0)) { + bam_error(DEFAULT_NOT_BAM); + return (BAM_ERROR); + } + } + + entryNum = -1; + entryp = find_boot_entry(mp, BOOTENV_RC_TITLE, NULL, NULL, 0, + &entryNum); + + if (entryp != NULL) { + for (ptr = entryp->start; ptr && ptr != entryp->end; + ptr = ptr->next) { + if (strncmp(ptr->cmd, menu_cmds[KERNEL_CMD], + sizeof (menu_cmds[KERNEL_CMD]) - 1) == 0) { + kernelp = ptr; + break; + } + } + if (kernelp == NULL) { + bam_error(NO_KERNEL, entryNum); + return (BAM_ERROR); + } + + old_kernel_len = strcspn(kernelp->arg, " \t"); + space = old_args = kernelp->arg + old_kernel_len; + while ((*old_args == ' ') || (*old_args == '\t')) + old_args++; + } + + if (path == NULL) { + /* Simply report what was found */ + if (kernelp == NULL) + return (BAM_SUCCESS); + + if (optnum == ARGS_CMD) { + if (old_args[0] != '\0') + (void) strlcpy(buf, old_args, bufsize); + } else { + /* + * We need to print the kernel, so we just turn the + * first space into a '\0' and print the beginning. + * We don't print anything if it's the default kernel. + */ + old_space = *space; + *space = '\0'; + if (strcmp(kernelp->arg, DIRECT_BOOT_KERNEL) != 0) + (void) strlcpy(buf, kernelp->arg, bufsize); + *space = old_space; + } + return (BAM_SUCCESS); + } + + /* + * First, check if we're resetting an entry to the default. + */ + if ((path[0] == '\0') || + ((optnum == KERNEL_CMD) && + (strcmp(path, DIRECT_BOOT_KERNEL) == 0))) { + if ((entryp == NULL) || (kernelp == NULL)) { + /* No previous entry, it's already the default */ + return (BAM_SUCCESS); + } + + /* + * Check if we can delete the entry. If we're resetting the + * kernel command, and the args is already empty, or if we're + * resetting the args command, and the kernel is already the + * default, we can restore the old default and delete the entry. + */ + if (((optnum == KERNEL_CMD) && + ((old_args == NULL) || (old_args[0] == '\0'))) || + ((optnum == ARGS_CMD) && + (strncmp(kernelp->arg, DIRECT_BOOT_KERNEL, + sizeof (DIRECT_BOOT_KERNEL) - 1) == 0))) { + kernelp = NULL; + (void) do_delete(mp, entryNum); + restore_default_entry(mp, BAM_OLD_RC_DEF, + mp->old_rc_default); + mp->old_rc_default = NULL; + rv = BAM_WRITE; + goto done; + } + + if (optnum == KERNEL_CMD) { + /* + * At this point, we've already checked that old_args + * and entryp are valid pointers. The "+ 2" is for + * a space a the string termination character. + */ + new_str_len = (sizeof (DIRECT_BOOT_KERNEL) - 1) + + strlen(old_args) + 2; + new_arg = s_calloc(1, new_str_len); + (void) snprintf(new_arg, new_str_len, "%s %s", + DIRECT_BOOT_KERNEL, old_args); + free(kernelp->arg); + kernelp->arg = new_arg; + + /* + * We have changed the kernel line, so we may need + * to update the archive line as well. + */ + set_archive_line(entryp, kernelp); + } else { + /* + * We're resetting the boot args to nothing, so + * we only need to copy the kernel. We've already + * checked that the kernel is not the default. + */ + new_arg = s_calloc(1, old_kernel_len + 1); + (void) snprintf(new_arg, old_kernel_len + 1, "%s", + kernelp->arg); + free(kernelp->arg); + kernelp->arg = new_arg; + } + rv = BAM_WRITE; + goto done; + } + + /* + * Expand the kernel file to a full path, if necessary + */ + if ((optnum == KERNEL_CMD) && (path[0] != '/')) { + new_path = expand_path(path); + if (new_path == NULL) { + return (BAM_ERROR); + } + free_new_path = 1; + } else { + new_path = path; + free_new_path = 0; + } + + /* + * At this point, we know we're setting a new value. First, take care + * of the case where there was no previous entry. + */ + if (entryp == NULL) { + /* Similar to code in update_temp */ + if (stat(GRUB_slice, &sb) != 0) { + /* + * 1. First get root disk name from mnttab + * 2. Translate disk name to grub name + * 3. Add the new menu entry + */ + rootdev = get_special("/"); + if (rootdev) { + grubdisk = os_to_grubdisk(rootdev, 1); + free(rootdev); + } + } else { + /* + * This is an LU BE. The GRUB_root file + * contains entry for GRUB's "root" cmd. + */ + grubdisk = read_grub_root(); + } + if (grubdisk == NULL) { + bam_error(REBOOT_WITH_ARGS_FAILED); + rv = BAM_ERROR; + goto done; + } + if (optnum == KERNEL_CMD) { + entryNum = add_boot_entry(mp, BOOTENV_RC_TITLE, + grubdisk, new_path, NULL); + } else { + new_str_len = strlen(DIRECT_BOOT_KERNEL) + + strlen(path) + 8; + new_arg = s_calloc(1, new_str_len); + + (void) snprintf(new_arg, new_str_len, "%s %s", + DIRECT_BOOT_KERNEL, path); + entryNum = add_boot_entry(mp, BOOTENV_RC_TITLE, + grubdisk, new_arg, DIRECT_BOOT_ARCHIVE); + } + save_default_entry(mp, BAM_OLD_RC_DEF); + (void) set_global(mp, menu_cmds[DEFAULT_CMD], entryNum); + rv = BAM_WRITE; + goto done; + } + + /* + * There was already an bootenv entry which we need to edit. + */ + if (optnum == KERNEL_CMD) { + new_str_len = strlen(new_path) + strlen(old_args) + 2; + new_arg = s_calloc(1, new_str_len); + (void) snprintf(new_arg, new_str_len, "%s %s", new_path, + old_args); + free(kernelp->arg); + kernelp->arg = new_arg; + + /* + * If we have changed the kernel line, we may need to update + * the archive line as well. + */ + set_archive_line(entryp, kernelp); + } else { + new_str_len = old_kernel_len + strlen(path) + 8; + new_arg = s_calloc(1, new_str_len); + (void) strncpy(new_arg, kernelp->arg, old_kernel_len); + (void) strlcat(new_arg, " ", new_str_len); + (void) strlcat(new_arg, path, new_str_len); + free(kernelp->arg); + kernelp->arg = new_arg; + } + rv = BAM_WRITE; + +done: + if ((rv == BAM_WRITE) && kernelp) + update_line(kernelp); + if (free_new_path) + free(new_path); + return (rv); +} + /*ARGSUSED*/ static error_t set_option(menu_t *mp, char *menu_path, char *opt) { int optnum, optval; char *val; + char buf[BUFSIZ] = ""; + error_t rv; assert(mp); assert(opt); val = strchr(opt, '='); - if (val == NULL) { - bam_error(INVALID_ENTRY, opt); - return (BAM_ERROR); + if (val != NULL) { + *val = '\0'; } - *val = '\0'; if (strcmp(opt, "default") == 0) { optnum = DEFAULT_CMD; } else if (strcmp(opt, "timeout") == 0) { optnum = TIMEOUT_CMD; + } else if (strcmp(opt, menu_cmds[KERNEL_CMD]) == 0) { + optnum = KERNEL_CMD; + } else if (strcmp(opt, menu_cmds[ARGS_CMD]) == 0) { + optnum = ARGS_CMD; } else { bam_error(INVALID_ENTRY, opt); return (BAM_ERROR); } - optval = s_strtol(val + 1); - *val = '='; - return (set_global(mp, menu_cmds[optnum], optval)); + /* + * kernel and args are allowed without "=new_value" strings. All + * others cause errors + */ + if ((val == NULL) && (optnum != KERNEL_CMD) && (optnum != ARGS_CMD)) { + bam_error(INVALID_ENTRY, opt); + return (BAM_ERROR); + } else if (val != NULL) { + *val = '='; + } + + if ((optnum == KERNEL_CMD) || (optnum == ARGS_CMD)) { + rv = set_kernel(mp, optnum, val ? val + 1 : NULL, buf, BUFSIZ); + if ((rv == BAM_SUCCESS) && (buf[0] != '\0')) + (void) printf("%s\n", buf); + return (rv); + } else { + optval = s_strtol(val + 1); + return (set_global(mp, menu_cmds[optnum], optval)); + } } /* @@ -3766,7 +4294,7 @@ s_fputs(char *str, FILE *fp) /* * Wrapper around fgets, that strips newlines returned by fgets */ -static char * +char * s_fgets(char *buf, int buflen, FILE *fp) { int n; @@ -3782,7 +4310,7 @@ s_fgets(char *buf, int buflen, FILE *fp) return (buf); } -static void * +void * s_calloc(size_t nelem, size_t sz) { void *ptr; @@ -3795,6 +4323,17 @@ s_calloc(size_t nelem, size_t sz) return (ptr); } +void * +s_realloc(void *ptr, size_t sz) +{ + ptr = realloc(ptr, sz); + if (ptr == NULL) { + bam_error(NO_MEM, sz); + bam_exit(1); + } + return (ptr); +} + static char * s_strdup(char *str) { diff --git a/usr/src/cmd/boot/bootadm/bootadm.h b/usr/src/cmd/boot/bootadm/bootadm.h new file mode 100644 index 0000000000..80309501cb --- /dev/null +++ b/usr/src/cmd/boot/bootadm/bootadm.h @@ -0,0 +1,184 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _BOOTADM_H +#define _BOOTADM_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TEXT_DOMAIN +#define TEXT_DOMAIN "SUNW_OST_OSCMD" +#endif /* TEXT_DOMAIN */ + +/* Type definitions */ + +/* GRUB menu per-line classification */ +typedef enum { + BAM_INVALID = 0, + BAM_EMPTY, + BAM_COMMENT, + BAM_GLOBAL, + BAM_ENTRY, + BAM_TITLE +} menu_flag_t; + +/* struct for menu.lst contents */ +typedef struct line { + int lineNum; /* Line number in menu.lst */ + int entryNum; /* menu boot entry #. ENTRY_INIT if not applicable */ + char *cmd; + char *sep; + char *arg; + char *line; + menu_flag_t flags; + struct line *next; + struct line *prev; +} line_t; + +typedef struct entry { + struct entry *next; + struct entry *prev; + line_t *start; + line_t *end; + int entryNum; + uint8_t flags; +} entry_t; + +/* For flags value in entry_t */ +#define BAM_ENTRY_BOOTADM 0x01 /* entry created by bootadm */ +#define BAM_ENTRY_LU 0x02 /* entry created by Live Upgrade */ +#define BAM_ENTRY_CHAINLOADER 0x04 /* chainloader entry; do not disturb */ +#define BAM_ENTRY_ROOT 0x08 /* entry has a root line */ +#define BAM_ENTRY_MINIROOT 0x10 /* entry uses the failsafe miniroot */ +#define BAM_ENTRY_DBOOT 0x20 /* Is a dboot entry */ +#define BAM_ENTRY_32BIT 0x40 /* Is a 32-bit entry */ + +typedef struct { + line_t *start; + line_t *end; + line_t *curdefault; /* line containing default */ + line_t *olddefault; /* old default line (commented) */ + line_t *old_rc_default; /* old default line for bootenv.rc */ + entry_t *entries; /* os entries */ +} menu_t; + +typedef enum { + BAM_ERROR = -1, /* Must be negative. add_boot_entry() depends on it */ + BAM_SUCCESS = 0, + BAM_WRITE = 2, + BAM_SKIP /* Used by upgrade_menu() */ +} error_t; + +/* + * Menu related + * menu_cmd_t and menu_cmds must be kept in sync + */ +typedef enum { + DEFAULT_CMD = 0, + TIMEOUT_CMD, + TITLE_CMD, + ROOT_CMD, + KERNEL_CMD, + KERNEL_DOLLAR_CMD, + MODULE_CMD, + MODULE_DOLLAR_CMD, + SEP_CMD, + COMMENT_CMD, + CHAINLOADER_CMD, + ARGS_CMD +} menu_cmd_t; + +extern char *menu_cmds[]; + +/* For multi- or direct-boot */ +typedef enum { + BAM_DIRECT_NOT_SET, + BAM_DIRECT_MULTIBOOT, + BAM_DIRECT_DBOOT +} direct_or_multi_t; + +extern int bam_verbose; +extern int bam_force; +extern direct_or_multi_t bam_direct; + +extern error_t upgrade_menu(menu_t *, char *, char *); +extern void *s_calloc(size_t, size_t); +extern void *s_realloc(void *, size_t); +extern char *s_fgets(char *buf, int n, FILE *fp); +extern void bam_error(char *format, ...); +extern void bam_print_stderr(char *format, ...); +extern error_t dboot_or_multiboot(const char *); +extern char *get_special(char *); +extern char *os_to_grubdisk(char *, int); +extern void update_line(line_t *); + +#define BAM_MAXLINE 8192 + +/* menu.lst comments created by bootadm */ +#define BAM_BOOTADM_HDR "---------- ADDED BY BOOTADM - DO NOT EDIT ----------" +#define BAM_BOOTADM_FTR "---------------------END BOOTADM--------------------" + +/* + * menu.lst comments create by Live Upgrade. Note that these are the end of + * the comment strings - there will be other text before them. + */ +#define BAM_LU_HDR " - ADDED BY LIVE UPGRADE - DO NOT EDIT -----" +#define BAM_LU_FTR " -------------- END LIVE UPGRADE ------------" + +#define BAM_OLDDEF "BOOTADM SAVED DEFAULT: " +#define BAM_OLD_RC_DEF "BOOTADM RC SAVED DEFAULT: " + +/* Title used for failsafe entries */ +#define FAILSAFE_TITLE "Solaris failsafe" + +/* multiboot */ +#define MULTI_BOOT "/platform/i86pc/multiboot" +#define MULTI_BOOT_FAILSAFE "/boot/multiboot" +#define MULTI_BOOT_FAILSAFE_UNIX "kernel/unix" +#define MULTI_BOOT_FAILSAFE_LINE "/boot/multiboot kernel/unix -s" + +/* directboot kernels */ +#define DIRECT_BOOT_32 "/platform/i86pc/kernel/unix" +#define DIRECT_BOOT_64 "/platform/i86pc/kernel/amd64/unix" +#define DIRECT_BOOT_KERNEL "/platform/i86pc/kernel/$ISADIR/unix" +#define DIRECT_BOOT_FAILSAFE_KERNEL "/boot/platform/i86pc/kernel/unix" +#define DIRECT_BOOT_FAILSAFE_LINE DIRECT_BOOT_FAILSAFE_KERNEL " -s" + +/* Boot archives */ +#define DIRECT_BOOT_ARCHIVE "/platform/i86pc/$ISADIR/boot_archive" +#define DIRECT_BOOT_ARCHIVE_32 "/platform/i86pc/boot_archive" +#define DIRECT_BOOT_ARCHIVE_64 "/platform/i86pc/amd64/boot_archive" +#define MULTI_BOOT_ARCHIVE DIRECT_BOOT_ARCHIVE_32 +#define MINIROOT "/boot/x86.miniroot-safe" + +#ifdef __cplusplus +} +#endif + +#endif /* _BOOTADM_H */ diff --git a/usr/src/cmd/boot/bootadm/bootadm_upgrade.c b/usr/src/cmd/boot/bootadm/bootadm_upgrade.c new file mode 100644 index 0000000000..0b375b7fd0 --- /dev/null +++ b/usr/src/cmd/boot/bootadm/bootadm_upgrade.c @@ -0,0 +1,575 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <limits.h> +#include <fcntl.h> +#include <strings.h> + +#include <sys/mman.h> +#include <sys/elf.h> +#include <sys/multiboot.h> + +#include "message.h" +#include "bootadm.h" + +direct_or_multi_t bam_direct = BAM_DIRECT_NOT_SET; + +error_t +dboot_or_multiboot(const char *root) +{ + char fname[PATH_MAX]; + char *image; + uchar_t *ident; + int fd, m; + multiboot_header_t *mbh; + + (void) snprintf(fname, PATH_MAX, "%s/%s", root, + "platform/i86pc/kernel/unix"); + fd = open(fname, O_RDONLY); + if (fd < 0) { + bam_error(OPEN_FAIL, fname, strerror(errno)); + return (BAM_ERROR); + } + + /* + * mmap the first 8K + */ + image = mmap(NULL, 8192, PROT_READ, MAP_SHARED, fd, 0); + if (image == MAP_FAILED) { + bam_error(MMAP_FAIL, fname, strerror(errno)); + return (BAM_ERROR); + } + + ident = (uchar_t *)image; + if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 || + ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) { + bam_error(NOT_ELF_FILE, fname); + return (BAM_ERROR); + } + if (ident[EI_CLASS] != ELFCLASS32) { + bam_error(WRONG_ELF_CLASS, fname, ident[EI_CLASS]); + return (BAM_ERROR); + } + + /* + * The GRUB multiboot header must be 32-bit aligned and completely + * contained in the 1st 8K of the file. If the unix binary has + * a multiboot header, then it is a 'dboot' kernel. Otherwise, + * this kernel must be booted via multiboot -- we call this a + * 'multiboot' kernel. + */ + bam_direct = BAM_DIRECT_MULTIBOOT; + for (m = 0; m < 8192 - sizeof (multiboot_header_t); m += 4) { + mbh = (void *)(image + m); + if (mbh->magic == MB_HEADER_MAGIC) { + bam_direct = BAM_DIRECT_DBOOT; + break; + } + } + (void) munmap(image, 8192); + (void) close(fd); + return (BAM_SUCCESS); +} + +#define INST_RELEASE "var/sadm/system/admin/INST_RELEASE" + +/* + * Return true if root has been bfu'ed. bfu will blow away + * var/sadm/system/admin/INST_RELEASE, so if it's still there, we can + * assume the system has not been bfu'ed. + */ +static int +is_bfu_system(const char *root) +{ + static int is_bfu = -1; + char path[PATH_MAX]; + struct stat sb; + + if (is_bfu != -1) + return (is_bfu); + + (void) snprintf(path, sizeof (path), "%s/%s", root, INST_RELEASE); + if (stat(path, &sb) != 0) { + is_bfu = 1; + } else { + is_bfu = 0; + } + return (is_bfu); +} + +#define MENU_URL(root) (is_bfu_system(root) ? \ + "http://www.sun.com/msg/SUNOS-8000-CF" : \ + "http://www.sun.com/msg/SUNOS-8000-AK") + +/* + * Simply allocate a new line and copy in cmd + sep + arg + */ +void +update_line(line_t *linep) +{ + size_t size; + + free(linep->line); + size = strlen(linep->cmd) + strlen(linep->sep) + strlen(linep->arg) + 1; + linep->line = s_calloc(1, size); + (void) snprintf(linep->line, size, "%s%s%s", linep->cmd, linep->sep, + linep->arg); +} + +/* + * The parse_kernel_line function examines a menu.lst kernel line. For + * multiboot, this is: + * + * kernel <multiboot path> <flags1> <kernel path> <flags2> + * + * <multiboot path> is either /platform/i86pc/multiboot or /boot/multiboot + * + * <kernel path> may be missing, or may be any full or relative path to unix. + * We check for it by looking for a word ending in "/unix". If it ends + * in "kernel/unix", we upgrade it to a 32-bit entry. If it ends in + * "kernel/amd64/unix", we upgrade it to the default entry. Otherwise, + * it's a custom kernel, and we skip it. + * + * <flags*> are anything that doesn't fit either of the above - these will be + * copied over. + * + * For direct boot, the defaults are + * + * kernel$ <kernel path> <flags> + * + * <kernel path> is one of: + * /platform/i86pc/kernel/$ISADIR/unix + * /platform/i86pc/kernel/unix + * /platform/i86pc/kernel/amd64/unix + * /boot/platform/i86pc/kernel/unix + * + * If <kernel path> is any of the last three, the command may also be "kernel". + * + * <flags> is anything that isn't <kernel path>. + * + * This function is only called if it applies to our target boot environment. + * If we can't make any sense of the kernel line, an error is printed and + * BAM_ERROR is returned. + * + * The desired install type is given in the global variable bam_direct. + * If the kernel line is of a different install type, we change it to the + * preferred type. If the kernel line is already of the correct install + * type, we do nothing. Either way, BAM_SUCCESS is returned. + * + * For safety, we do one more check: if the kernel path starts with /boot, + * we verify that the new kernel exists before changing it. This is mainly + * done for bfu, as it may cause the failsafe archives to be a different + * boot architecture from the newly bfu'ed system. + */ +static error_t +parse_kernel_line(line_t *linep, const char *root, uint8_t *flags) +{ + char path[PATH_MAX]; + int len, left, total_len; + struct stat sb; + char *new_ptr, *new_arg, *old_ptr; + menu_cmd_t which; + + /* Used when changing a multiboot line to dboot */ + char *unix_ptr, *flags1_ptr, *flags2_ptr; + + /* + * Note that BAM_ENTRY_DBOOT refers to the entry we're looking at, not + * necessarily the system type. + */ + if (strncmp(linep->arg, DIRECT_BOOT_32, + sizeof (DIRECT_BOOT_32) - 1) == 0) { + *flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_32BIT; + } else if ((strncmp(linep->arg, DIRECT_BOOT_KERNEL, + sizeof (DIRECT_BOOT_KERNEL) - 1) == 0) || + (strncmp(linep->arg, DIRECT_BOOT_64, + sizeof (DIRECT_BOOT_64) - 1) == 0) || + (strncmp(linep->arg, DIRECT_BOOT_FAILSAFE_KERNEL, + sizeof (DIRECT_BOOT_FAILSAFE_KERNEL) - 1) == 0)) { + *flags |= BAM_ENTRY_DBOOT; + } else if ((strncmp(linep->arg, MULTI_BOOT, + sizeof (MULTI_BOOT) - 1) == 0) || + (strncmp(linep->arg, MULTI_BOOT_FAILSAFE, + sizeof (MULTI_BOOT_FAILSAFE) - 1) == 0)) { + *flags &= ~BAM_ENTRY_DBOOT; + } else { + bam_error(NO_KERNEL_MATCH, linep->lineNum, MENU_URL(root)); + return (BAM_ERROR); + } + + if (((*flags & BAM_ENTRY_DBOOT) && (bam_direct == BAM_DIRECT_DBOOT)) || + (((*flags & BAM_ENTRY_DBOOT) == 0) && + (bam_direct == BAM_DIRECT_MULTIBOOT))) { + + /* No action needed */ + return (BAM_SUCCESS); + } + + if (*flags & BAM_ENTRY_MINIROOT) { + /* + * We're changing boot architectures - make sure + * the multiboot failsafe still exists. + */ + (void) snprintf(path, PATH_MAX, "%s%s", root, + (*flags & BAM_ENTRY_DBOOT) ? MULTI_BOOT_FAILSAFE : + DIRECT_BOOT_FAILSAFE_KERNEL); + if (stat(path, &sb) != 0) { + if (bam_verbose) { + bam_error(FAILSAFE_MISSING, linep->lineNum); + } + return (BAM_SUCCESS); + } + } + + /* + * Make sure we have the correct cmd - either kernel or kernel$ + * The failsafe entry should always be KERNEL_CMD. + */ + which = ((bam_direct == BAM_DIRECT_MULTIBOOT) || + (*flags & BAM_ENTRY_MINIROOT)) ? KERNEL_CMD : KERNEL_DOLLAR_CMD; + free(linep->cmd); + len = strlen(menu_cmds[which]) + 1; + linep->cmd = s_calloc(1, len); + (void) strncpy(linep->cmd, menu_cmds[which], len); + + /* + * Since all arguments are copied, the new arg string should be close + * in size to the old one. Just add 32 to cover the difference in + * the boot path. + */ + total_len = strlen(linep->arg) + 32; + new_arg = s_calloc(1, total_len); + old_ptr = strchr(linep->arg, ' '); + if (old_ptr != NULL) + old_ptr++; + + /* + * Transitioning from dboot to multiboot is pretty simple. We + * copy in multiboot and any args. + */ + if (bam_direct == BAM_DIRECT_MULTIBOOT) { + if (old_ptr == NULL) { + (void) snprintf(new_arg, total_len, "%s", + (*flags & BAM_ENTRY_MINIROOT) ? + MULTI_BOOT_FAILSAFE : MULTI_BOOT); + } else { + (void) snprintf(new_arg, total_len, "%s %s", + (*flags & BAM_ENTRY_MINIROOT) ? + MULTI_BOOT_FAILSAFE : MULTI_BOOT, old_ptr); + } + goto done; + } + + /* + * Transitioning from multiboot to directboot is a bit more + * complicated, since we may have two sets of arguments to + * copy and a unix path to parse. + * + * First, figure out if there's a unix path. + */ + if ((old_ptr != NULL) && + ((unix_ptr = strstr(old_ptr, "/unix")) != NULL)) { + /* See if there's anything past unix */ + flags2_ptr = unix_ptr + sizeof ("/unix"); + if (*flags2_ptr == '\0') { + flags2_ptr = NULL; + } + + while ((unix_ptr > old_ptr) && (*unix_ptr != ' ')) + unix_ptr--; + + if (unix_ptr == old_ptr) { + flags1_ptr = NULL; + } else { + flags1_ptr = old_ptr; + } + + if (strstr(unix_ptr, "kernel/unix") != NULL) { + *flags |= BAM_ENTRY_32BIT; + } else if ((strstr(unix_ptr, "kernel/amd64/unix") == NULL) && + (!bam_force)) { + /* + * If the above strstr returns NULL, but bam_force is + * set, we'll be upgrading an Install kernel. The + * result probably won't be what was intended, but we'll + * try it anyways. + */ + return (BAM_SKIP); + } + } else if (old_ptr != NULL) { + flags1_ptr = old_ptr; + unix_ptr = flags1_ptr + strlen(old_ptr); + flags2_ptr = NULL; + } else { + unix_ptr = flags1_ptr = flags2_ptr = NULL; + } + + if (*flags & BAM_ENTRY_MINIROOT) { + (void) snprintf(new_arg, total_len, "%s", + DIRECT_BOOT_FAILSAFE_KERNEL); + } else if (*flags & BAM_ENTRY_32BIT) { + (void) snprintf(new_arg, total_len, "%s", DIRECT_BOOT_32); + } else { + (void) snprintf(new_arg, total_len, "%s", DIRECT_BOOT_KERNEL); + } + + /* + * We now want to copy flags1_ptr through unix_ptr, and + * flags2_ptr through the end of the string + */ + if (flags1_ptr != NULL) { + len = strlcat(new_arg, " ", total_len); + left = total_len - len; + new_ptr = new_arg + len; + + if ((unix_ptr - flags1_ptr) < left) + left = (unix_ptr - flags1_ptr) + 1; + (void) strlcpy(new_ptr, flags1_ptr, left); + } + if (flags2_ptr != NULL) { + (void) strlcat(new_arg, " ", total_len); + (void) strlcat(new_arg, flags2_ptr, total_len); + } + +done: + free(linep->arg); + linep->arg = new_arg; + update_line(linep); + return (BAM_SUCCESS); +} + +/* + * Similar to above, except this time we're looking at a module line, + * which is quite a bit simpler. + * + * Under multiboot, the archive line is: + * + * module /platform/i86pc/boot_archive + * + * Under directboot, the archive line is: + * + * module$ /platform/i86pc/$ISADIR/boot_archive + * + * which may be specified exactly as either of: + * + * module /platform/i86pc/boot_archive + * module /platform/i86pc/amd64/boot_archive + * + * For either dboot or multiboot, the failsafe is: + * + * module /boot/x86.miniroot-safe + */ +static error_t +parse_module_line(line_t *linep, const char *root, uint8_t flags) +{ + int len; + menu_cmd_t which; + char *new; + + /* + * If necessary, BAM_ENTRY_MINIROOT was already set in flags + * in upgrade_menu(). We re-check BAM_ENTRY_DBOOT here in here + * in case the kernel and module lines differ. + */ + if ((strcmp(linep->arg, DIRECT_BOOT_ARCHIVE) == 0) || + (strcmp(linep->arg, DIRECT_BOOT_ARCHIVE_64) == 0)) { + flags |= BAM_ENTRY_DBOOT; + } else if ((strcmp(linep->arg, MULTI_BOOT_ARCHIVE) == 0) || + (strcmp(linep->arg, MINIROOT) == 0)) { + flags &= ~BAM_ENTRY_DBOOT; + } else { + bam_error(NO_MODULE_MATCH, linep->lineNum, MENU_URL(root)); + return (BAM_ERROR); + } + + if (((flags & BAM_ENTRY_DBOOT) && (bam_direct == BAM_DIRECT_DBOOT)) || + (((flags & BAM_ENTRY_DBOOT) == 0) && + (bam_direct == BAM_DIRECT_MULTIBOOT)) || + ((flags & BAM_ENTRY_MINIROOT) && + (strcmp(linep->cmd, menu_cmds[MODULE_CMD]) == 0))) { + + /* No action needed */ + return (BAM_SUCCESS); + } + + /* + * Make sure we have the correct cmd - either module or module$ + * The failsafe entry should always be MODULE_CMD. + */ + which = ((bam_direct == BAM_DIRECT_MULTIBOOT) || + (flags & BAM_ENTRY_MINIROOT)) ? MODULE_CMD : MODULE_DOLLAR_CMD; + free(linep->cmd); + len = strlen(menu_cmds[which]) + 1; + linep->cmd = s_calloc(1, len); + (void) strncpy(linep->cmd, menu_cmds[which], len); + + if (flags & BAM_ENTRY_MINIROOT) { + new = MINIROOT; + } else if ((bam_direct == BAM_DIRECT_DBOOT) && + ((flags & BAM_ENTRY_32BIT) == 0)) { + new = DIRECT_BOOT_ARCHIVE; + } else { + new = MULTI_BOOT_ARCHIVE; + } + + free(linep->arg); + len = strlen(new) + 1; + linep->arg = s_calloc(1, len); + (void) strncpy(linep->arg, new, len); + update_line(linep); + + return (BAM_SUCCESS); +} + +/*ARGSUSED*/ +error_t +upgrade_menu(menu_t *mp, char *root, char *opt) +{ + entry_t *cur_entry; + line_t *cur_line; + int i, skipit = 0, num_entries = 0; + int *hand_entries = NULL; + boolean_t found_kernel = B_FALSE; + error_t rv; + char *rootdev, *grubdisk = NULL; + + rootdev = get_special(root); + if (rootdev) { + grubdisk = os_to_grubdisk(rootdev, strlen(root) == 1); + free(rootdev); + rootdev = NULL; + } + + /* Loop through all OS entries in the menu.lst file */ + for (cur_entry = mp->entries; cur_entry != NULL; + cur_entry = cur_entry->next, skipit = 0) { + + if ((cur_entry->flags & BAM_ENTRY_CHAINLOADER) || + ((cur_entry->flags & BAM_ENTRY_MINIROOT) && !bam_force)) + continue; + + /* + * We only change entries added by bootadm and live upgrade, + * and warn on the rest, unless the -f flag was passed. + */ + if ((!(cur_entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU))) && + !bam_force) { + if (num_entries == 0) { + hand_entries = s_calloc(1, sizeof (int)); + } else { + hand_entries = s_realloc(hand_entries, + (num_entries + 1) * sizeof (int)); + } + hand_entries[num_entries++] = cur_entry->entryNum; + continue; + } + + /* + * We make two loops through the lines. First, we check if + * there is a root entry, and if so, whether we should be + * checking this entry. + */ + if ((grubdisk != NULL) && (cur_entry->flags & BAM_ENTRY_ROOT)) { + for (cur_line = cur_entry->start; cur_line != NULL; + cur_line = cur_line->next) { + if ((cur_line->cmd == NULL) || + (cur_line->arg == NULL)) + continue; + + if (strcmp(cur_line->cmd, + menu_cmds[ROOT_CMD]) == 0) { + if (strcmp(cur_line->arg, + grubdisk) != 0) { + /* A different slice */ + skipit = 1; + } + break; + } + if (cur_line == cur_entry->end) + break; + } + } + if (skipit) + continue; + + for (cur_line = cur_entry->start; cur_line != NULL; + cur_line = cur_line->next) { + + /* + * We only compare for the length of KERNEL_CMD, + * so that KERNEL_DOLLAR_CMD will also match. + */ + if (strncmp(cur_line->cmd, menu_cmds[KERNEL_CMD], + strlen(menu_cmds[KERNEL_CMD])) == 0) { + rv = parse_kernel_line(cur_line, root, + &(cur_entry->flags)); + if (rv == BAM_SKIP) { + break; + } else if (rv != BAM_SUCCESS) { + return (rv); + } + found_kernel = B_TRUE; + } else if (strncmp(cur_line->cmd, + menu_cmds[MODULE_CMD], + strlen(menu_cmds[MODULE_CMD])) == 0) { + rv = parse_module_line(cur_line, root, + cur_entry->flags); + if (rv != BAM_SUCCESS) { + return (rv); + } + } + if (cur_line == cur_entry->end) + break; + } + } + + /* + * We only want to output one error, to avoid confusing a user. We + * rank "No kernels changed" as a higher priority than "will not + * update hand-added entries", since the former implies the latter. + */ + if (found_kernel == B_FALSE) { + bam_error(NO_KERNELS_FOUND, MENU_URL(root)); + return (BAM_ERROR); + } else if (num_entries > 0) { + bam_error(HAND_ADDED_ENTRY, MENU_URL(root)); + bam_print_stderr("Entry Number%s: ", (num_entries > 1) ? + "s" : ""); + for (i = 0; i < num_entries; i++) { + bam_print_stderr("%d ", hand_entries[i]); + } + bam_print_stderr("\n"); + } + return (BAM_WRITE); +} diff --git a/usr/src/cmd/boot/bootadm/message.h b/usr/src/cmd/boot/bootadm/message.h index 0eb28e12b4..6d6dee45d2 100644 --- a/usr/src/cmd/boot/bootadm/message.h +++ b/usr/src/cmd/boot/bootadm/message.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,6 +32,8 @@ extern "C" { #endif +#include <libintl.h> + #define FILE_MISS gettext("file not found: %s\n") #define ARCH_EXEC_MISS gettext("archive creation file not found: %s: %s\n") @@ -130,6 +132,8 @@ extern "C" { #define INVALID_ROOT gettext("invalid root entry: %s\n") +#define NO_KERNEL gettext("No kernel line found in entry %d\n") + #define INVALID_KERNEL gettext("invalid kernel entry: %s\n") #define INVALID_MODULE gettext("invalid module entry: %s\n") @@ -179,6 +183,8 @@ extern "C" { #define UNLOCK_FAIL gettext("failed to unlock file: %s: %s\n") +#define MMAP_FAIL gettext("failed to mmap file: %s: %s\n") + #define FILE_LOCKED gettext("Another instance of bootadm (pid %u) is running\n") #define FLIST_FAIL \ @@ -198,7 +204,7 @@ extern "C" { #define RDONLY_FS gettext("read-only filesystem: %s\n") -#define ARCHIVE_FAIL gettext("failed to create boot archive: %s\n") +#define ARCHIVE_FAIL gettext("Command '%s' failed to create boot archive\n") #define ARCHIVE_NOT_CREATED gettext("couldn't create boot archive: %s\n") @@ -321,6 +327,44 @@ the failsafe archive unbootable\n") #define FILE_REMOVE_FAILED \ gettext("Failed to delete one or more of (%s,%s). Remove manually.\n") +#define UNKNOWN_KERNEL gettext("Unable to expand %s to a full file path.\n") + +#define NOT_DBOOT \ + gettext("bootadm set-menu %s may only be run on directboot kernels.\n") + +#define DEFAULT_NOT_BAM \ +gettext("Default menu.lst entry is not controlled by bootadm. Exiting\n") + +#define NO_KERNEL_MATCH \ +gettext("Unexpected kernel command on line %d.\n\ +** YOU MUST MANUALLY CORRECT menu.lst BEFORE REBOOT! **\n\ +For details, see %s\n") + +#define NO_MODULE_MATCH \ +gettext("Unexpected module command on line %d.\n\ +** YOU MUST MANUALLY CORRECT menu.lst BEFORE REBOOT! **\n\ +For details, see %s\n") + +#define NO_KERNELS_FOUND \ +gettext("Could not find any kernel lines to update. Only entries created by\n\ +bootadm(1M) and lu(1M) can be updated. All other must be manually changed.\n\ +** YOU MUST MANUALLY CORRECT menu.lst BEFORE REBOOT! **\n\ +For details on updating entries, see %s\n") + +#define HAND_ADDED_ENTRY \ +gettext("On upgrades, bootadm(1M) will only upgrade entries added by\n\ +bootadm(1M) or lu(1M). The following entry or entries in menu.lst will\n\ +not be upgraded. For details on updating entries, see\n\ +%s\n") + +#define NOT_ELF_FILE gettext("%s is not an ELF file.\n") + +#define WRONG_ELF_CLASS gettext("%s is wrong ELF class 0x%x\n") + +#define FAILSAFE_MISSING \ +gettext("bootadm -m upgrade run, but the failsafe archives have not been\n\ +updated. Not updating line %d\n") + #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/boot/scripts/Makefile.com b/usr/src/cmd/boot/scripts/Makefile.com index 8cd77a555d..b8fe31bc54 100644 --- a/usr/src/cmd/boot/scripts/Makefile.com +++ b/usr/src/cmd/boot/scripts/Makefile.com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -30,7 +30,7 @@ MANIFEST= boot-archive-update.xml SVCMETHOD= boot-archive-update -PROG= create_ramdisk create_diskmap +PROG= create_ramdisk create_diskmap update_grub METHODPROG= boot-archive-update SBINPROG= root_archive diff --git a/usr/src/cmd/boot/scripts/create_ramdisk.ksh b/usr/src/cmd/boot/scripts/create_ramdisk.ksh index f26dde26a1..85a5082780 100644 --- a/usr/src/cmd/boot/scripts/create_ramdisk.ksh +++ b/usr/src/cmd/boot/scripts/create_ramdisk.ksh @@ -20,33 +20,39 @@ # CDDL HEADER END # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # ident "%Z%%M% %I% %E% SMI" format=ufs ALT_ROOT= -NO_AMD64= +compress=yes +SPLIT=unknown +ERROR=0 BOOT_ARCHIVE=platform/i86pc/boot_archive +BOOT_ARCHIVE_64=platform/i86pc/amd64/boot_archive export PATH=$PATH:/usr/sbin:/usr/bin:/sbin # # Parse options # -while getopts R: OPT 2> /dev/null +while [ "$1" != "" ] do - case $OPT in - R) ALT_ROOT="$OPTARG" + case $1 in + -R) shift + ALT_ROOT="$1" if [ "$ALT_ROOT" != "/" ]; then echo "Creating ram disk for $ALT_ROOT" fi ;; - ?) echo Usage: ${0##*/}: [-R \<root\>] + -n|--nocompress) compress=no ;; + *) echo Usage: ${0##*/}: [-R \<root\>] [--nocompress] exit ;; esac + shift done if [ -x /usr/bin/mkisofs -o -x /tmp/bfubin/mkisofs ] ; then @@ -59,7 +65,7 @@ fi # release=`uname -r` if [ "$release" = "5.8" ]; then - format=ufs + format=ufs fi shift `expr $OPTIND - 1` @@ -69,18 +75,34 @@ if [ $# -eq 1 ]; then echo "Creating ram disk for $ALT_ROOT" fi +rundir=`dirname $0` +if [ ! -x $rundir/symdef ]; then + # Shouldn't happen + echo "Warning: $rundir/symdef not present." + echo "Creating single archive at $ALT_ROOT/platform/i86pc/boot_archive" + SPLIT=no + compress=no +elif $rundir/symdef "$ALT_ROOT"/platform/i86pc/kernel/unix \ + dboot_image 2>/dev/null; then + SPLIT=yes +else + SPLIT=no + compress=no +fi + +[ -x /usr/bin/gzip ] || compress=no + function cleanup { - umount -f "$rdmnt" 2>/dev/null - lofiadm -d "$rdfile" 2>/dev/null + umount -f "$rdmnt32" 2>/dev/null + umount -f "$rdmnt64" 2>/dev/null + lofiadm -d "$rdfile32" 2>/dev/null + lofiadm -d "$rdfile64" 2>/dev/null rm -fr "$rddir" 2> /dev/null } function getsize { - # should we exclude amd64 binaries? - [ $is_amd64 -eq 0 ] && NO_AMD64="-type d -name amd64 -prune -o" - # Estimate image size and add %10 overhead for ufs stuff. # Note, we can't use du here in case we're on a filesystem, e.g. zfs, # in which the disk usage is less than the sum of the file sizes. @@ -93,87 +115,225 @@ function getsize # with directories. This results in a total size that's slightly # bigger than if du was called on a ufs directory. total_size=$(cd "/$ALT_ROOT" - find $filelist $NO_AMD64 -ls 2>/dev/null | nawk ' + find $filelist -ls 2>/dev/null | nawk ' {t += ($7 % 1024) ? (int($7 / 1024) + 1) * 1024 : $7} END {print int(t * 1.10 / 1024)}') } +# +# The first argument can be: +# +# "both" - create an archive with both 32-bit and 64-bit binaries +# "32-bit" - create an archive with only 32-bit binaries +# "64-bit" - create an archive with only 64-bit binaries +# function create_ufs { + which=$1 + archive=$2 + lofidev=$3 + # should we exclude amd64 binaries? - [ $is_amd64 -eq 0 ] && NO_AMD64="-type d -name amd64 -prune -o" + if [ "$which" = "32-bit" ]; then + NO_AMD64="-type d -name amd64 -prune -o" + rdfile="$rdfile32" + rdmnt="$rdmnt32" + elif [ "$which" = "64-bit" ]; then + NO_AMD64="" + rdfile="$rdfile64" + rdmnt="$rdmnt64" + else + NO_AMD64="" + rdfile="$rdfile32" + rdmnt="$rdmnt32" + fi - mkfile ${total_size}k "$rdfile" - lofidev=`lofiadm -a "$rdfile"` newfs $lofidev < /dev/null 2> /dev/null mkdir "$rdmnt" mount -F mntfs mnttab /etc/mnttab > /dev/null 2>&1 mount -o nologging $lofidev "$rdmnt" + files= # do the actual copy cd "/$ALT_ROOT" - find $filelist $NO_AMD64 -print 2> /dev/null | \ - cpio -pdum "$rdmnt" 2> /dev/null + for path in `find $filelist $NO_AMD64 -type f -print 2> /dev/null` + do + if [ "$which" = "both" ]; then + files="$files $path" + else + filetype=`file $path 2>/dev/null |\ + awk '/ELF/ { print \$3 }'` + if [ -z "$filetype" ] || [ "$filetype" = "$which" ] + then + files="$files $path" + fi + fi + done + if [ $compress = yes ]; then + ls $files | while read path + do + dir="${path%/*}" + mkdir -p "$rdmnt/$dir" + /usr/bin/gzip -c "$path" > "$rdmnt/$path" + done + else + ls $files | cpio -pdum "$rdmnt" 2> /dev/null + fi umount "$rdmnt" - lofiadm -d "$rdfile" rmdir "$rdmnt" + # # Check if gzip exists in /usr/bin, so we only try to run gzip # on systems that have gzip. Then run gzip out of the patch to # pick it up from bfubin or something like that if needed. # - if [ -x /usr/bin/gzip ] ; then - gzip -c "$rdfile" > "$ALT_ROOT/$BOOT_ARCHIVE-new" + # If compress is set, the individual files in the archive are + # compressed, and the final compression will accomplish very + # little. To save time, we skip the gzip in this case. + # + if [ $compress = no ] && [ -x /usr/bin/gzip ] ; then + gzip -c "$rdfile" > "${archive}-new" else - cat "$rdfile" > "$ALT_ROOT/$BOOT_ARCHIVE-new" + cat "$rdfile" > "${archive}-new" fi } +# +# The first argument can be: +# +# "both" - create an archive with both 32-bit and 64-bit binaries +# "32-bit" - create an archive with only 32-bit binaries +# "64-bit" - create an archive with only 64-bit binaries +# function create_isofs { + which=$1 + archive=$2 + # should we exclude amd64 binaries? - [ $is_amd64 = 0 ] && NO_AMD64="-m amd64" + if [ "$which" = "32-bit" ]; then + NO_AMD64="-type d -name amd64 -prune -o" + rdmnt="$rdmnt32" + errlog="$errlog32" + elif [ "$which" = "64-bit" ]; then + NO_AMD64="" + rdmnt="$rdmnt64" + errlog="$errlog64" + else + NO_AMD64="" + rdmnt="$rdmnt32" + errlog="$errlog32" + fi # create image directory seed with graft points mkdir "$rdmnt" files= - isocmd="mkisofs -quiet -graft-points -dlrDJN -relaxed-filenames $NO_AMD64" - for path in $filelist + isocmd="mkisofs -quiet -graft-points -dlrDJN -relaxed-filenames" + + cd "/$ALT_ROOT" + for path in `find $filelist $NO_AMD64 -type f -print 2> /dev/null` do - if [ -d "$ALT_ROOT/$path" ]; then - isocmd="$isocmd $path/=\"$ALT_ROOT/$path\"" - mkdir -p "$rdmnt/$path" - elif [ -f "$ALT_ROOT/$path" ]; then + if [ "$which" = "both" ]; then files="$files $path" + else + filetype=`file $path 2>/dev/null |\ + awk '/ELF/ { print \$3 }'` + if [ -z "$filetype" ] || [ "$filetype" = "$which" ] + then + files="$files $path" + fi fi done - cd "/$ALT_ROOT" - find $files 2> /dev/null | cpio -pdum "$rdmnt" 2> /dev/null + if [ $compress = yes ]; then + ls $files | while read path + do + dir="${path%/*}" + mkdir -p "$rdmnt/$dir" + /usr/bin/gzip -c "$path" > "$rdmnt/$path" + done + else + ls $files | cpio -pdum "$rdmnt" 2> /dev/null + fi isocmd="$isocmd \"$rdmnt\"" rm -f "$errlog" + # # Check if gzip exists in /usr/bin, so we only try to run gzip # on systems that have gzip. Then run gzip out of the patch to # pick it up from bfubin or something like that if needed. # - if [ -x /usr/bin/gzip ] ; then + # If compress is set, the individual files in the archive are + # compressed, and the final compression will accomplish very + # little. To save time, we skip the gzip in this case. + # + if [ $compress = no ] && [ -x /usr/bin/gzip ] ; then ksh -c "$isocmd" 2> "$errlog" | \ - gzip > "$ALT_ROOT/$BOOT_ARCHIVE-new" + gzip > "${archive}-new" else - ksh -c "$isocmd" 2> "$errlog" > "$ALT_ROOT/$BOOT_ARCHIVE-new" + ksh -c "$isocmd" 2> "$errlog" > "${archive}-new" fi if [ -s "$errlog" ]; then grep Error: "$errlog" >/dev/null 2>&1 if [ $? -eq 0 ]; then grep Error: "$errlog" - rm -f "$ALT_ROOT/$BOOT_ARCHIVE-new" + rm -f "${archive}-new" fi fi rm -f "$errlog" } +function create_archive +{ + which=$1 + archive=$2 + lofidev=$3 + + echo "updating $archive...this may take a minute" + + if [ "$format" = "ufs" ]; then + create_ufs "$which" "$archive" "$lofidev" + else + create_isofs "$which" "$archive" + fi + + # sanity check the archive before moving it into place + # + ARCHIVE_SIZE=`du -k "${archive}-new" | cut -f 1` + if [ $compress = yes ] + then + # + # 'file' will report "English text" for uncompressed + # boot_archives. Checking for that doesn't seem stable, + # so we just check that the file exists. + # + ls "${archive}-new" >/dev/null 2>&1 + else + # + # the file type check also establishes that the + # file exists at all + # + file "${archive}-new" | grep gzip > /dev/null + fi + + if [ $? = 1 ] && [ -x /usr/bin/gzip ] || [ $ARCHIVE_SIZE -lt 5000 ] + then + # + # Two of these functions may be run in parallel. We + # need to allow the other to clean up, so we can't + # exit immediately. Instead, we set a flag. + # + echo "update of $archive failed" + ERROR=1 + else + lockfs -f "/$ALT_ROOT" 2>/dev/null + mv "${archive}-new" "$archive" + lockfs -f "/$ALT_ROOT" 2>/dev/null + fi + +} + # # get filelist # @@ -186,33 +346,35 @@ then fi filelist=$(sort -u $files) -# -# decide if cpu is amd64 capable -# -prtconf -v /devices | grep CPU_not_amd64 > /dev/null 2>&1 -is_amd64=$? - scratch=tmp if [ $format = ufs ] ; then # calculate image size getsize + # We do two mkfile's of total_size, so double the space + (( tmp_needed = total_size * 2 )) + # check to see if there is sufficient space in tmpfs # tmp_free=`df -b /tmp | tail -1 | awk '{ printf ($2) }'` (( tmp_free = tmp_free / 2 )) - if [ $total_size -gt $tmp_free ] ; then + if [ $tmp_needed -gt $tmp_free ] ; then # assumes we have enough scratch space on $ALT_ROOT scratch="$ALT_ROOT" fi fi rddir="/$scratch/create_ramdisk.$$.tmp" -rdfile="$rddir/rd.file" -rdmnt="$rddir/rd.mount" -errlog="$rddir/rd.errlog" +rdfile32="$rddir/rd.file.32" +rdfile64="$rddir/rd.file.64" +rdmnt32="$rddir/rd.mount.32" +rdmnt64="$rddir/rd.mount.64" +errlog32="$rddir/rd.errlog.32" +errlog64="$rddir/rd.errlog.64" +lofidev32="" +lofidev64="" # make directory for temp files safely rm -rf "$rddir" @@ -221,46 +383,46 @@ mkdir "$rddir" # Clean up upon exit. trap 'cleanup' EXIT -echo "updating $ALT_ROOT/$BOOT_ARCHIVE...this may take a minute" - -if [ $format = "ufs" ]; then - create_ufs +if [ $SPLIT = yes ]; then + # + # We can't run lofiadm commands in parallel, so we have to do + # them here. + # + if [ "$format" = "ufs" ]; then + mkfile ${total_size}k "$rdfile32" + lofidev32=`lofiadm -a "$rdfile32"` + mkfile ${total_size}k "$rdfile64" + lofidev64=`lofiadm -a "$rdfile64"` + fi + create_archive "32-bit" "$ALT_ROOT/$BOOT_ARCHIVE" $lofidev32 & + create_archive "64-bit" "$ALT_ROOT/$BOOT_ARCHIVE_64" $lofidev64 + wait + if [ "$format" = "ufs" ]; then + lofiadm -d "$rdfile32" + lofiadm -d "$rdfile64" + fi else - create_isofs + if [ "$format" = "ufs" ]; then + mkfile ${total_size}k "$rdfile32" + lofidev32=`lofiadm -a "$rdfile32"` + fi + create_archive "both" "$ALT_ROOT/$BOOT_ARCHIVE" $lofidev32 + [ "$format" = "ufs" ] && lofiadm -d "$rdfile32" fi - -# Make sure $BOOT_ARCHIVE-new created by either create_ufs or creat_isofs -# above is flushed to the backing store before we do anything with it. -lockfs -f "/$ALT_ROOT" - -# sanity check the archive before moving it into place -# the file type check also establishes that the file exists at all -# -ARCHIVE_SIZE=$(/bin/ls -l "$ALT_ROOT/$BOOT_ARCHIVE-new" | - nawk '{print int($5 / 1024)}') -file "$ALT_ROOT/$BOOT_ARCHIVE-new" | grep gzip > /dev/null - -if [ $? = 1 ] && [ -x /usr/bin/gzip ] || [ $ARCHIVE_SIZE -lt 5000 ]; then - echo "update of $ALT_ROOT/$BOOT_ARCHIVE failed" - rm -rf "$rddir" +if [ $ERROR = 1 ]; then + cleanup exit 1 fi # # For the diskless case, hardlink archive to /boot to make it # visible via tftp. /boot is lofs mounted under /tftpboot/<hostname>. -# NOTE: this script must work on both client and server +# NOTE: this script must work on both client and server. # grep "[ ]/[ ]*nfs[ ]" "$ALT_ROOT/etc/vfstab" > /dev/null if [ $? = 0 ]; then - mv "$ALT_ROOT/$BOOT_ARCHIVE-new" "$ALT_ROOT/$BOOT_ARCHIVE" - rm -f "$ALT_ROOT/boot/boot_archive" + rm -f "$ALT_ROOT/boot/boot_archive" "$ALT_ROOT/boot/amd64/boot_archive" ln "$ALT_ROOT/$BOOT_ARCHIVE" "$ALT_ROOT/boot/boot_archive" - rm -rf "$rddir" - exit + ln "$ALT_ROOT/$BOOT_ARCHIVE_64" "$ALT_ROOT/boot/amd64/boot_archive" fi - -mv "$ALT_ROOT/$BOOT_ARCHIVE-new" "$ALT_ROOT/$BOOT_ARCHIVE" -lockfs -f "/$ALT_ROOT" - rm -rf "$rddir" diff --git a/usr/src/cmd/boot/scripts/root_archive.ksh b/usr/src/cmd/boot/scripts/root_archive.ksh index 40bd1cd755..7321c23e2c 100644 --- a/usr/src/cmd/boot/scripts/root_archive.ksh +++ b/usr/src/cmd/boot/scripts/root_archive.ksh @@ -20,7 +20,7 @@ # CDDL HEADER END # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -111,7 +111,7 @@ packmedia() RELEASE=`basename "$RELEASE"` mkdir -p "$MEDIA/$RELEASE/Tools/Boot" - mkdir -p "$MEDIA/boot" + mkdir -p "$MEDIA/boot/platform/i86pc/kernel" # archive package databases to conserve memory # @@ -134,6 +134,8 @@ packmedia() archive_X "$MEDIA" "$MINIROOT" cp "$MINIROOT/platform/i86pc/multiboot" "$MEDIA/boot" + cp "$MINIROOT/platform/i86pc/kernel/unix" \ + "$MEDIA/boot/platform/i86pc/kernel/unix" # copy the install menu to menu.lst so we have a menu # on the install media diff --git a/usr/src/cmd/boot/scripts/update_grub.ksh b/usr/src/cmd/boot/scripts/update_grub.ksh new file mode 100644 index 0000000000..86a2ee65c8 --- /dev/null +++ b/usr/src/cmd/boot/scripts/update_grub.ksh @@ -0,0 +1,125 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# ident "%Z%%M% %I% %E% SMI" + +PATH="/usr/bin:/usr/sbin:${PATH}"; export PATH +ALT_ROOT= + +while getopts R: OPT 2>/dev/null +do + case $OPT in + R) ALT_ROOT="$OPTARG" + ;; + ?) echo "Usage: ${0##*/}: [-R \<root\>]" + ;; + esac +done + +ARCH=`uname -p` + +is_pcfs_boot=yes + +check_pcfs_boot() +{ + bootdev=`grep -v "^#" "$ALT_ROOT"/etc/vfstab | grep pcfs \ + | grep "[ ]/stubboot[ ]" | nawk '{print $1}'` + if [ X"$bootdev" = "X" ]; then + is_pcfs_boot=no + fi +} + +# +# Detect SVM root and return the list of raw devices under the mirror +# +get_rootdev_list() +{ + if [ -f "$ALT_ROOT"/etc/lu/GRUB_slice ]; then + grep '^PHYS_SLICE' "$ALT_ROOT"/etc/lu/GRUB_slice | cut -d= -f2 + else + metadev=`grep -v "^#" "$ALT_ROOT"/etc/vfstab | \ + grep "[ ]/[ ]" | nawk '{print $2}'` + if [[ $metadev = /dev/rdsk/* ]]; then + rootdevlist=`echo "$metadev" | sed -e "s#/dev/rdsk/##"` + elif [[ $metadev = /dev/md/rdsk/* ]]; then + metavol=`echo "$metadev" | sed -e "s#/dev/md/rdsk/##"` + rootdevlist=`metastat -p $metavol |\ + grep -v "^$metavol[ ]" | nawk '{print $4}'` + fi + for rootdev in $rootdevlist + do + echo /dev/rdsk/$rootdev + done + fi +} + +# +# multiboot: install grub on the boot slice +# +install_grub() +{ + # Stage 2 blocks must remain untouched + STAGE1="$ALT_ROOT"/boot/grub/stage1 + STAGE2="$ALT_ROOT"/boot/grub/stage2 + + if [ $is_pcfs_boot = yes ]; then + # + # Note: /stubboot/boot/grub/stage2 must stay untouched. + # + mkdir -p "$ALT_ROOT"/stubboot/boot/grub + cp "$ALT_ROOT"/boot/grub/menu.lst "$ALT_ROOT"/stubboot/boot/grub + bootdev=`grep -v "^#" "$ALT_ROOT"/etc/vfstab | grep pcfs | \ + grep "[ ]/stubboot[ ]" | nawk '{print $1}'` + rpcfsdev=`echo "$bootdev" | sed -e "s/dev\/dsk/dev\/rdsk/"` + if [ X"$rpcfsdev" != X ]; then + print "Installing grub on $rpcfsdev" + "$ALT_ROOT"/sbin/installgrub $STAGE1 $STAGE2 $rpcfsdev + fi + fi + + get_rootdev_list | while read rootdev + do + if [ X"$rpcfsdev" != X ]; then + echo "create GRUB menu in "$ALT_ROOT"/stubboot" + "$ALT_ROOT"/sbin/bootadm update-menu \ + -R "$ALT_ROOT"/stubboot -o $rootdev,"$ALT_ROOT" + else + echo "Creating GRUB menu in ${ALT_ROOT:-/}" + $ALT_ROOT/sbin/bootadm update-menu -R ${ALT_ROOT:-/} \ + -o $rootdev + fi + print "Installing grub on $rootdev" + "$ALT_ROOT"/sbin/installgrub $STAGE1 $STAGE2 $rootdev + done +} + +if [ -f "$ALT_ROOT"/platform/i86pc/multiboot -a "$ARCH" = i386 ] ; then + check_pcfs_boot + install_grub +fi + +exit 0 diff --git a/usr/src/cmd/eeprom/i386/i86pc/Makefile b/usr/src/cmd/boot/symdef/Makefile index da26f7f3a7..dba76dea89 100644 --- a/usr/src/cmd/eeprom/i386/i86pc/Makefile +++ b/usr/src/cmd/boot/symdef/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,28 +19,40 @@ # CDDL HEADER END # # -# Copyright 1993, 2002 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" -# -# Platform specific Makefile for the eeprom command. -# -# PLATFORM is the target for the binary instalation. -# -# PLATLINKS is a list of platforms which are to be linked to this binary -# at the file level. -# -SRCDIR = ../.. -PLATFORM = i86pc -PLATLINKS = +# + +PROG= symdef + +OBJS= symdef.o +SRCS = $(OBJS:.o=.c) -include $(SRCDIR)/Makefile.com +include ../Makefile.com .KEEP_STATE: -all: $(PROG) +LDLIBS += -lelf + +# Writing into string literals is incorrect. We need to match gcc's +# behavior, which causes us to take SIGSEGV on such a write. +CFLAGS += $(XSTRCONST) + +all: $(PROG) + +$(PROG): $(OBJS) + $(LINK.c) -o $@ $(OBJS) $(LDLIBS) + $(POST_PROCESS) + +install: all $(ROOTBOOTSOLARISBINPROG) + +clean: + -$(RM) $(OBJS) + +_msg: -include $(SRCDIR)/Makefile.targ +lint: lint_SRCS -LDLIBS += -lgen +include ../Makefile.targ diff --git a/usr/src/cmd/boot/symdef/symdef.c b/usr/src/cmd/boot/symdef/symdef.c new file mode 100644 index 0000000000..4a0ddbc1a1 --- /dev/null +++ b/usr/src/cmd/boot/symdef/symdef.c @@ -0,0 +1,117 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <libelf.h> +#include <gelf.h> +#include <errno.h> + +/* + * symdef is a very simplified version of nm. It is used by upgrade and + * create_ramdisk in situations where we can't guarantee that nm will be around. + * + * Two arguments are expected: a binary and a symbol name. If the symbol is + * found in the name table of the binary, 0 is returned. If it is not found, + * 1 is returned. If an error occurs, a message is printed to stderr and -1 + * is returned. + */ + + +static void +usage(void) +{ + (void) fprintf(stderr, "USAGE: symdef file_name symbol\n"); +} + +int +main(int argc, char *argv[]) +{ + int fd = 0; + int rv = 1; + uint_t cnt, symcnt; + Elf *elfp = NULL; + Elf_Scn *scn = NULL; + size_t shstrndx; + GElf_Ehdr ehdr; + GElf_Shdr shdr; + GElf_Sym sym; + Elf32_Word shndx; + Elf_Data *symdata, *shndxdata; + + if (argc != 3) { + usage(); + return (-1); + } + + fd = open(argv[1], O_RDONLY); + if (fd == -1) { + (void) fprintf(stderr, "%s\n", strerror(errno)); + rv = -1; + goto done; + } + if (elf_version(EV_CURRENT) == EV_NONE) { + (void) fprintf(stderr, "Elf library version out of date\n"); + rv = -1; + goto done; + } + elfp = elf_begin(fd, ELF_C_READ, NULL); + if ((elfp == NULL) || (elf_kind(elfp) != ELF_K_ELF) || + ((gelf_getehdr(elfp, &ehdr)) == NULL) || + (elf_getshstrndx(elfp, &shstrndx) == 0)) + goto done; + + while ((scn = elf_nextscn(elfp, scn)) != NULL) { + if ((gelf_getshdr(scn, &shdr) == NULL) || + ((shdr.sh_type != SHT_SYMTAB) && + (shdr.sh_type != SHT_DYNSYM)) || + ((symdata = elf_getdata(scn, NULL)) == NULL)) + continue; + symcnt = shdr.sh_size / shdr.sh_entsize; + shndxdata = NULL; + for (cnt = 0; cnt < symcnt; cnt++) { + if ((gelf_getsymshndx(symdata, shndxdata, cnt, + &sym, &shndx) != NULL) && + (strcmp(argv[2], elf_strptr(elfp, shdr.sh_link, + sym.st_name)) == 0)) { + rv = 0; + goto done; + } + } + } +done: + if (elfp) + (void) elf_end(elfp); + if (fd != -1) + (void) close(fd); + return (rv); +} diff --git a/usr/src/cmd/devfsadm/i386/misc_link_i386.c b/usr/src/cmd/devfsadm/i386/misc_link_i386.c index f855486dee..95fb5895e8 100644 --- a/usr/src/cmd/devfsadm/i386/misc_link_i386.c +++ b/usr/src/cmd/devfsadm/i386/misc_link_i386.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -48,6 +48,7 @@ static int smbios(di_minor_t minor, di_node_t node); static int agp_process(di_minor_t minor, di_node_t node); static int drm_node(di_minor_t minor, di_node_t node); static int mc_node(di_minor_t minor, di_node_t node); +static int xsvc(di_minor_t minor, di_node_t node); static devfsadm_create_t misc_cbt[] = { { "vt00", "ddi_display", NULL, @@ -89,6 +90,9 @@ static devfsadm_create_t misc_cbt[] = { { "agp", "ddi_agp:master", NULL, TYPE_EXACT, ILEVEL_0, agp_process }, + { "pseudo", "ddi_pseudo", NULL, + TYPE_EXACT, ILEVEL_0, xsvc + }, { "memory-controller", "ddi_mem_ctrl", NULL, TYPE_EXACT, ILEVEL_0, mc_node } @@ -548,3 +552,22 @@ mc_node(di_minor_t minor, di_node_t node) (void) devfsadm_mklink(linkpath, node, minor, 0); return (DEVFSADM_CONTINUE); } + +/* + * Creates \M0 devlink for xsvc node + */ +static int +xsvc(di_minor_t minor, di_node_t node) +{ + char *mn; + + if (strcmp(di_node_name(node), "xsvc") != 0) + return (DEVFSADM_CONTINUE); + + mn = di_minor_name(minor); + if (mn == NULL) + return (DEVFSADM_CONTINUE); + + (void) devfsadm_mklink(mn, node, minor, 0); + return (DEVFSADM_CONTINUE); +} diff --git a/usr/src/cmd/eeprom/Makefile b/usr/src/cmd/eeprom/Makefile index 47011aeb75..9cda9fbd7b 100644 --- a/usr/src/cmd/eeprom/Makefile +++ b/usr/src/cmd/eeprom/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -27,31 +27,18 @@ # SUBDIRS= $(MACH) -MANIFEST=eeprom.xml - include ../Makefile.cmd -ROOTMANIFESTDIR = $(ROOTSVCPLATFORMI86PC) - -all:= TARGET= all -install:= TARGET= install -clean:= TARGET= clean -clobber:= TARGET= clobber -lint:= TARGET= lint - -PROG = eeprom -FILEMODE = 555 -GROUP = sys +all := TARGET= all +install := TARGET= install +clean := TARGET= clean +clobber := TARGET= clobber +lint := TARGET= lint +check := TARGET= check .KEEP_STATE: -all install clean clobber lint : $(SUBDIRS) - -install: $(SUBDIRS) $(ROOTMANIFEST) - $(RM) $(ROOTUSRSBINPROG) - $(LN) $(PLATEXEC) $(ROOTUSRSBINPROG) - -check: $(CHKMANIFEST) +all install clean clobber lint check: $(SUBDIRS) $(SUBDIRS): FRC @cd $@; pwd; $(MAKE) $(TARGET) diff --git a/usr/src/cmd/eeprom/Makefile.com b/usr/src/cmd/eeprom/Makefile.com index cc5944fd6f..0cc0be6f29 100644 --- a/usr/src/cmd/eeprom/Makefile.com +++ b/usr/src/cmd/eeprom/Makefile.com @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,12 +21,10 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1993,1998 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # -# cmd/eeprom/Makefile.com -# - + # # Create default so empty rules don't # confuse make @@ -35,7 +32,6 @@ CLASS = 32 include $(SRCDIR)/../Makefile.cmd -include $(SRCDIR)/../../Makefile.psm PROG = eeprom @@ -43,44 +39,15 @@ FILEMODE = 02555 DIRMODE = 755 GROUP = sys -# -# Sparc program implementation supports openprom machines. identical versions -# are installed in /usr/platform for each machine type -# because (at this point in time) we have no guarantee that a common version -# will be available for all potential sparc machines (eg: ICL, solbourne ,...). -# -# The identical binary is installed several times (rather than linking them -# together) because they will be in separate packages. -# -# Now that it should be obvious that little (if anything) was gained from -# this `fix-impl' implementation style, maybe somebody will unroll this in -# distinct, small and simpler versions for each PROM type. -# -IMPL = $(PLATFORM:sun%=sun) +OBJS = error.o -prep_OBJS = openprom.o loadlogo.o -sun_OBJS = openprom.o loadlogo.o -i86pc_OBJS = benv.o benv_kvm.o benv_sync.o -OBJS = error.o -OBJS += $($(IMPL)_OBJS) LINT_OBJS = $(OBJS:%.o=%.ln) - -prep_SOURCES = openprom.c loadlogo.c -sun_SOURCES = openprom.c loadlogo.c -i86pc_SOURCES = benv.c benv_kvm.c benv_syn.c -SOURCES = error.c -SOURCES += $($(IMPL)_SOURCES) +SOURCES = $(OBJS:%.o=%.c) .PARALLEL: $(OBJS) -%.o: ../common/%.c - $(COMPILE.c) -o $@ $< - %.o: $(SRCDIR)/common/%.c $(COMPILE.c) -o $@ $< %.ln: ../common/%.c $(LINT.c) -c $@ $< - -%.ln: $(SRCDIR)/common/%.c - $(LINT.c) -c $@ $< diff --git a/usr/src/cmd/eeprom/Makefile.targ b/usr/src/cmd/eeprom/Makefile.targ index 538108a183..1d819bdabc 100644 --- a/usr/src/cmd/eeprom/Makefile.targ +++ b/usr/src/cmd/eeprom/Makefile.targ @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,11 +21,13 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1993 by Sun Microsystems, Inc. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # # cmd/eeprom/Makefile.targ # -install: all $(USR_PSM_SBIN_PROG) $(USR_PSM_SBIN_PROG_LINKS) + +install: all $(ROOTUSRSBIN) $(ROOTUSRSBINPROG) $(PROG): $(OBJS) $(LINK.c) -o $@ $(OBJS) $(LDLIBS) @@ -35,9 +36,11 @@ $(PROG): $(OBJS) clean: -$(RM) $(OBJS) -$(RM) $(LINT_OBJS) + -$(RM) $(PROG) lint: $(LINT_OBJS) $(LINT.c) $(LINT_OBJS) +check: + include $(SRCDIR)/../Makefile.targ -include $(SRCDIR)/../../Makefile.psm.targ diff --git a/usr/src/cmd/eeprom/common/Makefile b/usr/src/cmd/eeprom/common/Makefile deleted file mode 100644 index 9828df5a79..0000000000 --- a/usr/src/cmd/eeprom/common/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright (c) 1995,1998 by Sun Microsystems, Inc. -# All rights reserved. -# -# cmd/eeprom/common/Makefile -# -include ../../Makefile.cmd - -PROG = eeprom -FILEMODE = 555 -GROUP = sys - -.KEEP_STATE: - -all install : $(ROOTUSRSBINPROG) - -clean clobber : FRC - $(RM) $(ROOTUSRSBINPROG) - -FRC: diff --git a/usr/src/cmd/eeprom/eeprom.xml b/usr/src/cmd/eeprom/eeprom.xml deleted file mode 100644 index 48db9f3599..0000000000 --- a/usr/src/cmd/eeprom/eeprom.xml +++ /dev/null @@ -1,81 +0,0 @@ -<?xml version="1.0"?> -<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"> -<!-- - Copyright 2005 Sun Microsystems, Inc. All rights reserved. - Use is subject to license terms. - - CDDL HEADER START - - The contents of this file are subject to the terms of the - Common Development and Distribution License, Version 1.0 only - (the "License"). You may not use this file except in compliance - with the License. - - You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - or http://www.opensolaris.org/os/licensing. - See the License for the specific language governing permissions - and limitations under the License. - - When distributing Covered Code, include this CDDL HEADER in each - file and include the License file at usr/src/OPENSOLARIS.LICENSE. - If applicable, add the following below this CDDL HEADER, with the - fields enclosed by brackets "[]" replaced with your own identifying - information: Portions Copyright [yyyy] [name of copyright owner] - - CDDL HEADER END - - ident "%Z%%M% %I% %E% SMI" - - NOTE: This service manifest is not editable; its contents will - be overwritten by package or patch operations, including - operating system upgrade. Make customizations in a different - file. ---> - -<service_bundle type='manifest' name='SUNWos86r:eeprom'> - -<service - name='platform/i86pc/eeprom' - type='service' - version='1'> - - <create_default_instance enabled='false' /> - - <single_instance /> - - <dependency - name='usr' - type='service' - grouping='require_all' - restart_on='none'> - <service_fmri value='svc:/system/filesystem/usr' /> - </dependency> - - <exec_method - type='method' - name='start' - exec='/usr/sbin/eeprom -I' - timeout_seconds='60'> - </exec_method> - - <property_group name='startd' type='framework'> - <propval name='duration' type='astring' - value='transient' /> - </property_group> - - <stability value='Unstable' /> - - <template> - <common_name> - <loctext xml:lang='C'> - EEPROM emulation - </loctext> - </common_name> - <documentation> - <manpage title='eeprom' section='1M' - manpath='/usr/share/man' /> - </documentation> - </template> -</service> - -</service_bundle> diff --git a/usr/src/cmd/eeprom/i386/Makefile b/usr/src/cmd/eeprom/i386/Makefile index 33c7bc2ccf..4c28dce186 100644 --- a/usr/src/cmd/eeprom/i386/Makefile +++ b/usr/src/cmd/eeprom/i386/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,23 +21,22 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1993 by Sun Microsystems, Inc. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # -# cmd/eeprom/i386/Makefile -# -SUBDIRS= i86pc -all:= TARGET= all -install:= TARGET= install -clean:= TARGET= clean -clobber:= TARGET= clobber -lint:= TARGET= lint +SRCDIR = .. -.KEEP_STATE: +include $(SRCDIR)/Makefile.com + +# We "borrow" some error messages from bootadm. Add the path to pick these up +CFLAGS += -I../../boot/bootadm +LINTFLAGS += -I../../boot/bootadm -all install clean clobber lint : $(SUBDIRS) +OBJS += benv.o benv_kvm.o + +.KEEP_STATE: -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) +all: $(PROG) -FRC: +include $(SRCDIR)/Makefile.targ diff --git a/usr/src/cmd/eeprom/i386/common/benv.c b/usr/src/cmd/eeprom/i386/benv.c index a1d9809bcc..3e44469f9a 100644 --- a/usr/src/cmd/eeprom/i386/common/benv.c +++ b/usr/src/cmd/eeprom/i386/benv.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,17 +19,20 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include "benv.h" +#include "message.h" #include <ctype.h> #include <stdarg.h> #include <sys/mman.h> #include <unistd.h> +#include <signal.h> +#include <sys/wait.h> /* * Usage: % eeprom [-v] [-f prom_dev] [-] @@ -40,7 +42,6 @@ extern void get_kbenv(void); extern void close_kbenv(void); extern caddr_t get_propval(char *name, char *node); -extern void sync_benv(void); extern void setprogname(char *prog); char *boottree; @@ -48,7 +49,6 @@ struct utsname uts_buf; static int test; int verbose; -static char *bootargs; /* * Concatenate a NULL terminated list of strings into @@ -69,7 +69,7 @@ strcats(char *s, ...) } else { len += strlen(cp); ret = realloc(ret, len); - strcat(ret, cp); + (void) strcat(ret, cp); } } va_end(ap); @@ -187,15 +187,262 @@ get_var(char *name, eplist_t *list) return (NULL); } +/*PRINTFLIKE1*/ +static void +eeprom_error(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + (void) fprintf(stderr, "eeprom: "); + (void) vfprintf(stderr, format, ap); + va_end(ap); +} + +static int +exec_cmd(char *cmdline, char *output, int64_t osize) +{ + char buf[BUFSIZ]; + int ret; + size_t len; + FILE *ptr; + sigset_t set; + void (*disp)(int); + + if (output) + output[0] = '\0'; + + /* + * For security + * - only absolute paths are allowed + * - set IFS to space and tab + */ + if (*cmdline != '/') { + eeprom_error(ABS_PATH_REQ, cmdline); + return (-1); + } + (void) putenv("IFS= \t"); + + /* + * We may have been exec'ed with SIGCHLD blocked + * unblock it here + */ + (void) sigemptyset(&set); + (void) sigaddset(&set, SIGCHLD); + if (sigprocmask(SIG_UNBLOCK, &set, NULL) != 0) { + eeprom_error(FAILED_SIG, strerror(errno)); + return (-1); + } + + /* + * Set SIGCHLD disposition to SIG_DFL for popen/pclose + */ + disp = sigset(SIGCHLD, SIG_DFL); + if (disp == SIG_ERR) { + eeprom_error(FAILED_SIG, strerror(errno)); + return (-1); + } + if (disp == SIG_HOLD) { + eeprom_error(BLOCKED_SIG, cmdline); + return (-1); + } + + ptr = popen(cmdline, "r"); + if (ptr == NULL) { + eeprom_error(POPEN_FAIL, cmdline, strerror(errno)); + return (-1); + } + + /* + * If we simply do a pclose() following a popen(), pclose() + * will close the reader end of the pipe immediately even + * if the child process has not started/exited. pclose() + * does wait for cmd to terminate before returning though. + * When the executed command writes its output to the pipe + * there is no reader process and the command dies with + * SIGPIPE. To avoid this we read repeatedly until read + * terminates with EOF. This indicates that the command + * (writer) has closed the pipe and we can safely do a + * pclose(). + * + * Since pclose() does wait for the command to exit, + * we can safely reap the exit status of the command + * from the value returned by pclose() + */ + while (fgets(buf, sizeof (buf), ptr) != NULL) { + if (output && osize > 0) { + (void) snprintf(output, osize, "%s", buf); + len = strlen(buf); + output += len; + osize -= len; + } + } + + /* + * If there's a "\n" at the end, we want to chop it off + */ + if (output) { + len = strlen(output) - 1; + if (output[len] == '\n') + output[len] = '\0'; + } + + ret = pclose(ptr); + if (ret == -1) { + eeprom_error(PCLOSE_FAIL, cmdline, strerror(errno)); + return (-1); + } + + if (WIFEXITED(ret)) { + return (WEXITSTATUS(ret)); + } else { + eeprom_error(EXEC_FAIL, cmdline, ret); + return (-1); + } +} + +#define BOOTADM_STR "bootadm: " + +/* + * bootadm starts all error messages with "bootadm: ". + * Add a note so users don't get confused on how they ran bootadm. + */ +static void +output_error_msg(const char *msg) +{ + size_t len = sizeof (BOOTADM_STR) - 1; + + if (strncmp(msg, BOOTADM_STR, len) == 0) { + eeprom_error("error returned from %s\n", msg); + } else if (msg[0] != '\0') { + eeprom_error("%s\n", msg); + } +} + +static char * +get_bootadm_value(char *name) +{ + char *ptr, *ret_str, *end_ptr, *orig_ptr; + char output[BUFSIZ]; + int is_console, is_kernel = 0; + size_t len; + + is_console = (strcmp(name, "console") == 0); + + if (strcmp(name, "boot-file") == 0) { + is_kernel = 1; + ptr = "/sbin/bootadm set-menu kernel 2>&1"; + } else if (is_console || (strcmp(name, "boot-args") == 0)) { + ptr = "/sbin/bootadm set-menu args 2>&1"; + } else { + eeprom_error("Unknown value in get_bootadm_value: %s\n", name); + return (NULL); + } + + if (exec_cmd(ptr, output, BUFSIZ) != 0) { + output_error_msg(output); + return (NULL); + } + + if (is_console) { + if ((ptr = strstr(output, "console=")) == NULL) { + return (NULL); + } + ptr += strlen("console="); + + /* + * -B may have comma-separated values. It may also be + * followed by other flags. + */ + len = strcspn(ptr, " \t,"); + ret_str = calloc(len + 1, 1); + if (ret_str == NULL) { + eeprom_error(NO_MEM, len + 1); + return (NULL); + } + (void) strncpy(ret_str, ptr, len); + return (ret_str); + } else if (is_kernel) { + ret_str = strdup(output); + if (ret_str == NULL) + eeprom_error(NO_MEM, strlen(output) + 1); + return (ret_str); + } else { + /* If there's no console setting, we can return */ + if ((orig_ptr = strstr(output, "console=")) == NULL) { + return (strdup(output)); + } + len = strcspn(orig_ptr, " \t,"); + ptr = orig_ptr; + end_ptr = orig_ptr + len + 1; + + /* Eat up any white space */ + while ((*end_ptr == ' ') || (*end_ptr == '\t')) + end_ptr++; + + /* + * If there's data following the console string, copy it. + * If not, cut off the new string. + */ + if (*end_ptr == '\0') + *ptr = '\0'; + + while (*end_ptr != '\0') { + *ptr = *end_ptr; + ptr++; + end_ptr++; + } + *ptr = '\0'; + if ((strchr(output, '=') == NULL) && + (strncmp(output, "-B ", 3) == 0)) { + /* + * Since we removed the console setting, we no + * longer need the initial "-B " + */ + orig_ptr = output + 3; + } else { + orig_ptr = output; + } + + ret_str = strdup(orig_ptr); + if (ret_str == NULL) + eeprom_error(NO_MEM, strlen(orig_ptr) + 1); + return (ret_str); + } +} + +/* + * If quiet is 1, print nothing if there is no value. If quiet is 0, print + * a message. + */ +static void +print_bootadm_value(char *name, int quiet) +{ + char *value = get_bootadm_value(name); + + if ((value != NULL) && (value[0] != '\0')) { + (void) printf("%s=%s\n", name, value); + } else if (quiet == 0) { + (void) printf("%s: data not available.\n", name); + } + + if (value != NULL) + free(value); +} + static void print_var(char *name, eplist_t *list) { benv_ent_t *p; - if ((p = get_var(name, list)) == NULL) - printf("%s: data not available.\n", name); + if ((strcmp(name, "boot-file") == 0) || + (strcmp(name, "boot-args") == 0) || + (strcmp(name, "console") == 0)) { + print_bootadm_value(name, 0); + } else if ((p = get_var(name, list)) == NULL) + (void) printf("%s: data not available.\n", name); else - printf("%s=%s\n", name, p->val ? p->val : ""); + (void) printf("%s=%s\n", name, p->val ? p->val : ""); } static void @@ -206,9 +453,19 @@ print_vars(eplist_t *list) for (e = list->next; e != list; e = e->next) { p = (benv_ent_t *)e->item; - if (p->name != NULL) - printf("%s=%s\n", p->name, p->val ? p->val : ""); + if (p->name != NULL) { + if ((strcmp(p->name, "boot-file") == 0) || + (strcmp(p->name, "boot-args") == 0) || + (strcmp(p->name, "console") == 0)) { + /* handle these separately */ + continue; + } + (void) printf("%s=%s\n", p->name, p->val ? p->val : ""); + } } + print_bootadm_value("boot-file", 1); + print_bootadm_value("boot-args", 1); + print_bootadm_value("console", 1); } /* @@ -219,35 +476,91 @@ print_vars(eplist_t *list) static void put_quoted(FILE *fp, char *val) { - putc('\'', fp); + (void) putc('\'', fp); while (*val) { switch (*val) { case '\'': case '\\': - putc('\\', fp); + (void) putc('\\', fp); /* FALLTHROUGH */ default: - putc(*val, fp); + (void) putc(*val, fp); break; } val++; } - putc('\'', fp); + (void) putc('\'', fp); } static void -write_bargs(char *name, char *val) +set_bootadm_var(char *name, char *value) { - FILE *fp; + char buf[BUFSIZ]; + char output[BUFSIZ] = ""; + char *ptr, *console, *args; + int is_console; - if ((fp = fopen(bootargs, "w")) == NULL) - exit(_error(PERROR, "cannot open %s", bootargs)); + if (verbose) { + (void) printf("old:"); + print_bootadm_value(name, 0); + } - fprintf(fp, "setprop %s ", name); - put_quoted(fp, val); - fprintf(fp, "\n"); + /* + * For security, we single-quote whatever we run on the command line, + * and we don't allow single quotes in the string. + */ + if ((ptr = strchr(value, '\'')) != NULL) { + eeprom_error("Single quotes are not allowed " + "in the %s property.\n", name); + return; + } - fclose(fp); + is_console = (strcmp(name, "console") == 0); + if (strcmp(name, "boot-file") == 0) { + (void) snprintf(buf, BUFSIZ, "/sbin/bootadm set-menu " + "kernel='%s' 2>&1", value); + } else if (is_console || (strcmp(name, "boot-args") == 0)) { + if (is_console) { + args = get_bootadm_value("boot-args"); + console = value; + } else { + args = value; + console = get_bootadm_value("console"); + } + if (((args == NULL) || (args[0] == '\0')) && + ((console == NULL) || (console[0] == '\0'))) { + (void) snprintf(buf, BUFSIZ, "/sbin/bootadm set-menu " + "args= 2>&1"); + } else if ((args == NULL) || (args[0] == '\0')) { + (void) snprintf(buf, BUFSIZ, "/sbin/bootadm " + "set-menu args='-B console=%s' 2>&1", + console); + } else if ((console == NULL) || (console[0] == '\0')) { + (void) snprintf(buf, BUFSIZ, "/sbin/bootadm " + "set-menu args='%s' 2>&1", args); + } else if (strncmp(args, "-B ", 3) != 0) { + (void) snprintf(buf, BUFSIZ, "/sbin/bootadm " + "set-menu args='-B console=%s %s' 2>&1", + console, args); + } else { + (void) snprintf(buf, BUFSIZ, "/sbin/bootadm " + "set-menu args='-B console=%s,%s' 2>&1", + console, args + 3); + } + } else { + eeprom_error("Unknown value in set_bootadm_value: %s\n", name); + return; + } + + if (exec_cmd(buf, output, BUFSIZ) != 0) { + output_error_msg(output); + return; + } + + if (verbose) { + (void) printf("new:"); + print_bootadm_value(name, 0); + } } static void @@ -255,8 +568,15 @@ set_var(char *name, char *val, eplist_t *list) { benv_ent_t *p; + if ((strcmp(name, "boot-file") == 0) || + (strcmp(name, "boot-args") == 0) || + (strcmp(name, "console") == 0)) { + set_bootadm_var(name, val); + return; + } + if (verbose) { - printf("old:"); + (void) printf("old:"); print_var(name, list); } @@ -267,7 +587,7 @@ set_var(char *name, char *val, eplist_t *list) add_bent(list, NULL, "setprop", name, val); if (verbose) { - printf("new:"); + (void) printf("new:"); print_var(name, list); } } @@ -307,8 +627,6 @@ init_benv(benv_des_t *bd, char *file) bd->name = file; else bd->name = strcats(boottree, "/solaris/bootenv.rc", NULL); - - bootargs = strcats(boottree, "/solaris/bootargs.rc", NULL); } static void @@ -636,25 +954,22 @@ write_benv(benv_des_t *bd) for (e = list->next; e != list; e = e->next) { bent = (benv_ent_t *)e->item; name = bent->name; - if (name) - if (strcmp(name, "bootargs") == 0) { - /* - * Write "bootargs" to bootargs.rc file. - */ - write_bargs(name, bent->val); - } else if (bent->val) { - fprintf(fp, "%s %s ", + if (name) { + if (bent->val) { + (void) fprintf(fp, "%s %s ", bent->cmd, bent->name); put_quoted(fp, bent->val); - fprintf(fp, "\n"); - } else - fprintf(fp, "%s %s\n", + (void) fprintf(fp, "\n"); + } else { + (void) fprintf(fp, "%s %s\n", bent->cmd, bent->name); - else - fprintf(fp, "%s\n", bent->cmd); + } + } else { + (void) fprintf(fp, "%s\n", bent->cmd); + } } - fclose(fp); + (void) fclose(fp); } static char * @@ -679,23 +994,12 @@ get_line(void) return (NULL); } -void -init_eeprom(void) -{ - - /* ignore truncate failure */ - (void) truncate(bootargs, 0); - - sync_benv(); -} - int main(int argc, char **argv) { int c; - int init = 0; int updates = 0; - char *usage = "Usage: %s [-I] [-v] [-f prom-device]" + char *usage = "Usage: %s [-v] [-f prom-device]" " [variable[=value] ...]"; eplist_t *elist; benv_des_t *bd; @@ -705,9 +1009,6 @@ main(int argc, char **argv) while ((c = getopt(argc, argv, "f:Itv")) != -1) switch (c) { - case 'I': - init++; - break; case 'v': verbose++; break; @@ -733,9 +1034,7 @@ main(int argc, char **argv) elist = bd->elist; - if (init) - init_eeprom(); - else if (optind >= argc) { + if (optind >= argc) { print_vars(elist); return (0); } else @@ -761,7 +1060,7 @@ main(int argc, char **argv) * don't write benv if we are processing delayed writes since * it is likely that the delayed writes changes bootenv.rc anyway... */ - if (!init && updates) + if (updates) write_benv(bd); close_kbenv(); diff --git a/usr/src/cmd/eeprom/i386/common/benv.h b/usr/src/cmd/eeprom/i386/benv.h index ec031e67c6..ec031e67c6 100644 --- a/usr/src/cmd/eeprom/i386/common/benv.h +++ b/usr/src/cmd/eeprom/i386/benv.h diff --git a/usr/src/cmd/eeprom/i386/common/benv_kvm.c b/usr/src/cmd/eeprom/i386/benv_kvm.c index b7b912eb73..b7b912eb73 100644 --- a/usr/src/cmd/eeprom/i386/common/benv_kvm.c +++ b/usr/src/cmd/eeprom/i386/benv_kvm.c diff --git a/usr/src/cmd/eeprom/i386/common/benv_sync.c b/usr/src/cmd/eeprom/i386/common/benv_sync.c deleted file mode 100644 index 5faf7e68ab..0000000000 --- a/usr/src/cmd/eeprom/i386/common/benv_sync.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "benv.h" -#include <unistd.h> -#include <sys/sunddi.h> -#include <sys/ddi_impldefs.h> - -extern ddi_prop_t *get_proplist(char *name); -extern int verbose; - -/* - * Delayed-write descriptor. - */ -typedef struct dw_des { - char *path; /* file path */ - eplist_t *wlist; /* list of writes to the file */ -} dw_des_t; - -/* - * Delayed-write request. - */ -typedef struct dw_req { - caddr_t adr; /* data address */ - uint_t len; /* data length */ - int num; /* write number */ -} dw_req_t; - -static dw_des_t * -new_dwd(char *path) -{ - dw_des_t *dwd; - - dwd = (dw_des_t *)malloc(sizeof (dw_des_t)); - (void) memset(dwd, 0, sizeof (dw_des_t)); - - dwd->path = path; - dwd->wlist = new_list(); - - return (dwd); -} - -/* - * Parse a delayed-write property into a delayed-write request. - * The property name is of the form 'writeN' where N represents - * the Nth write request to the pathname encoded in the property's value. - */ -static void -parse_dw(ddi_prop_t *prop, char **path, dw_req_t **dwrp) -{ - int plen; - caddr_t tok; - dw_req_t *dwr; - - dwr = (dw_req_t *)malloc(sizeof (dw_req_t)); - dwr->num = atoi(&prop->prop_name[5]); - - tok = prop->prop_val; - plen = *((int *)tok); - tok += 4; - *path = (char *)tok; - tok += plen; - dwr->len = *((int *)tok); - tok += 4; - dwr->adr = tok; - - *dwrp = dwr; -} - -/* - * Sync a delayed-write out request to a file. - */ -static void -sync_dwr(char *relpath, dw_req_t *dwr) -{ - int fd; - char *p, *path; - - path = strcats(boottree, "/", relpath, NULL); - p = strrchr(path, '/'); - *p = NULL; - - - if (access(path, F_OK) != 0) { - if (mkdirp(path, 755) == -1) - exit(_error(PERROR, "cannot mkdir %s", path)); - } - - *p = '/'; - - if ((fd = open(path, O_RDWR|O_CREAT|O_TRUNC, 0644)) == -1) - exit(_error(PERROR, "cannot open %s", path)); - - - if (write(fd, dwr->adr, dwr->len) != dwr->len) - exit(_error(PERROR, "cannot write %s", path)); - - if (verbose) - printf("sync \"%s\" size %d data <%s>\n", - path, dwr->len, dwr->adr); - - close(fd); - free(path); -} - -/* - * Sync all delayed-write requests from the boot. - */ -void -sync_benv(void) -{ - ddi_prop_t *prop, *plist; - eplist_t *dwlp, *pl, *wl; - dw_des_t *dwd; - dw_req_t *dwr, *dwrlast; - - if ((plist = get_proplist("delayed-writes")) == NULL) { - if (verbose) - printf("no delayed writes.\n"); - return; - } - - dwlp = new_list(); - - /* - * Parse each property into a delayed-write request for - * for a given file. - */ - for (prop = plist; prop != NULL; prop = prop->prop_next) { - if (strncmp(prop->prop_name, "write", 5) == 0) { - char *path; - - parse_dw(prop, &path, &dwr); - - if (verbose) - printf("write \"%s\"\n", path); - - /* - * Get a delayed-write descriptor for each - * new file. Add all delayed-write requests - * for a given file to the descriptor's request - * list. - */ - for (pl = dwlp->next; pl != dwlp; pl = pl->next) { - dwd = (dw_des_t *)pl->item; - - if (strcmp(dwd->path, path) == 0) - break; - } - - if (pl == dwlp) { - dwd = new_dwd(path); - add_item((void *)dwd, dwlp); - } - - add_item((void *)dwr, dwd->wlist); - } - } - - /* - * Process the last request for each path. We only need to - * do the last request since the writes are destructive and - * overwrite all previous file contents. - */ - for (pl = dwlp->next; pl != dwlp; pl = pl->next) { - dwd = (dw_des_t *)(pl->item); - dwrlast = NULL; - - for (wl = dwd->wlist->next; wl != dwd->wlist; wl = wl->next) { - dwr = (dw_req_t *)(wl->item); - if (dwrlast == NULL || dwr->num >= dwrlast->num) - dwrlast = dwr; - } - - if (dwrlast != NULL) - sync_dwr(dwd->path, dwrlast); - } -} diff --git a/usr/src/cmd/eeprom/sparc/Makefile b/usr/src/cmd/eeprom/sparc/Makefile index e3579bd4dc..7215f7466a 100644 --- a/usr/src/cmd/eeprom/sparc/Makefile +++ b/usr/src/cmd/eeprom/sparc/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,26 +21,18 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# cmd/eeprom/sparc/Makefile -# -SRCDIR=.. -SUBDIRS= sun4u sun4v +SRCDIR = .. -all:= TARGET= all -install:= TARGET= install -clean:= TARGET= clean -clobber:= TARGET= clobber -lint:= TARGET= lint +include $(SRCDIR)/Makefile.com -.KEEP_STATE: +OBJS += openprom.o loadlogo.o -all install clean clobber lint : $(SUBDIRS) +.KEEP_STATE: -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) +all: $(PROG) -FRC: +include $(SRCDIR)/Makefile.targ diff --git a/usr/src/cmd/eeprom/common/loadlogo.c b/usr/src/cmd/eeprom/sparc/loadlogo.c index ebd30f324e..ebd30f324e 100644 --- a/usr/src/cmd/eeprom/common/loadlogo.c +++ b/usr/src/cmd/eeprom/sparc/loadlogo.c diff --git a/usr/src/cmd/eeprom/common/openprom.c b/usr/src/cmd/eeprom/sparc/openprom.c index 36bf325a62..36bf325a62 100644 --- a/usr/src/cmd/eeprom/common/openprom.c +++ b/usr/src/cmd/eeprom/sparc/openprom.c diff --git a/usr/src/cmd/eeprom/sparc/sun4u/Makefile b/usr/src/cmd/eeprom/sparc/sun4u/Makefile deleted file mode 100644 index 2cb9c73cfb..0000000000 --- a/usr/src/cmd/eeprom/sparc/sun4u/Makefile +++ /dev/null @@ -1,46 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright (c) 1993 by Sun Microsystems, Inc. -# -# cmd/eeprom/sparc/sun4u/Makefile -# -# Platform specific Makefile for the eeprom command. -# -# PLATFORM is the target for the binary instalation. -# -# PLATLINKS is a list of platforms which are to be linked to this binary -# at the file level. -# -SRCDIR = ../.. -PLATFORM = sun4u -#PLATLINKS = SUNW,SPARCstation-fusion - -include $(SRCDIR)/Makefile.com - -.KEEP_STATE: - -all: $(PROG) - -include $(SRCDIR)/Makefile.targ diff --git a/usr/src/cmd/eeprom/sparc/sun4v/Makefile b/usr/src/cmd/eeprom/sparc/sun4v/Makefile deleted file mode 100644 index d4cb137cff..0000000000 --- a/usr/src/cmd/eeprom/sparc/sun4v/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -#ident "%Z%%M% %I% %E% SMI" -# -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/eeprom/sparc/sun4v/Makefile -# -# Platform specific Makefile for the eeprom command. -# -# PLATFORM is the target for the binary instalation. -# -# PLATLINKS is a list of platforms which are to be linked to this binary -# at the file level. -# -SRCDIR = ../.. -PLATFORM = sun4v - -include $(SRCDIR)/Makefile.com - -.KEEP_STATE: - -all: $(PROG) - -include $(SRCDIR)/Makefile.targ diff --git a/usr/src/cmd/mdb/common/kmdb/kaif_start.c b/usr/src/cmd/mdb/common/kmdb/kaif_start.c index 17f136b307..6c0fc810bb 100644 --- a/usr/src/cmd/mdb/common/kmdb/kaif_start.c +++ b/usr/src/cmd/mdb/common/kmdb/kaif_start.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -80,6 +80,13 @@ kaif_lock_exit(uintptr_t *lock) membar_producer(); } +static void +kaif_start_slaves(int cmd) +{ + kaif_slave_cmd = cmd; + kmdb_kdi_start_slaves(); +} + static int kaif_master_loop(kaif_cpusave_t *cpusave) { @@ -90,6 +97,12 @@ kaif_master_loop(kaif_cpusave_t *cpusave) #endif kaif_trap_set_debugger(); + /* + * If we re-entered due to a ::switch, we need to tell the slave CPUs + * to sleep again. + */ + kmdb_kdi_stop_slaves(cpusave->krs_cpu_id, 0); + master_loop: switch (kmdb_dpi_reenter()) { case KMDB_DPI_CMD_SWITCH_CPU: @@ -112,7 +125,7 @@ master_loop: */ kaif_trap_set_saved(cpusave); - kaif_slave_cmd = KAIF_SLAVE_CMD_SWITCH; + kaif_start_slaves(KAIF_SLAVE_CMD_SWITCH); /* The new master is now awake */ return (KAIF_CPU_CMD_SWITCH); @@ -124,7 +137,7 @@ master_loop: */ kaif_master_cpuid = KAIF_MASTER_CPUID_UNSET; membar_producer(); - kaif_slave_cmd = KAIF_SLAVE_CMD_RESUME; + kaif_start_slaves(KAIF_SLAVE_CMD_RESUME); if (kmdb_dpi_work_required()) kmdb_dpi_wrintr_fire(); @@ -141,7 +154,7 @@ master_loop: return (KAIF_CPU_CMD_RESUME_MASTER); case KMDB_DPI_CMD_FLUSH_CACHES: - kaif_slave_cmd = KAIF_SLAVE_CMD_FLUSH; + kaif_start_slaves(KAIF_SLAVE_CMD_FLUSH); /* * Wait for the other cpus to finish flushing their caches. @@ -170,9 +183,9 @@ master_loop: * afraid that I don't want to know the answer. */ if (cpusave->krs_cpu_id == 0) - return (KAIF_CPU_CMD_REBOOT); + kmdb_kdi_reboot(); - kaif_slave_cmd = KAIF_SLAVE_CMD_REBOOT; + kaif_start_slaves(KAIF_SLAVE_CMD_REBOOT); /* * Spin forever, waiting for CPU 0 (apparently a slave) to @@ -223,7 +236,8 @@ kaif_slave_loop(kaif_cpusave_t *cpusave) #if defined(__i386) || defined(__amd64) } else if (slavecmd == KAIF_SLAVE_CMD_REBOOT && cpusave->krs_cpu_id == 0) { - rv = KAIF_CPU_CMD_REBOOT; + rv = 0; + kmdb_kdi_reboot(); break; #endif @@ -238,6 +252,8 @@ kaif_slave_loop(kaif_cpusave_t *cpusave) cpusave->krs_cpu_acked = 0; #endif } + + kmdb_kdi_slave_wait(); } #if defined(__sparc) @@ -260,9 +276,7 @@ kaif_select_master(kaif_cpusave_t *cpusave) membar_producer(); - kmdb_kdi_stop_other_cpus(cpusave->krs_cpu_id, - kaif_slave_entry); - + kmdb_kdi_stop_slaves(cpusave->krs_cpu_id, 1); } else { /* The master was already chosen - go be a slave */ cpusave->krs_cpu_state = KAIF_CPU_STATE_SLAVE; @@ -405,7 +419,7 @@ kaif_slave_loop_barrier(void) int not_acked; int timeout_count = 0; - kaif_slave_cmd = KAIF_SLAVE_CMD_ACK; + kaif_start_slaves(KAIF_SLAVE_CMD_ACK); /* * Wait for slave cpus to explicitly acknowledge diff --git a/usr/src/cmd/mdb/common/kmdb/kaif_start.h b/usr/src/cmd/mdb/common/kmdb/kaif_start.h index a0234cb493..40ddc252b5 100644 --- a/usr/src/cmd/mdb/common/kmdb/kaif_start.h +++ b/usr/src/cmd/mdb/common/kmdb/kaif_start.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -30,7 +29,7 @@ #pragma ident "%Z%%M% %I% %E% SMI" #include <sys/types.h> -#include <kmdb/kaif_regs.h> +#include <kmdb/kaif.h> #ifdef __cplusplus extern "C" { @@ -40,6 +39,12 @@ extern int kaif_main_loop(kaif_cpusave_t *); extern int kaif_master_cpuid; +#define KAIF_MASTER_CPUID_UNSET -1 + +#define KAIF_CPU_CMD_RESUME 0 +#define KAIF_CPU_CMD_RESUME_MASTER 1 +#define KAIF_CPU_CMD_SWITCH 2 + #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/mdb/common/kmdb/kctl/kctl.h b/usr/src/cmd/mdb/common/kmdb/kctl/kctl.h index 612ed8db13..8c082d6649 100644 --- a/usr/src/cmd/mdb/common/kmdb/kctl/kctl.h +++ b/usr/src/cmd/mdb/common/kmdb/kctl/kctl.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -49,7 +49,6 @@ typedef enum { KCTL_ST_MOD_NOTIFIERS, /* krtld module notifiers registered */ KCTL_ST_THREAD_STARTED, /* WR queue thread started */ KCTL_ST_DBG_ACTIVATED, /* kmdb activated */ - KCTL_ST_KCTL_ACTIVATED, /* kctl activated */ KCTL_ST_ACTIVE, /* kernel is aware of kmdb activation */ KCTL_ST_DEACTIVATING /* debugger is being deactivated */ } kctl_state_t; @@ -93,9 +92,8 @@ extern void kctl_dprintf(const char *, ...); extern void kctl_warn(const char *, ...); extern int kctl_preactivate_isadep(void); -extern int kctl_activate_isadep(kdi_debugvec_t *); +extern void kctl_activate_isadep(kdi_debugvec_t *); extern void kctl_depreactivate_isadep(void); -extern void kctl_deactivate_isadep(void); extern void kctl_cleanup(void); extern void *kctl_boot_tmpinit(void); diff --git a/usr/src/cmd/mdb/common/kmdb/kctl/kctl_auxv.c b/usr/src/cmd/mdb/common/kmdb/kctl/kctl_auxv.c index 1ea1216ae6..773a088783 100644 --- a/usr/src/cmd/mdb/common/kmdb/kctl/kctl_auxv.c +++ b/usr/src/cmd/mdb/common/kmdb/kctl/kctl_auxv.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -83,28 +82,15 @@ kctl_auxv_init(kmdb_auxv_t *kav, const char *cfg, const char **argv, void *romp) kav->kav_config = cfg; kav->kav_argv = argv; + kav->kav_modpath = kobj_module_path; - if (kctl.kctl_boot_loaded) { - /* - * default_path hasn't been set yet, so we have to fetch the - * path from OBP. - */ - ssize_t sz; - - if ((sz = BOP_GETPROPLEN(kctl.kctl_boot_ops, - "module-path")) != -1) { - kav->kav_modpath = kobj_alloc(sz, KM_TMP); - (void) BOP_GETPROP(kctl.kctl_boot_ops, "module-path", - (char *)kav->kav_modpath); - } + kctl_dprintf("kctl_auxv_init: modpath '%s'", kav->kav_modpath); + if (kctl.kctl_boot_loaded) { kav->kav_lookup_by_name = kctl_boot_lookup_by_name; kav->kav_flags |= KMDB_AUXV_FL_NOUNLOAD; - } else { - kav->kav_modpath = default_path; - + } else kav->kav_lookup_by_name = kctl_lookup_by_name; - } if (kctl.kctl_flags & KMDB_F_TRAP_NOSWITCH) kav->kav_flags |= KMDB_AUXV_FL_NOTRPSWTCH; diff --git a/usr/src/cmd/mdb/common/kmdb/kctl/kctl_dmod.c b/usr/src/cmd/mdb/common/kmdb/kctl/kctl_dmod.c index 76fc32bdc6..36a088e437 100644 --- a/usr/src/cmd/mdb/common/kmdb/kctl/kctl_dmod.c +++ b/usr/src/cmd/mdb/common/kmdb/kctl/kctl_dmod.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -76,7 +76,7 @@ kctl_find_module(char *modname, char *fullname, size_t fullnamelen) /* If they gave us an absolute path, we don't need to search */ if (modname[0] == '/') { if (strlen(modname) + 1 > fullnamelen) { - cmn_err(CE_WARN, "Can't load dmod %s - name too long\n", + cmn_err(CE_WARN, "Can't load dmod %s - name too long", modname); return (0); } @@ -343,7 +343,7 @@ kctl_dmod_unload(kmdb_wr_unload_t *dur) int rc; if ((rc = kctl_dmod_unload_common(dur->dur_modctl)) != 0) { - cmn_err(CE_WARN, "unexpected dmod unload failure: %d\n", rc); + cmn_err(CE_WARN, "unexpected dmod unload failure: %d", rc); dur->dur_errno = rc; } } diff --git a/usr/src/cmd/mdb/common/kmdb/kctl/kctl_main.c b/usr/src/cmd/mdb/common/kmdb/kctl/kctl_main.c index 13992c6ae2..11b6ec8231 100644 --- a/usr/src/cmd/mdb/common/kmdb/kctl/kctl_main.c +++ b/usr/src/cmd/mdb/common/kmdb/kctl/kctl_main.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -192,17 +191,13 @@ kctl_memavail(void) * If we're going to wedge the machine during debugger startup, * at least let them know why it's going to wedge. */ - cmn_err(CE_WARN, "retrying of kmdb allocation of 0x%lx bytes\n", + cmn_err(CE_WARN, "retrying of kmdb allocation of 0x%lx bytes", (ulong_t)needed); base = kmem_zalloc(needed, KM_SLEEP); } - if (kdi_dvec->dv_memavail(base, needed) < 0) { - cmn_err(CE_WARN, "failed to add memory to debugger\n"); - kmem_free(base, needed); - } - + kdi_dvec->dv_memavail(base, needed); kctl.kctl_mrbase = base; kctl.kctl_mrsize = needed; } @@ -223,10 +218,6 @@ kctl_cleanup(void) kdi_dvec = NULL; /*FALLTHROUGH*/ - case KCTL_ST_KCTL_ACTIVATED: - kctl_deactivate_isadep(); - /*FALLTHROUGH*/ - case KCTL_ST_DBG_ACTIVATED: KCTL_PROM_LOCK; kmdb_deactivate(); @@ -375,10 +366,7 @@ kctl_startup_activate(uint_t flags) dvec->dv_kctl_thravail = kctl_startup_thread; dvec->dv_kctl_memavail = kctl_memavail; - if (kctl_activate_isadep(dvec) != 0) - return (EIO); - - (void) kctl_set_state(KCTL_ST_KCTL_ACTIVATED); + kctl_activate_isadep(dvec); kdi_dvec = dvec; membar_producer(); @@ -425,7 +413,7 @@ kctl_deactivate(void) goto deactivate_done; kmdb_kdi_set_unload_request(); - kdi_dvec_enter(); + kmdb_kdi_kmdb_enter(); /* * The debugger will pass the request to the work thread, which will @@ -487,13 +475,14 @@ kctl_boot_activate(struct bootops *ops, void *romp, size_t memsz, if (memsz == 0) memsz = KCTL_MEM_GOALSZ; - kctl.kctl_dseg = (caddr_t)SEGDEBUGBASE; - kctl.kctl_dseg_size = (memsz > SEGDEBUGSIZE ? SEGDEBUGSIZE : memsz); + kctl.kctl_dseg = kdi_segdebugbase; + kctl.kctl_dseg_size = + memsz > kdi_segdebugsize ? kdi_segdebugsize : memsz; kctl.kctl_memgoalsz = memsz; if (kctl_boot_dseg_alloc(kctl.kctl_dseg, kctl.kctl_dseg_size) < 0) { - kctl_warn("kmdb: failed to allocate %d-byte debugger area at " - "%x", kctl.kctl_dseg_size, kctl.kctl_dseg); + kctl_warn("kmdb: failed to allocate %lu-byte debugger area at " + "%p", kctl.kctl_dseg_size, (void *)kctl.kctl_dseg); return (-1); } @@ -510,9 +499,10 @@ kctl_boot_activate(struct bootops *ops, void *romp, size_t memsz, kctl_dprintf("finished with kmdb initialization"); - kctl.kctl_boot_ops = NULL; kctl_boot_tmpfini(old); + kctl.kctl_boot_ops = NULL; + return (0); } @@ -525,7 +515,7 @@ kctl_modload_activate(size_t memsz, const char *cfg, uint_t flags) if ((rc = kctl_state_check(kctl.kctl_state, KCTL_ST_INACTIVE)) != 0) { if ((flags & KMDB_F_AUTO_ENTRY) && rc == EMDB_KACTIVE) { - kdi_dvec_enter(); + kmdb_kdi_kmdb_enter(); rc = 0; } @@ -538,8 +528,9 @@ kctl_modload_activate(size_t memsz, const char *cfg, uint_t flags) if (memsz == 0) memsz = KCTL_MEM_GOALSZ; - kctl.kctl_dseg = (caddr_t)SEGDEBUGBASE; - kctl.kctl_dseg_size = (memsz > SEGDEBUGSIZE ? SEGDEBUGSIZE : memsz); + kctl.kctl_dseg = kdi_segdebugbase; + kctl.kctl_dseg_size = + memsz > kdi_segdebugsize ? kdi_segdebugsize : memsz; kctl.kctl_memgoalsz = memsz; if ((rc = kctl_dseg_alloc(kctl.kctl_dseg, kctl.kctl_dseg_size)) != 0) @@ -559,7 +550,7 @@ kctl_modload_activate(size_t memsz, const char *cfg, uint_t flags) kctl_memavail(); /* Must be after kdi_dvec is set */ if (kctl.kctl_flags & KMDB_F_AUTO_ENTRY) - kdi_dvec_enter(); + kmdb_kdi_kmdb_enter(); mutex_exit(&kctl.kctl_lock); return (0); diff --git a/usr/src/cmd/mdb/common/kmdb/kctl/kctl_wr.c b/usr/src/cmd/mdb/common/kmdb/kctl/kctl_wr.c index 0b8103ae70..b9d54edc02 100644 --- a/usr/src/cmd/mdb/common/kmdb/kctl/kctl_wr.c +++ b/usr/src/cmd/mdb/common/kmdb/kctl/kctl_wr.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -256,7 +255,7 @@ kctl_wr_thread(void *arg) * debugger for processing, so we need to wake the debugger up. */ if (kctl_wr_process() > 0) - kdi_dvec_enter(); + kmdb_kdi_kmdb_enter(); } /* diff --git a/usr/src/cmd/mdb/common/kmdb/kmdb_dpi_impl.h b/usr/src/cmd/mdb/common/kmdb/kmdb_dpi_impl.h index fe4bd9458b..a94cfae990 100644 --- a/usr/src/cmd/mdb/common/kmdb/kmdb_dpi_impl.h +++ b/usr/src/cmd/mdb/common/kmdb/kmdb_dpi_impl.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -95,10 +94,8 @@ struct dpi_ops { void (*dpo_dump_crumbs)(uintptr_t, int); - int (*dpo_memrange_add)(caddr_t, size_t); - #if defined(__i386) || defined(__amd64) - void (*dpo_msr_add)(const kmdb_msr_t *); + void (*dpo_msr_add)(const kdi_msr_t *); uint64_t (*dpo_msr_get)(int, uint_t); #endif diff --git a/usr/src/cmd/mdb/common/kmdb/kmdb_kdi.c b/usr/src/cmd/mdb/common/kmdb/kmdb_kdi.c index 7d2f674748..c9e3358af9 100644 --- a/usr/src/cmd/mdb/common/kmdb/kmdb_kdi.c +++ b/usr/src/cmd/mdb/common/kmdb/kmdb_kdi.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -50,7 +49,7 @@ #include <sys/kdi_impl.h> -#include <kmdb/kmdb_kdi_impl.h> +#include <kmdb/kmdb_kdi.h> #include <kmdb/kmdb_dpi.h> #include <kmdb/kmdb_kvm.h> #include <kmdb/kmdb_promif.h> @@ -221,6 +220,12 @@ kmdb_kdi_get_polled_io(void) return (mdb.m_kdi->kdi_get_polled_io()); } +void +kmdb_kdi_kmdb_enter(void) +{ + mdb.m_kdi->kdi_kmdb_enter(); +} + int kmdb_kdi_vtop(uintptr_t va, physaddr_t *pap) { @@ -284,8 +289,6 @@ kmdb_kdi_init(kdi_t *kdi, kmdb_auxv_t *kav) kdi_auxv = kav; kmdb_kdi_init_isadep(kdi, kav); - - kdi_cpu_init(); } void diff --git a/usr/src/cmd/mdb/common/kmdb/kmdb_kdi.h b/usr/src/cmd/mdb/common/kmdb/kmdb_kdi.h index 8ffd0f2cab..28f047a33a 100644 --- a/usr/src/cmd/mdb/common/kmdb/kmdb_kdi.h +++ b/usr/src/cmd/mdb/common/kmdb/kmdb_kdi.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -69,7 +68,10 @@ extern int kmdb_kdi_mod_haschanged(struct modctl *, struct module *, struct modctl *, struct module *); extern ssize_t kmdb_kdi_pread(void *, size_t, physaddr_t); extern ssize_t kmdb_kdi_pwrite(void *, size_t, physaddr_t); -extern void kmdb_kdi_stop_other_cpus(int, void (*)(void)); /* Driver OK */ +extern void kmdb_kdi_stop_slaves(int, int); +extern void kmdb_kdi_start_slaves(void); +extern void kmdb_kdi_slave_wait(void); +extern void kmdb_kdi_kmdb_enter(void); /* Driver OK */ extern void kmdb_kdi_system_claim(void); extern void kmdb_kdi_system_release(void); extern size_t kmdb_kdi_range_is_nontoxic(uintptr_t, size_t, int); diff --git a/usr/src/cmd/mdb/common/kmdb/kmdb_kvm.c b/usr/src/cmd/mdb/common/kmdb/kmdb_kvm.c index 18f0d4eb7c..a79d455af1 100644 --- a/usr/src/cmd/mdb/common/kmdb/kmdb_kvm.c +++ b/usr/src/cmd/mdb/common/kmdb/kmdb_kvm.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -977,7 +976,7 @@ kmt_lookup_by_name(mdb_tgt_t *t, const char *obj, const char *name, break; case (uintptr_t)MDB_TGT_OBJ_RTLD: - obj = KMT_RTLD_NAME; + obj = kmt->kmt_rtld_name; /*FALLTHROUGH*/ default: @@ -1081,7 +1080,7 @@ kmt_symbol_iter(mdb_tgt_t *t, const char *obj, uint_t which, uint_t type, return (0); case (uintptr_t)MDB_TGT_OBJ_RTLD: - obj = KMT_RTLD_NAME; + obj = kmt->kmt_rtld_name; /*FALLTHROUGH*/ default: @@ -1197,6 +1196,20 @@ kmt_addr_to_map(mdb_tgt_t *t, uintptr_t addr) return (NULL); } +static kmt_module_t * +kmt_module_by_name(kmt_data_t *kmt, const char *name) +{ + kmt_module_t *km; + + for (km = mdb_list_next(&kmt->kmt_modlist); km != NULL; + km = mdb_list_next(km)) { + if (strcmp(name, km->km_name) == 0) + return (km); + } + + return (NULL); +} + static const mdb_map_t * kmt_name_to_map(mdb_tgt_t *t, const char *name) { @@ -1214,13 +1227,10 @@ kmt_name_to_map(mdb_tgt_t *t, const char *name) } if (name == MDB_TGT_OBJ_RTLD) - name = KMT_RTLD_NAME; /* replace MDB_TGT_OBJ_RTLD with krtld */ + name = kmt->kmt_rtld_name; - for (km = mdb_list_next(&kmt->kmt_modlist); km != NULL; - km = mdb_list_next(km)) { - if (strcmp(name, km->km_name) == 0) - return (kmt_mod_to_map(km, &m)); - } + if ((km = kmt_module_by_name(kmt, name)) != NULL) + return (kmt_mod_to_map(km, &m)); (void) set_errno(EMDB_NOOBJ); return (NULL); @@ -1300,19 +1310,16 @@ kmt_name_to_ctf(mdb_tgt_t *t, const char *name) kmt_module_t *km; if (name == MDB_TGT_OBJ_EXEC) { - name = KMT_CTFPARENT; /* base CTF data is kept in genunix */ + name = KMT_CTFPARENT; } else if (name == MDB_TGT_OBJ_RTLD) { - name = KMT_RTLD_NAME; /* replace with krtld */ + name = kt->kmt_rtld_name; } else if (strncmp(name, "DMOD`", 5) == 0) { /* Request for CTF data for a DMOD symbol */ return (kmdb_module_name_to_ctf(name + 5)); } - for (km = mdb_list_next(&kt->kmt_modlist); km != NULL; - km = mdb_list_next(km)) { - if (strcmp(name, km->km_name) == 0) - return (kmt_load_ctfdata(t, km)); - } + if ((km = kmt_module_by_name(kt, name)) != NULL) + return (kmt_load_ctfdata(t, km)); (void) set_errno(EMDB_NOOBJ); return (NULL); @@ -2344,6 +2351,12 @@ kmt_activate(mdb_tgt_t *t) (void) mdb_tgt_register_dcmds(t, &kmt_dcmds[0], MDB_MOD_FORCE); mdb_tgt_register_regvars(t, kmt->kmt_rds, &kmt_reg_disc, 0); + + /* + * Force load of the MDB krtld module, in case it's been rolled into + * unix. + */ + (void) mdb_module_load(KMT_RTLD_NAME, MDB_MOD_SILENT | MDB_MOD_DEFER); } static void @@ -2525,6 +2538,8 @@ create_err: void kmdb_kvm_startup(void) { + kmt_data_t *kmt = mdb.m_target->t_data; + mdb_dprintf(MDB_DBG_KMOD, "kmdb_kvm startup\n"); kmt_sync(mdb.m_target); @@ -2538,6 +2553,11 @@ kmdb_kvm_startup(void) * startup. */ (void) mdb_tgt_sespec_activate_all(mdb.m_target); + + kmt->kmt_rtld_name = KMT_RTLD_NAME; + + if (kmt_module_by_name(kmt, KMT_RTLD_NAME) == NULL) + kmt->kmt_rtld_name = "unix"; } /* diff --git a/usr/src/cmd/mdb/common/kmdb/kmdb_promif.c b/usr/src/cmd/mdb/common/kmdb/kmdb_promif.c index 0757ccb48d..135a22e4d0 100644 --- a/usr/src/cmd/mdb/common/kmdb/kmdb_promif.c +++ b/usr/src/cmd/mdb/common/kmdb/kmdb_promif.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -52,24 +52,31 @@ static char kmdb_prom_readbuf[KMDB_PROM_READBUF_SIZE]; static int kmdb_prom_readbuf_head; static int kmdb_prom_readbuf_tail; -static ssize_t -kmdb_prom_polled_read(caddr_t buf, size_t len) +static int +kmdb_prom_getchar(int wait) { - uintptr_t arg = (uintptr_t)mdb.m_pio->cons_polledio_argument; - uintptr_t ischar = (uintptr_t)mdb.m_pio->cons_polledio_ischar; - int nread = 0; - int c; + struct cons_polledio *pio = mdb.m_pio; + uintptr_t ischar; + uintptr_t getchar; + uintptr_t arg; + + if (pio == NULL || pio->cons_polledio_getchar == NULL) { + int c; + while ((c = prom_mayget()) == -1) { + if (!wait) + return (-1); + } + return (c); + } - while ((ischar == NULL || kmdb_dpi_call(ischar, 1, &arg)) && - nread < len) { - c = kmdb_dpi_call((uintptr_t)mdb.m_pio->cons_polledio_getchar, - 1, &arg); + ischar = (uintptr_t)pio->cons_polledio_ischar; + getchar = (uintptr_t)pio->cons_polledio_getchar; + arg = (uintptr_t)pio->cons_polledio_argument; - *buf++ = (char)c; - nread++; - } + if (!wait && ischar != NULL && !kmdb_dpi_call(ischar, 1, &arg)) + return (-1); - return (nread); + return ((int)kmdb_dpi_call(getchar, 1, &arg)); } static ssize_t @@ -90,17 +97,18 @@ kmdb_prom_polled_write(caddr_t buf, size_t len) } static ssize_t -kmdb_prom_reader(caddr_t buf, size_t len) +kmdb_prom_reader(caddr_t buf, size_t len, int wait) { int nread = 0; int c; - if (mdb.m_pio != NULL && mdb.m_pio->cons_polledio_getchar != NULL) - return (kmdb_prom_polled_read(buf, len)); + while (nread < len) { + if ((c = kmdb_prom_getchar(wait)) == -1) + break; - while (nread < len && (c = prom_mayget()) != -1) { *buf++ = (char)c; nread++; + wait = 0; } return (nread); @@ -217,7 +225,7 @@ check_int(char *buf, size_t len) * delivering an interrupt directly if we find one. */ static void -kmdb_prom_fill_readbuf(int check_for_int) +kmdb_prom_fill_readbuf(int check_for_int, int wait) { int oldhead, left, n; @@ -238,7 +246,7 @@ kmdb_prom_fill_readbuf(int check_for_int) * the common code handle the second. */ if ((n = kmdb_prom_reader(kmdb_prom_readbuf + - kmdb_prom_readbuf_head, left)) <= 0) + kmdb_prom_readbuf_head, left, wait)) <= 0) return; oldhead = kmdb_prom_readbuf_head; @@ -255,7 +263,7 @@ kmdb_prom_fill_readbuf(int check_for_int) left = kmdb_prom_readbuf_tail - kmdb_prom_readbuf_head - 1; if (left > 0) { if ((n = kmdb_prom_reader(kmdb_prom_readbuf + - kmdb_prom_readbuf_head, left)) <= 0) + kmdb_prom_readbuf_head, left, wait)) <= 0) return; oldhead = kmdb_prom_readbuf_head; @@ -272,7 +280,7 @@ kmdb_prom_fill_readbuf(int check_for_int) if (check_for_int) { char c; - while (kmdb_prom_reader(&c, 1) == 1) + while (kmdb_prom_reader(&c, 1, 0) == 1) check_int(&c, 1); } } @@ -280,7 +288,7 @@ kmdb_prom_fill_readbuf(int check_for_int) void kmdb_prom_check_interrupt(void) { - kmdb_prom_fill_readbuf(1); + kmdb_prom_fill_readbuf(1, 0); } /* @@ -294,9 +302,10 @@ kmdb_prom_read(void *buf, size_t len, struct termios *tio) size_t totread = 0; size_t thisread; char *c = (char *)buf; + int wait = 1; for (;;) { - kmdb_prom_fill_readbuf(0); + kmdb_prom_fill_readbuf(0, wait); thisread = kmdb_prom_drain_readbuf(c, len); len -= thisread; totread += thisread; @@ -306,6 +315,8 @@ kmdb_prom_read(void *buf, size_t len, struct termios *tio) if (totread == 0) continue; + wait = 0; + /* * We're done if we've exhausted available input or if we've * filled the provided buffer. diff --git a/usr/src/cmd/mdb/common/kmdb/kvm.h b/usr/src/cmd/mdb/common/kmdb/kvm.h index 4c1786dbf6..414a79eca9 100644 --- a/usr/src/cmd/mdb/common/kmdb/kvm.h +++ b/usr/src/cmd/mdb/common/kmdb/kvm.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -80,6 +80,7 @@ typedef struct kmt_data { const mdb_tgt_regdesc_t *kmt_rds; /* Register description table */ mdb_nv_t kmt_modules; /* Hash table of modules */ mdb_list_t kmt_modlist; /* List of mods in load order */ + const char *kmt_rtld_name; /* Module containing krtld */ caddr_t kmt_writemap; /* Used to map PAs for writes */ size_t kmt_writemapsz; /* Size of same */ mdb_map_t kmt_map; /* Persistant map for callers */ diff --git a/usr/src/cmd/mdb/common/mdb/mdb_ks.h b/usr/src/cmd/mdb/common/mdb/mdb_ks.h index bb3038dcd8..3ea1343492 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_ks.h +++ b/usr/src/cmd/mdb/common/mdb/mdb_ks.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -65,7 +65,7 @@ extern int mdb_devinfo2statep(uintptr_t, char *, uintptr_t *); extern int mdb_cpu2cpuid(uintptr_t); -extern int mdb_cpuset_find(uintptr_t cpusetp); +extern int mdb_cpuset_find(uintptr_t); /* * Returns a pointer to the top of the soft state struct for the instance diff --git a/usr/src/cmd/mdb/common/mdb/mdb_kvm.c b/usr/src/cmd/mdb/common/mdb/mdb_kvm.c index c2e71bb643..853feb80d1 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_kvm.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_kvm.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -90,7 +89,6 @@ typedef struct kt_maparg { void *map_data; /* Callback function argument */ } kt_maparg_t; -static const char KT_RTLD_NAME[] = "krtld"; static const char KT_MODULE[] = "mdb_ks"; static const char KT_CTFPARENT[] = "genunix"; @@ -491,6 +489,19 @@ reg_disc_get(const mdb_var_t *v) return (r); } +static kt_module_t * +kt_module_by_name(kt_data_t *kt, const char *name) +{ + kt_module_t *km; + + for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) { + if (strcmp(name, km->km_name) == 0) + return (km); + } + + return (NULL); +} + void kt_activate(mdb_tgt_t *t) { @@ -546,9 +557,23 @@ kt_activate(mdb_tgt_t *t) mdb_iob_flush(mdb.m_out); } - if (!(t->t_flags & MDB_TGT_F_NOLOAD)) + if (!(t->t_flags & MDB_TGT_F_NOLOAD)) { kt_load_modules(kt, t); + /* + * Determine where the CTF data for krtld is. If krtld + * is rolled into unix, force load the MDB krtld + * module. + */ + kt->k_rtld_name = "krtld"; + + if (kt_module_by_name(kt, "krtld") == NULL) { + (void) mdb_module_load("krtld", MDB_MOD_SILENT); + kt->k_rtld_name = "unix"; + } + } + + if (t->t_flags & MDB_TGT_F_PRELOAD) { mdb_iob_puts(mdb.m_out, " ]\n"); mdb_iob_setflags(mdb.m_out, oflag); @@ -778,7 +803,7 @@ kt_lookup_by_name(mdb_tgt_t *t, const char *obj, const char *name, break; case (uintptr_t)MDB_TGT_OBJ_RTLD: - obj = KT_RTLD_NAME; + obj = kt->k_rtld_name; /*FALLTHRU*/ default: @@ -964,7 +989,7 @@ kt_symbol_iter(mdb_tgt_t *t, const char *obj, uint_t which, uint_t type, break; case (uintptr_t)MDB_TGT_OBJ_RTLD: - obj = KT_RTLD_NAME; + obj = kt->k_rtld_name; /*FALLTHRU*/ default: @@ -1092,12 +1117,10 @@ kt_name_to_map(mdb_tgt_t *t, const char *name) return (kt_module_to_map(mdb_list_next(&kt->k_modlist), &m)); if (name == MDB_TGT_OBJ_RTLD) - name = KT_RTLD_NAME; /* replace MDB_TGT_OBJ_RTLD with krtld */ + name = kt->k_rtld_name; - for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) { - if (strcmp(name, km->km_name) == 0) - return (kt_module_to_map(km, &m)); - } + if ((km = kt_module_by_name(kt, name)) != NULL) + return (kt_module_to_map(km, &m)); (void) set_errno(EMDB_NOOBJ); return (NULL); @@ -1200,14 +1223,12 @@ kt_name_to_ctf(mdb_tgt_t *t, const char *name) kt_module_t *km; if (name == MDB_TGT_OBJ_EXEC) - name = KT_CTFPARENT; /* base CTF data is kept in genunix */ + name = KT_CTFPARENT; else if (name == MDB_TGT_OBJ_RTLD) - name = KT_RTLD_NAME; /* replace MDB_TGT_OBJ_RTLD with krtld */ + name = kt->k_rtld_name; - for (km = mdb_list_next(&kt->k_modlist); km; km = mdb_list_next(km)) { - if (strcmp(name, km->km_name) == 0) - return (kt_load_ctfdata(t, km)); - } + if ((km = kt_module_by_name(kt, name)) != NULL) + return (kt_load_ctfdata(t, km)); (void) set_errno(EMDB_NOOBJ); return (NULL); diff --git a/usr/src/cmd/mdb/common/mdb/mdb_kvm.h b/usr/src/cmd/mdb/common/mdb/mdb_kvm.h index 9e4ca6f774..ef85d9179e 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_kvm.h +++ b/usr/src/cmd/mdb/common/mdb/mdb_kvm.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -79,6 +78,7 @@ typedef struct kt_data { int (*k_dump_find_curproc)(); /* mdb_ks dump_find_curproc routine */ char *k_symfile; /* Symbol table pathname */ char *k_kvmfile; /* Core file pathname */ + const char *k_rtld_name; /* module containing krtld */ mdb_map_t k_map; /* Persistant map for callers */ kvm_t *k_cookie; /* Cookie for libkvm routines */ struct as *k_as; /* Kernel VA of kas struct */ diff --git a/usr/src/cmd/mdb/common/modules/genunix/Makefile.files b/usr/src/cmd/mdb/common/modules/genunix/Makefile.files new file mode 100644 index 0000000000..b125e5f21b --- /dev/null +++ b/usr/src/cmd/mdb/common/modules/genunix/Makefile.files @@ -0,0 +1,68 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" + +# +# This file simply contains the list of sources files compiled together +# to create the genunix mdb module. Having them in one place saves +# a bunch of unnecessary replication. +# +GENUNIX_SRCS = \ + avl.c \ + bio.c \ + contract.c \ + cpupart.c \ + ctxop.c \ + cyclic.c \ + devinfo.c \ + findstack.c \ + fm.c \ + genunix.c \ + group.c \ + kgrep.c \ + kmem.c \ + ldi.c \ + leaky.c \ + leaky_subr.c \ + lgrp.c \ + list.c \ + log.c \ + mdi.c \ + memory.c \ + mmd.c \ + modhash.c \ + ndievents.c \ + net.c \ + nvpair.c \ + pg.c \ + rctl.c \ + sobj.c \ + streams.c \ + sysevent.c \ + thread.c \ + tsd.c \ + tsol.c \ + vfs.c \ + zone.c diff --git a/usr/src/cmd/mdb/common/modules/libc/libc.c b/usr/src/cmd/mdb/common/modules/libc/libc.c index a24a8bf6b4..acfa8ad884 100644 --- a/usr/src/cmd/mdb/common/modules/libc/libc.c +++ b/usr/src/cmd/mdb/common/modules/libc/libc.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -566,13 +566,12 @@ d_ulwp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) prt_addr(ulwp.ul_schedctl_called, 1), prt_addr((void *)ulwp.ul_schedctl, 0)); - HD("bindflags gs stsd &ftsd"); + HD("bindflags pad2 stsd &ftsd"); mdb_printf(OFFSTR, OFFSET(ul_bindflags)); mdb_printf(ulwp.ul_bindflags? "0x%-8x " : "%-10d ", ulwp.ul_bindflags); - mdb_printf(ulwp.ul_gs? "0x%-8x " : "%-10d ", - ulwp.ul_gs); + mdb_printf("%-10d ", ulwp.ul_pad2); mdb_printf("%s %s\n", prt_addr(ulwp.ul_stsd, 1), prt_addr((void *)(addr + OFFSET(ul_ftsd[0])), 0)); diff --git a/usr/src/cmd/mdb/i86pc/modules/uppc/intr_common.c b/usr/src/cmd/mdb/i86pc/modules/common/intr_common.c index 9fb1f0e3d3..36f0f78bb7 100644 --- a/usr/src/cmd/mdb/i86pc/modules/uppc/intr_common.c +++ b/usr/src/cmd/mdb/i86pc/modules/common/intr_common.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -29,12 +29,33 @@ #include <sys/multidata.h> #include <sys/gld.h> #include <sys/gldpriv.h> -#include <sys/ddi_intr_impl.h> -#include <sys/cpuvar.h> -int option_flags; -uintptr_t gld_intr_addr; -static struct av_head softvec_tbl[LOCK_LEVEL + 1]; +int option_flags; +uintptr_t gld_intr_addr; +static struct av_head softvec_tbl[LOCK_LEVEL + 1]; + +static char *businfo_array[] = { + " ", + "CBUS", + "CBUSII", + "EISA", + "FUTURE", + "INTERN", + "ISA", + "MBI", + "MBII", + "PCIe", + "MPI", + "MPSA", + "NUBUS", + "PCI", + "PCMCIA", + "TC", + "VL", + "VME", + "XPRESS", + " " +}; void interrupt_help(void) @@ -55,42 +76,6 @@ soft_interrupt_help(void) " -d instead of ISR, print <driver_name><instance#>\n"); } -void -interrupt_print_isr(uintptr_t vector, uintptr_t arg1, uintptr_t dip) -{ - uintptr_t isr_addr = vector; - struct dev_info dev_info; - - /* - * figure out the real ISR function name from gld_intr() - */ - if (isr_addr == gld_intr_addr) { - gld_mac_info_t macinfo; - - if (mdb_vread(&macinfo, sizeof (gld_mac_info_t), arg1) != -1) { - /* verify gld data structure and get the real ISR */ - if (macinfo.gldm_GLD_version == GLD_VERSION) - isr_addr = (uintptr_t)macinfo.gldm_intr; - } - } - - if ((option_flags & INTR_DISPLAY_DRVR_INST) && dip) { - char drvr_name[MODMAXNAMELEN + 1]; - - if (dip && mdb_devinfo2driver(dip, drvr_name, - sizeof (drvr_name)) == 0) { - (void) mdb_vread(&dev_info, sizeof (dev_info), dip); - mdb_printf("%s#%d", drvr_name, dev_info.devi_instance); - } else { - mdb_printf("%a", isr_addr); - } - - } else { - mdb_printf("%a", isr_addr); - } -} - - /* * This is copied from avintr.c * NOTE: Ensure that this definition stays in sync @@ -152,3 +137,164 @@ soft_interrupt_dump(uintptr_t addr, uint_t flags, int argc, return (DCMD_OK); } + +void +interrupt_print_isr(uintptr_t vector, uintptr_t arg1, uintptr_t dip) +{ + uintptr_t isr_addr = vector; + struct dev_info dev_info; + + /* + * figure out the real ISR function name from gld_intr() + */ + if (isr_addr == gld_intr_addr) { + gld_mac_info_t macinfo; + + if (mdb_vread(&macinfo, sizeof (gld_mac_info_t), arg1) != -1) { + /* verify gld data structure and get the real ISR */ + if (macinfo.gldm_GLD_version == GLD_VERSION) + isr_addr = (uintptr_t)macinfo.gldm_intr; + } + } + + if ((option_flags & INTR_DISPLAY_DRVR_INST) && dip) { + char drvr_name[MODMAXNAMELEN + 1]; + + if (dip && mdb_devinfo2driver(dip, drvr_name, + sizeof (drvr_name)) == 0) { + (void) mdb_vread(&dev_info, sizeof (dev_info), dip); + mdb_printf("%s#%d", drvr_name, dev_info.devi_instance); + } else { + mdb_printf("%a", isr_addr); + } + + } else { + mdb_printf("%a", isr_addr); + } +} + +/* + * get_interrupt_type: + * + * Get some interrupt related useful information + * + * NOTE: a0 is clock, c0/d0/e0 are x-calls, e1 is apic_error_intr + * d1/d3 are cbe_fire interrupts + */ +static char * +get_interrupt_type(short index) +{ + if (index == RESERVE_INDEX) + return ("IPI"); + else if (index == ACPI_INDEX) + return ("Fixed"); + else if (index == MSI_INDEX) + return ("MSI"); + else if (index == MSIX_INDEX) + return ("MSI-X"); + else + return ("Fixed"); +} + +void +apic_interrupt_dump(apic_irq_t *irqp, struct av_head *avp, + int i, ushort_t *evtchnp, char level) +{ + int bus_type; + int j; + char *intr_type; + char ioapic_iline[10]; + char ipl[3]; + char cpu_assigned[4]; + char evtchn[8]; + uchar_t assigned_cpu; + struct autovec avhp; + + /* If invalid index; continue */ + if (!irqp->airq_mps_intr_index || + irqp->airq_mps_intr_index == FREE_INDEX) + return; + + /* Figure out interrupt type and trigger information */ + intr_type = get_interrupt_type(irqp->airq_mps_intr_index); + + /* Figure out IOAPIC number and ILINE number */ + if (APIC_IS_MSI_OR_MSIX_INDEX(irqp->airq_mps_intr_index)) + (void) mdb_snprintf(ioapic_iline, 10, "- "); + else { + if (!irqp->airq_ioapicindex && !irqp->airq_intin_no) { + if (strcmp(intr_type, "Fixed") == 0) + (void) mdb_snprintf(ioapic_iline, 10, + "0x%x/0x%x", irqp->airq_ioapicindex, + irqp->airq_intin_no); + else if (irqp->airq_mps_intr_index == RESERVE_INDEX) + (void) mdb_snprintf(ioapic_iline, 10, "- "); + else + (void) mdb_snprintf(ioapic_iline, 10, " "); + } else + (void) mdb_snprintf(ioapic_iline, 10, "0x%x/0x%x", + irqp->airq_ioapicindex, irqp->airq_intin_no); + } + + evtchn[0] = '\0'; + if (evtchnp != NULL) + (void) mdb_snprintf(evtchn, 8, "%-7hd", *evtchnp); + + assigned_cpu = irqp->airq_temp_cpu; + if (assigned_cpu == IRQ_UNINIT || assigned_cpu == IRQ_UNBOUND) + assigned_cpu = irqp->airq_cpu; + bus_type = irqp->airq_iflag.bustype; + + if (irqp->airq_mps_intr_index == RESERVE_INDEX) { + (void) mdb_snprintf(cpu_assigned, 4, "all"); + (void) mdb_snprintf(ipl, 3, "%d", avp->avh_hi_pri); + } else { + (void) mdb_snprintf(cpu_assigned, 4, "%d", assigned_cpu); + (void) mdb_snprintf(ipl, 3, "%d", irqp->airq_ipl); + } + + /* Print each interrupt entry */ + if (option_flags & INTR_DISPLAY_INTRSTAT) + mdb_printf("%-4s", cpu_assigned); + else + mdb_printf("%-3d 0x%x %s%-3s %-6s %-3s %-6s %-4s%-3d %-9s ", + i, irqp->airq_vector, evtchn, ipl, + (bus_type ? businfo_array[bus_type] : " "), + (level ? "Lvl" : "Edg"), + intr_type, cpu_assigned, irqp->airq_share, ioapic_iline); + + /* If valid dip found; print driver name */ + if (irqp->airq_dip) { + (void) mdb_vread(&avhp, sizeof (struct autovec), + (uintptr_t)avp->avh_link); + + /* + * Loop thru all the shared IRQs + */ + if (irqp->airq_share) + interrupt_print_isr((uintptr_t)avhp.av_vector, + (uintptr_t)avhp.av_intarg1, (uintptr_t)avhp.av_dip); + + for (j = 1; irqp->airq_mps_intr_index != FREE_INDEX && + j < irqp->airq_share; j++) { + if (mdb_vread(&avhp, sizeof (struct autovec), + (uintptr_t)avhp.av_link) != -1) { + mdb_printf(", "); + interrupt_print_isr((uintptr_t)avhp.av_vector, + (uintptr_t)avhp.av_intarg1, + (uintptr_t)avhp.av_dip); + } else { + break; + } + } + + } else { + if (irqp->airq_mps_intr_index == RESERVE_INDEX && + !irqp->airq_share) + mdb_printf("poke_cpu"); + else if (mdb_vread(&avhp, sizeof (struct autovec), + (uintptr_t)avp->avh_link) != -1) + mdb_printf("%a", avhp.av_vector); + } + mdb_printf("\n"); +} diff --git a/usr/src/cmd/mdb/i86pc/modules/uppc/intr_common.h b/usr/src/cmd/mdb/i86pc/modules/common/intr_common.h index 74a0b44668..19c90f04bc 100644 --- a/usr/src/cmd/mdb/i86pc/modules/uppc/intr_common.h +++ b/usr/src/cmd/mdb/i86pc/modules/common/intr_common.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -39,16 +39,18 @@ extern "C" { #include <sys/avintr.h> #include <sys/psm_common.h> #include <sys/pic.h> -#include <io/pcplusmp/apic.h> +#include <sys/apic.h> /* * Function prototypes */ -void interrupt_help(void); -void soft_interrupt_help(void); -void interrupt_print_isr(uintptr_t vector, uintptr_t arg1, uintptr_t dip); -int soft_interrupt_dump(uintptr_t addr, uint_t flags, int argc, - const mdb_arg_t *argv); +void interrupt_help(void); +void interrupt_print_isr(uintptr_t, uintptr_t, uintptr_t); +void apic_interrupt_dump(apic_irq_t *, struct av_head *, int i, + ushort_t *, char); + +void soft_interrupt_help(void); +int soft_interrupt_dump(uintptr_t, uint_t, int, const mdb_arg_t *); /* * ::interrupts usage related defines and variables diff --git a/usr/src/cmd/mdb/i86pc/modules/pcplusmp/amd64/Makefile b/usr/src/cmd/mdb/i86pc/modules/pcplusmp/amd64/Makefile index fddfa8db13..88bf7fd4c8 100644 --- a/usr/src/cmd/mdb/i86pc/modules/pcplusmp/amd64/Makefile +++ b/usr/src/cmd/mdb/i86pc/modules/pcplusmp/amd64/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -35,10 +35,10 @@ include ../../../../intel/Makefile.amd64 include ../../../Makefile.i86pc include ../../../../Makefile.module -MODSRCS_DIR = ../../uppc +MODSRCS_DIR = ../../common CPPFLAGS += -DMP -D_MACHDEP CPPFLAGS += -I../../../../common -CPPFLAGS += -I../../uppc +CPPFLAGS += -I../../common CPPFLAGS += -I$(SRC)/uts/intel CPPFLAGS += -I$(SRC)/uts/i86pc diff --git a/usr/src/cmd/mdb/i86pc/modules/pcplusmp/apic.c b/usr/src/cmd/mdb/i86pc/modules/pcplusmp/apic.c index c2c9b6538d..fb8824855a 100644 --- a/usr/src/cmd/mdb/i86pc/modules/pcplusmp/apic.c +++ b/usr/src/cmd/mdb/i86pc/modules/pcplusmp/apic.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -30,154 +30,9 @@ /* * Globals */ -static char *businfo_array[] = { - " ", - "CBUS", - "CBUSII", - "EISA", - "FUTURE", - "INTERN", - "ISA", - "MBI", - "MBII", - "PCIe", - "MPI", - "MPSA", - "NUBUS", - "PCI", - "PCMCIA", - "TC", - "VL", - "VME", - "XPRESS", - " " -}; - static struct av_head avec_tbl[APIC_MAX_VECTOR+1]; - -/* - * get_interrupt_type: - * - * Get some interrupt related useful information - * - * NOTE: a0 is clock, c0/d0/e0 are x-calls, e1 is apic_error_intr - * d1/d3 are cbe_fire interrupts - */ -static char * -get_interrupt_type(short index) -{ - if (index == RESERVE_INDEX) - return ("IPI"); - else if (index == ACPI_INDEX) - return ("Fixed"); - else if (index == MSI_INDEX) - return ("MSI"); - else if (index == MSIX_INDEX) - return ("MSI-X"); - else - return ("Fixed"); -} - -/* - * interrupt_display_info: - * - * Dump interrupt information including shared interrupts. - */ -static void -interrupt_display_info(apic_irq_t irqp, int i) -{ - int bus_type; - int j; - char *intr_type; - char ioapic_iline[10]; - char ipl[3]; - char cpu_assigned[4]; - uchar_t assigned_cpu; - struct autovec avhp; - - /* If invalid index; continue */ - if (!irqp.airq_mps_intr_index || irqp.airq_mps_intr_index == FREE_INDEX) - return; - - /* Figure out interrupt type and trigger information */ - intr_type = get_interrupt_type(irqp.airq_mps_intr_index); - - /* Figure out IOAPIC number and ILINE number */ - if (APIC_IS_MSI_OR_MSIX_INDEX(irqp.airq_mps_intr_index)) - (void) mdb_snprintf(ioapic_iline, 10, "- "); - else { - if (!irqp.airq_ioapicindex && !irqp.airq_intin_no) { - if (strcmp(intr_type, "Fixed") == 0) - (void) mdb_snprintf(ioapic_iline, 10, - "0x%x/0x%x", irqp.airq_ioapicindex, - irqp.airq_intin_no); - else if (irqp.airq_mps_intr_index == RESERVE_INDEX) - (void) mdb_snprintf(ioapic_iline, 10, "- "); - else - (void) mdb_snprintf(ioapic_iline, 10, " "); - } else - (void) mdb_snprintf(ioapic_iline, 10, "0x%x/0x%x", - irqp.airq_ioapicindex, irqp.airq_intin_no); - } - - assigned_cpu = irqp.airq_temp_cpu; - if (assigned_cpu == IRQ_UNINIT || assigned_cpu == IRQ_UNBOUND) - assigned_cpu = irqp.airq_cpu; - bus_type = irqp.airq_iflag.bustype; - - if (irqp.airq_mps_intr_index == RESERVE_INDEX) { - (void) mdb_snprintf(cpu_assigned, 4, "ALL"); - (void) mdb_snprintf(ipl, 3, "%d", avec_tbl[i].avh_hi_pri); - } else { - (void) mdb_snprintf(cpu_assigned, 4, "%d", assigned_cpu); - (void) mdb_snprintf(ipl, 3, "%d", irqp.airq_ipl); - } - - /* Print each interrupt entry */ - if (option_flags & INTR_DISPLAY_INTRSTAT) - mdb_printf("cpu%s\t", cpu_assigned); - else - mdb_printf("%-3d 0x%x %-3s %-5s %-6s%-4s%-3d %-9s ", - i, irqp.airq_vector, ipl, - (bus_type ? businfo_array[bus_type] : " "), - intr_type, cpu_assigned, irqp.airq_share, ioapic_iline); - - /* If valid dip found; print driver name */ - if (irqp.airq_dip) { - (void) mdb_vread(&avhp, sizeof (struct autovec), - (uintptr_t)avec_tbl[i].avh_link); - - /* - * Loop thru all the shared IRQs - */ - if (irqp.airq_share) - interrupt_print_isr((uintptr_t)avhp.av_vector, - (uintptr_t)avhp.av_intarg1, (uintptr_t)avhp.av_dip); - - for (j = 1; irqp.airq_mps_intr_index != FREE_INDEX && - j < irqp.airq_share; j++) { - if (mdb_vread(&avhp, sizeof (struct autovec), - (uintptr_t)avhp.av_link) != -1) { - mdb_printf(", "); - interrupt_print_isr((uintptr_t)avhp.av_vector, - (uintptr_t)avhp.av_intarg1, - (uintptr_t)avhp.av_dip); - } else { - break; - } - } - - } else { - if (irqp.airq_mps_intr_index == RESERVE_INDEX && - !irqp.airq_share) - mdb_printf("poke_cpu"); - else if (mdb_vread(&avhp, sizeof (struct autovec), - (uintptr_t)avec_tbl[i].avh_link) != -1) - mdb_printf("%a", avhp.av_vector); - } - mdb_printf("\n"); -} - +static apic_irq_t *irq_tbl[APIC_MAX_VECTOR+1], airq; +static char level_tbl[APIC_MAX_VECTOR+1]; /* * interrupt_dump: @@ -189,7 +44,6 @@ int interrupt_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { int i; - apic_irq_t *irq_tbl[APIC_MAX_VECTOR+1], irqp; option_flags = 0; if (mdb_getopts(argc, argv, @@ -203,6 +57,11 @@ interrupt_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) return (DCMD_ERR); } + if (mdb_readvar(&level_tbl, "apic_level_intr") == -1) { + mdb_warn("failed to read apic_level_intr"); + return (DCMD_ERR); + } + if (mdb_readvar(&avec_tbl, "autovect") == -1) { mdb_warn("failed to read autovect"); return (DCMD_ERR); @@ -210,21 +69,21 @@ interrupt_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) /* Print the header first */ if (option_flags & INTR_DISPLAY_INTRSTAT) - mdb_printf("%<u>CPU\t "); + mdb_printf("%<u>CPU "); else mdb_printf( - "%<u>IRQ Vector IPL Bus Type CPU Share APIC/INT# "); + "%<u>IRQ Vect IPL Bus Trg Type CPU Share APIC/INT# "); mdb_printf("%s %</u>\n", option_flags & INTR_DISPLAY_DRVR_INST ? "Driver Name(s)" : "ISR(s)"); /* Walk all the entries */ for (i = 0; i < APIC_MAX_VECTOR + 1; i++) { /* Read the entry */ - if (mdb_vread(&irqp, sizeof (apic_irq_t), + if (mdb_vread(&airq, sizeof (apic_irq_t), (uintptr_t)irq_tbl[i]) == -1) continue; - interrupt_display_info(irqp, i); + apic_interrupt_dump(&airq, &avec_tbl[i], i, NULL, level_tbl[i]); } return (DCMD_OK); diff --git a/usr/src/cmd/mdb/i86pc/modules/pcplusmp/ia32/Makefile b/usr/src/cmd/mdb/i86pc/modules/pcplusmp/ia32/Makefile index 3964bf6bde..e0e8edc45b 100644 --- a/usr/src/cmd/mdb/i86pc/modules/pcplusmp/ia32/Makefile +++ b/usr/src/cmd/mdb/i86pc/modules/pcplusmp/ia32/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -34,10 +34,10 @@ include ../../../../intel/Makefile.ia32 include ../../../Makefile.i86pc include ../../../../Makefile.module -MODSRCS_DIR = ../../uppc +MODSRCS_DIR = ../../common CPPFLAGS += -DMP -D_MACHDEP CPPFLAGS += -I../../../../common -CPPFLAGS += -I../../uppc +CPPFLAGS += -I../../common CPPFLAGS += -I$(SRC)/uts/intel CPPFLAGS += -I$(SRC)/uts/i86pc diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile b/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile index 7ed692a12b..08cbabf3e1 100644 --- a/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile +++ b/usr/src/cmd/mdb/i86pc/modules/unix/amd64/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -38,5 +37,5 @@ include ../../../../Makefile.module CPPFLAGS += -DMP -D_MACHDEP CPPFLAGS += -I../../../../common -CPPFLAGS += -I$(SRC)/uts/intel CPPFLAGS += -I$(SRC)/uts/i86pc +CPPFLAGS += -I$(SRC)/uts/intel diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/i86mmu.c b/usr/src/cmd/mdb/i86pc/modules/unix/i86mmu.c index 05577a6cc8..161bd9d9a1 100644 --- a/usr/src/cmd/mdb/i86pc/modules/unix/i86mmu.c +++ b/usr/src/cmd/mdb/i86pc/modules/unix/i86mmu.c @@ -19,10 +19,9 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - #pragma ident "%Z%%M% %I% %E% SMI" /* @@ -37,6 +36,7 @@ #include <sys/types.h> #include <sys/machparam.h> #include <sys/controlregs.h> +#include <sys/mach_mmu.h> #include <vm/as.h> #include <mdb/mdb_modapi.h> @@ -50,7 +50,7 @@ struct pfn2pp { page_t *pp; }; -static int do_va2pfn(uintptr_t, struct as *, int, physaddr_t *); +static int do_va2pa(uintptr_t, struct as *, int, physaddr_t *, pfn_t *); static void get_mmu(void); int @@ -66,7 +66,7 @@ platform_vtop(uintptr_t addr, struct as *asp, physaddr_t *pap) if (mmu.num_level == 0) return (DCMD_ERR); - return (do_va2pfn(addr, asp, 0, pap)); + return (do_va2pa(addr, asp, 0, pap, NULL)); } @@ -134,9 +134,6 @@ page_num2pp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) } - - - /* * ::memseg_list dcmd and walker to implement it. */ @@ -221,20 +218,7 @@ memseg_walk_fini(mdb_walk_state_t *wsp) } /* - * HAT related dcmds: - * - * ::pte [-p XXXXXXXX] [-l 0/1/2/3] - * - * dcmd that interprets the -p argument as a page table entry and - * prints it in more human readable form. The PTE is assumed to be in - * a level 0 page table, unless -l specifies another level. - * - * ::vatopfn [-v] [-a as] - * - * Given a virtual address, returns the PFN, if any, mapped at the address. - * -v shows the intermediate htable/page table entries used to resolve the - * mapping. By default the virtual address is assumed to be in the kernel's - * address space. -a is used to specify a different address space. + * Now HAT related dcmds. */ struct hat *khat; /* value of kas.a_hat */ @@ -261,6 +245,21 @@ get_mmu(void) khat = kas.a_hat; } +#define mdb_ma_to_pa(ma) (ma) +#define mdb_mfn_to_pfn(mfn) (mfn) +#define mdb_pfn_to_mfn(pfn) (pfn) + +static pfn_t +pte2mfn(x86pte_t pte, uint_t level) +{ + pfn_t mfn; + if (level > 0 && (pte & PT_PAGESIZE)) + mfn = mmu_btop(pte & PT_PADDR_LGPG); + else + mfn = mmu_btop(pte & PT_PADDR); + return (mfn); +} + /* * Print a PTE in more human friendly way. The PTE is assumed to be in * a level 0 page table, unless -l specifies another level. @@ -275,12 +274,14 @@ do_pte_dcmd(int level, uint64_t pte) "wrback", "wrthru", "uncached", "uncached", "wrback", "wrthru", "wrcombine", "uncached"}; int pat_index = 0; + pfn_t mfn; - mdb_printf("PTE=%llx: ", pte); + mdb_printf("pte=%llr: ", pte); if (PTE_GET(pte, mmu.pt_nx)) mdb_printf("noexec "); - mdb_printf("page=0x%llx ", PTE2PFN(pte, level)); + mfn = pte2mfn(pte, level); + mdb_printf("%s=0x%lr ", "pfn", mfn); if (PTE_GET(pte, PT_NOCONSIST)) mdb_printf("noconsist "); @@ -387,8 +388,43 @@ pte_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) return (do_pte_dcmd(level, pte)); } +static size_t +va2entry(htable_t *htable, uintptr_t addr) +{ + size_t entry = (addr - htable->ht_vaddr); + + entry >>= mmu.level_shift[htable->ht_level]; + return (entry & HTABLE_NUM_PTES(htable) - 1); +} + +static x86pte_t +get_pte(hat_t *hat, htable_t *htable, uintptr_t addr) +{ + x86pte_t buf; + x86pte32_t *pte32 = (x86pte32_t *)&buf; + size_t len; + + if (htable->ht_flags & HTABLE_VLP) { + uintptr_t ptr = (uintptr_t)hat->hat_vlp_ptes; + ptr += va2entry(htable, addr) << mmu.pte_size_shift; + len = mdb_vread(&buf, mmu.pte_size, ptr); + } else { + paddr_t paddr = mmu_ptob((paddr_t)htable->ht_pfn); + paddr += va2entry(htable, addr) << mmu.pte_size_shift; + len = mdb_pread(&buf, mmu.pte_size, paddr); + } + + if (len != mmu.pte_size) + return (0); + + if (mmu.pte_size == sizeof (x86pte_t)) + return (buf); + return (*pte32); +} + static int -do_va2pfn(uintptr_t addr, struct as *asp, int print_level, physaddr_t *pap) +do_va2pa(uintptr_t addr, struct as *asp, int print_level, physaddr_t *pap, + pfn_t *mfnp) { struct as as; struct hat *hatp; @@ -400,10 +436,7 @@ do_va2pfn(uintptr_t addr, struct as *asp, int print_level, physaddr_t *pap) int level; int found = 0; x86pte_t pte; - x86pte_t buf; - x86pte32_t *pte32 = (x86pte32_t *)&buf; physaddr_t paddr; - size_t len; if (asp != NULL) { if (mdb_vread(&as, sizeof (as), (uintptr_t)asp) == -1) { @@ -426,9 +459,8 @@ do_va2pfn(uintptr_t addr, struct as *asp, int print_level, physaddr_t *pap) /* * read the htable hashtable */ - *pap = 0; for (level = 0; level <= mmu.max_level; ++level) { - if (level == mmu.max_level) + if (level == TOP_LEVEL(&hat)) base = 0; else base = addr & mmu.level_mask[level + 1]; @@ -445,38 +477,38 @@ do_va2pfn(uintptr_t addr, struct as *asp, int print_level, physaddr_t *pap) mdb_warn("Couldn't read htable\n"); return (DCMD_ERR); } + if (htable.ht_vaddr != base || htable.ht_level != level) continue; - /* - * found - read the page table entry - */ - paddr = htable.ht_pfn << MMU_PAGESHIFT; - paddr += ((addr - base) >> - mmu.level_shift[level]) << - mmu.pte_size_shift; - len = mdb_pread(&buf, mmu.pte_size, paddr); - if (len != mmu.pte_size) - return (DCMD_ERR); - if (mmu.pte_size == sizeof (x86pte_t)) - pte = buf; - else - pte = *pte32; + pte = get_pte(&hat, &htable, addr); - if (!found) { - if (PTE_IS_LGPG(pte, level)) - paddr = pte & PT_PADDR_LGPG; - else - paddr = pte & PT_PADDR; - paddr += addr & mmu.level_offset[level]; - *pap = paddr; - found = 1; + if (print_level) { + mdb_printf("\tlevel=%d htable=%p " + "pte=%llr\n", level, ht, pte); } - if (print_level == 0) + + if (!PTE_ISVALID(pte)) { + mdb_printf("Address %p is unmapped.\n", + addr); + return (DCMD_ERR); + } + + if (found) continue; - mdb_printf("\tlevel=%d htable=%p pte=%llx\n", - level, ht, pte); + + if (PTE_IS_LGPG(pte, level)) + paddr = mdb_ma_to_pa(pte & + PT_PADDR_LGPG); + else + paddr = mdb_ma_to_pa(pte & PT_PADDR); + paddr += addr & mmu.level_offset[level]; + if (pap != NULL) + *pap = paddr; + if (mfnp != NULL) + *mfnp = pte2mfn(pte, level); + found = 1; } } } @@ -492,7 +524,9 @@ va2pfn_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uintptr_t addrspace; char *addrspace_str = NULL; - uint64_t physaddr; + int piped = flags & DCMD_PIPE_OUT; + pfn_t pfn; + pfn_t mfn; int rc; /* @@ -517,12 +551,26 @@ va2pfn_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) else addrspace = 0; - rc = do_va2pfn(addr, (struct as *)addrspace, 1, &physaddr); + rc = do_va2pa(addr, (struct as *)addrspace, !piped, NULL, &mfn); + + if (rc != DCMD_OK) + return (rc); + + if ((pfn = mdb_mfn_to_pfn(mfn)) == -(pfn_t)1) { + mdb_warn("Invalid mfn %lr\n", mfn); + return (DCMD_ERR); + } + + if (piped) { + mdb_printf("0x%lr\n", pfn); + return (DCMD_OK); + } - if (rc == DCMD_OK) - mdb_printf("Virtual %p maps Physical %llx\n", addr, physaddr); + mdb_printf("Virtual address 0x%p maps pfn 0x%lr", addr, pfn); - return (rc); + mdb_printf("\n"); + + return (DCMD_OK); } /* @@ -596,8 +644,9 @@ do_report_maps(pfn_t pfn) level = htable.ht_level; if (level > mmu.max_page_level) continue; - paddr = htable.ht_pfn << MMU_PAGESHIFT; - for (entry = 0; entry < htable.ht_num_ptes; + paddr = mmu_ptob((physaddr_t)htable.ht_pfn); + for (entry = 0; + entry < HTABLE_NUM_PTES(&htable); ++entry) { base = htable.ht_vaddr + entry * @@ -625,7 +674,7 @@ do_report_maps(pfn_t pfn) pte &= PT_PADDR; else pte &= PT_PADDR_LGPG; - if ((pte >> MMU_PAGESHIFT) != pfn) + if (mmu_btop(mdb_ma_to_pa(pte)) != pfn) continue; mdb_printf("hat=%p maps addr=%p\n", hatp, (caddr_t)base); @@ -645,6 +694,9 @@ done: int report_maps_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { + pfn_t pfn; + uint_t mflag = 0; + /* * The kernel has to at least have made it thru mmu_init() */ @@ -655,12 +707,17 @@ report_maps_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if ((flags & DCMD_ADDRSPEC) == 0) return (DCMD_USAGE); - return (do_report_maps((pfn_t)addr)); + if (mdb_getopts(argc, argv, + 'm', MDB_OPT_SETBITS, TRUE, &mflag, NULL) != argc) + return (DCMD_USAGE); + + pfn = (pfn_t)addr; + if (mflag) + pfn = mdb_mfn_to_pfn(pfn); + + return (do_report_maps(pfn)); } -/* - * Dump the page table at the given PFN - */ static int do_ptable_dcmd(pfn_t pfn) { @@ -730,7 +787,7 @@ found_it: pagesize = MMU_PAGESIZE; } - paddr = pfn << MMU_PAGESHIFT; + paddr = mmu_ptob((physaddr_t)pfn); for (entry = 0; entry < mmu.ptes_per_table; ++entry) { len = mdb_pread(&buf, mmu.pte_size, paddr + entry * mmu.pte_size); @@ -753,12 +810,82 @@ done: } /* - * given a PFN as its address argument, prints out the uses of it + * Dump the page table at the given PFN */ /*ARGSUSED*/ int ptable_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { + pfn_t pfn; + uint_t mflag = 0; + + /* + * The kernel has to at least have made it thru mmu_init() + */ + get_mmu(); + if (mmu.num_level == 0) + return (DCMD_ERR); + + if ((flags & DCMD_ADDRSPEC) == 0) + return (DCMD_USAGE); + + if (mdb_getopts(argc, argv, + 'm', MDB_OPT_SETBITS, TRUE, &mflag, NULL) != argc) + return (DCMD_USAGE); + + pfn = (pfn_t)addr; + if (mflag) + pfn = mdb_mfn_to_pfn(pfn); + + return (do_ptable_dcmd(pfn)); +} + +static int +do_htables_dcmd(hat_t *hatp) +{ + struct hat hat; + htable_t *ht; + htable_t htable; + int h; + + /* + * read the hat and its hash table + */ + if (mdb_vread(&hat, sizeof (hat), (uintptr_t)hatp) == -1) { + mdb_warn("Couldn't read struct hat\n"); + return (DCMD_ERR); + } + + /* + * read the htable hashtable + */ + for (h = 0; h < hat.hat_num_hash; ++h) { + if (mdb_vread(&ht, sizeof (htable_t *), + (uintptr_t)(hat.hat_ht_hash + h)) == -1) { + mdb_warn("Couldn't read htable ptr\\n"); + return (DCMD_ERR); + } + for (; ht != NULL; ht = htable.ht_next) { + mdb_printf("%p\n", ht); + if (mdb_vread(&htable, sizeof (htable_t), + (uintptr_t)ht) == -1) { + mdb_warn("Couldn't read htable\n"); + return (DCMD_ERR); + } + } + } + return (DCMD_OK); +} + +/* + * Dump the htables for the given hat + */ +/*ARGSUSED*/ +int +htables_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + hat_t *hat; + /* * The kernel has to at least have made it thru mmu_init() */ @@ -769,5 +896,7 @@ ptable_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if ((flags & DCMD_ADDRSPEC) == 0) return (DCMD_USAGE); - return (do_ptable_dcmd((pfn_t)addr)); + hat = (hat_t *)addr; + + return (do_htables_dcmd(hat)); } diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/i86mmu.h b/usr/src/cmd/mdb/i86pc/modules/unix/i86mmu.h index 6b01d31c47..5f86f0fd5e 100644 --- a/usr/src/cmd/mdb/i86pc/modules/unix/i86mmu.h +++ b/usr/src/cmd/mdb/i86pc/modules/unix/i86mmu.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -39,6 +38,9 @@ extern int pte_dcmd(uintptr_t addr, uint_t flags, int argc, extern int report_maps_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv); +extern int htables_dcmd(uintptr_t addr, uint_t flags, int argc, + const mdb_arg_t *argv); + extern int ptable_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv); diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/ia32/Makefile b/usr/src/cmd/mdb/i86pc/modules/unix/ia32/Makefile index edb2d65a68..8121af9b49 100644 --- a/usr/src/cmd/mdb/i86pc/modules/unix/ia32/Makefile +++ b/usr/src/cmd/mdb/i86pc/modules/unix/ia32/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -37,5 +36,5 @@ include ../../../../Makefile.module CPPFLAGS += -DMP -D_MACHDEP CPPFLAGS += -I../../../../common -CPPFLAGS += -I$(SRC)/uts/intel CPPFLAGS += -I$(SRC)/uts/i86pc +CPPFLAGS += -I$(SRC)/uts/intel diff --git a/usr/src/cmd/mdb/i86pc/modules/unix/unix.c b/usr/src/cmd/mdb/i86pc/modules/unix/unix.c index 21921df599..d251ee9e11 100644 --- a/usr/src/cmd/mdb/i86pc/modules/unix/unix.c +++ b/usr/src/cmd/mdb/i86pc/modules/unix/unix.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,6 +30,7 @@ #include <sys/cpuvar.h> #include <sys/systm.h> #include <sys/traptrace.h> +#include <sys/x_call.h> #include <sys/avintr.h> #include <sys/systm.h> #include <sys/trap.h> @@ -186,11 +186,10 @@ ttrace_syscall(trap_trace_rec_t *rec) uintptr_t addr; struct sysent sys; - mdb_printf("%s%-*x", sysnum < 0x10 ? " " : "", - sysnum < 0x10 ? 2 : 3, sysnum); + mdb_printf("%-3x", sysnum); if (rec->ttr_sysnum > NSYSCALL) { - mdb_printf("%-*d", TT_HDLR_WIDTH, rec->ttr_sysnum); + mdb_printf(" %-*d", TT_HDLR_WIDTH, rec->ttr_sysnum); return (0); } @@ -211,7 +210,7 @@ ttrace_syscall(trap_trace_rec_t *rec) return (-1); } - mdb_printf("%-*a", TT_HDLR_WIDTH, sys.sy_callc); + mdb_printf(" %-*a", TT_HDLR_WIDTH, sys.sy_callc); return (0); } @@ -224,12 +223,15 @@ ttrace_interrupt(trap_trace_rec_t *rec) struct av_head hd; struct autovec av; - if (rec->ttr_regs.r_trapno == T_SOFTINT) { - mdb_printf("%2s %-*s", "-", TT_HDLR_WIDTH, "(fakesoftint)"); + switch (rec->ttr_regs.r_trapno) { + case T_SOFTINT: + mdb_printf("%-3s %-*s", "-", TT_HDLR_WIDTH, "(fakesoftint)"); return (0); + default: + break; } - mdb_printf("%2x ", rec->ttr_vector); + mdb_printf("%-3x ", rec->ttr_vector); if (mdb_lookup_by_name("autovect", &sym) == -1) { mdb_warn("\ncouldn't find 'autovect'"); @@ -250,7 +252,10 @@ ttrace_interrupt(trap_trace_rec_t *rec) } if (hd.avh_link == NULL) { - mdb_printf("%-*s", TT_HDLR_WIDTH, "(spurious)"); + if (rec->ttr_ipl == XC_CPUPOKE_PIL) + mdb_printf("%-*s", TT_HDLR_WIDTH, "(cpupoke)"); + else + mdb_printf("%-*s", TT_HDLR_WIDTH, "(spurious)"); } else { if (mdb_vread(&av, sizeof (av), (uintptr_t)hd.avh_link) == -1) { mdb_warn("couldn't read autovec at %p", @@ -286,6 +291,17 @@ static struct { { T_ALIGNMENT, "alignment-check" }, { T_MCE, "machine-check" }, { T_SIMDFPE, "sse-exception" }, + + { T_DBGENTR, "debug-enter" }, + { T_FASTTRAP, "fasttrap-0xd2" }, + { T_SYSCALLINT, "syscall-0x91" }, + { T_DTRACE_RET, "dtrace-ret" }, + { T_SOFTINT, "softint" }, + { T_INTERRUPT, "interrupt" }, + { T_FAULT, "fault" }, + { T_AST, "ast" }, + { T_SYSCALL, "syscall" }, + { 0, NULL } }; @@ -294,7 +310,10 @@ ttrace_trap(trap_trace_rec_t *rec) { int i; - mdb_printf("%2x ", rec->ttr_regs.r_trapno); + if (rec->ttr_regs.r_trapno == T_AST) + mdb_printf("%-3s ", "-"); + else + mdb_printf("%-3x ", rec->ttr_regs.r_trapno); for (i = 0; ttrace_traps[i].tt_name != NULL; i++) { if (rec->ttr_regs.r_trapno == ttrace_traps[i].tt_trapno) @@ -310,6 +329,137 @@ ttrace_trap(trap_trace_rec_t *rec) } static struct { + int tt_type; + char *tt_name; +} ttrace_xcalls[] = { + { TT_XC_SVC_BEGIN, "<svc-begin>" }, + { TT_XC_SVC_END, "<svc-end>" }, + { TT_XC_START, "<start>" }, + { TT_XC_WAIT, "<wait>" }, + { TT_XC_ACK, "<ack>" }, + { TT_XC_CAPTURE, "<capture>" }, + { TT_XC_RELEASE, "<release>" }, + { TT_XC_POKE_CPU, "<poke-cpu>" }, + { TT_XC_CBE_FIRE, "<cbe-fire>" }, + { TT_XC_CBE_XCALL, "<cbe-xcall>" }, + { 0, NULL } +}; + +static int +ttrace_xcall(trap_trace_rec_t *rec) +{ + struct _xc_entry *xce = &(rec->ttr_info.xc_entry); + int i; + + for (i = 0; ttrace_xcalls[i].tt_name != NULL; i++) + if (ttrace_xcalls[i].tt_type == xce->xce_marker) + break; + + switch (xce->xce_marker) { + case TT_XC_SVC_BEGIN: + case TT_XC_SVC_END: + mdb_printf("%3s ", "-"); + break; + default: + mdb_printf("%3x ", (int)xce->xce_arg); + break; + } + + if (ttrace_xcalls[i].tt_name == NULL) + mdb_printf("%-*s", TT_HDLR_WIDTH, "(unknown)"); + else + mdb_printf("%-*s", TT_HDLR_WIDTH, ttrace_xcalls[i].tt_name); + return (0); +} + +static char * +xc_pri_to_str(int pri) +{ + switch (pri) { + case X_CALL_LOPRI: + return (" low"); + case X_CALL_MEDPRI: + return (" med"); + case X_CALL_HIPRI: + return ("high"); + default: + return ("bad?"); + } +} + +static char * +xc_state_to_str(uint8_t state) +{ + switch (state) { + case XC_DONE: + return ("done"); + case XC_HOLD: + return ("hold"); + case XC_SYNC_OP: + return ("sync"); + case XC_CALL_OP: + return ("call"); + case XC_WAIT: + return ("wait"); + default: + return ("bad?"); + } +} + +static void +ttrace_intr_detail(trap_trace_rec_t *rec) +{ + mdb_printf("\tirq %x ipl %d oldpri %d basepri %d\n", rec->ttr_vector, + rec->ttr_ipl, rec->ttr_pri, rec->ttr_spl); +} + +static void +ttrace_xcall_detail(trap_trace_rec_t *rec) +{ + struct _xc_entry *xce = &(rec->ttr_info.xc_entry); + + if ((uint_t)xce->xce_pri < X_CALL_LEVELS) + mdb_printf("\t%s pri [%s] ", xc_pri_to_str(xce->xce_pri), + xc_state_to_str(xce->xce_state)); + else + mdb_printf("\t"); + + switch (xce->xce_marker) { + case TT_XC_SVC_BEGIN: + if (xce->xce_pri != X_CALL_MEDPRI && xce->xce_func != NULL) + mdb_printf("call %a() ..", xce->xce_func); + break; + case TT_XC_SVC_END: + if (xce->xce_arg == DDI_INTR_UNCLAIMED) + mdb_printf("[spurious]"); + else if (xce->xce_pri != X_CALL_MEDPRI && + xce->xce_func != NULL) + mdb_printf(".. called %a() returned %d", + xce->xce_func, xce->xce_retval); + break; + case TT_XC_START: + case TT_XC_CAPTURE: + mdb_printf("--> cpu%d", (int)xce->xce_arg); + break; + case TT_XC_RELEASE: + case TT_XC_WAIT: + case TT_XC_ACK: + mdb_printf("<-- cpu%d", (int)xce->xce_arg); + break; + case TT_XC_POKE_CPU: + case TT_XC_CBE_FIRE: + case TT_XC_CBE_XCALL: + mdb_printf("--> cpu%d", (int)xce->xce_arg); + break; + default: + mdb_printf("tag %d? arg 0x%lx", + xce->xce_marker, xce->xce_arg); + break; + } + mdb_printf("\n\n"); +} + +static struct { uchar_t t_marker; char *t_name; int (*t_hdlr)(trap_trace_rec_t *); @@ -320,6 +470,8 @@ static struct { { TT_SYSC64, "sc64", ttrace_syscall }, { TT_INTERRUPT, "intr", ttrace_interrupt }, { TT_TRAP, "trap", ttrace_trap }, + { TT_EVENT, "evnt", ttrace_trap }, + { TT_XCALL, "xcal", ttrace_xcall }, { 0, NULL, NULL } }; @@ -333,7 +485,6 @@ typedef struct ttrace_dcmd { #define DUMP(reg) #reg, regs->r_##reg #define THREEREGS " %3s: %16lx %3s: %16lx %3s: %16lx\n" -#define TWOREGS " %3s: %16lx %3s: %16lx\n" static void ttrace_dumpregs(trap_trace_rec_t *rec) @@ -345,12 +496,10 @@ ttrace_dumpregs(trap_trace_rec_t *rec) mdb_printf(THREEREGS, DUMP(rax), DUMP(rbx), DUMP(rbp)); mdb_printf(THREEREGS, DUMP(r10), DUMP(r11), DUMP(r12)); mdb_printf(THREEREGS, DUMP(r13), DUMP(r14), DUMP(r15)); - mdb_printf(THREEREGS, "fsb", regs->r_fsbase, "gsb", regs->r_gsbase, - DUMP(ds)); - mdb_printf(THREEREGS, DUMP(es), DUMP(fs), DUMP(gs)); - mdb_printf(THREEREGS, "trp", regs->r_trapno, DUMP(err), DUMP(rip)); - mdb_printf(THREEREGS, DUMP(cs), DUMP(rfl), DUMP(rsp)); - mdb_printf(TWOREGS, DUMP(ss), "cr2", rec->ttr_cr2); + mdb_printf(THREEREGS, DUMP(ds), DUMP(es), DUMP(fs)); + mdb_printf(THREEREGS, DUMP(gs), "trp", regs->r_trapno, DUMP(err)); + mdb_printf(THREEREGS, DUMP(rip), DUMP(cs), DUMP(rfl)); + mdb_printf(THREEREGS, DUMP(rsp), DUMP(ss), "cr2", rec->ttr_cr2); mdb_printf("\n"); } @@ -408,12 +557,17 @@ ttrace_walk(uintptr_t addr, trap_trace_rec_t *rec, ttrace_dcmd_t *dcmd) return (WALK_ERR); } - mdb_printf("%a\n", regs->r_pc); + mdb_printf(" %a\n", regs->r_pc); if (dcmd->ttd_extended == FALSE) return (WALK_NEXT); - ttrace_dumpregs(rec); + if (rec->ttr_marker == TT_XCALL) + ttrace_xcall_detail(rec); + else if (rec->ttr_marker == TT_INTERRUPT) + ttrace_intr_detail(rec); + else + ttrace_dumpregs(rec); if (rec->ttr_sdepth > 0) { for (i = 0; i < rec->ttr_sdepth; i++) { @@ -459,8 +613,8 @@ ttrace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (DCMD_HDRSPEC(flags)) { mdb_printf("%3s %15s %4s %2s %-*s%s\n", "CPU", - "TIMESTAMP", "TYPE", "VC", TT_HDLR_WIDTH, "HANDLER", - "EIP"); + "TIMESTAMP", "TYPE", "Vec", TT_HDLR_WIDTH, "HANDLER", + " EIP"); } if (flags & DCMD_ADDRSPEC) { @@ -618,15 +772,47 @@ idt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) return (DCMD_OK); } +static void +htables_help(void) +{ + mdb_printf( + "Given a (hat_t *), generates the list of all (htable_t *)s\n" + "that correspond to that address space\n"); +} + +static void +report_maps_help(void) +{ + mdb_printf( + "Given a PFN, report HAT structures that map the page, or use\n" + "the page as a pagetable.\n" + "\n" + "-m Interpret the PFN as a Xen MFN (machine frame number)\n"); +} + +static void +ptable_help(void) +{ + mdb_printf( + "Given a PFN holding a page table, print its contents, and\n" + "the address of the corresponding htable structure.\n" + "\n" + "-m Interpret the PFN as a Xen MFN (machine frame number)\n"); +} + static const mdb_dcmd_t dcmds[] = { { "gate_desc", ":", "dump a gate descriptor", gate_desc }, { "idt", ":[-v]", "dump an IDT", idt }, { "ttrace", "[-x]", "dump trap trace buffers", ttrace }, { "vatopfn", ":[-a as]", "translate address to physical page", va2pfn_dcmd }, - { "report_maps", "", "Given PFN, report mappings / page table usage", - report_maps_dcmd }, - { "ptable", "", "Dump contents of a page table", ptable_dcmd }, + { "report_maps", ":[-m]", + "Given PFN, report mappings / page table usage", + report_maps_dcmd, report_maps_help }, + { "htables", "", "Given hat_t *, lists all its htable_t * values", + htables_dcmd, htables_help }, + { "ptable", ":[-m]", "Given PFN, dump contents of a page table", + ptable_dcmd, ptable_help }, { "pte", ":[-p XXXXX] [-l N]", "print human readable page table entry", pte_dcmd }, { "page_num2pp", ":", "page frame number to page structure", diff --git a/usr/src/cmd/mdb/i86pc/modules/uppc/amd64/Makefile b/usr/src/cmd/mdb/i86pc/modules/uppc/amd64/Makefile index 0bcf1cd107..501eecf8c5 100644 --- a/usr/src/cmd/mdb/i86pc/modules/uppc/amd64/Makefile +++ b/usr/src/cmd/mdb/i86pc/modules/uppc/amd64/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -35,7 +35,10 @@ include ../../../../intel/Makefile.amd64 include ../../../Makefile.i86pc include ../../../../Makefile.module +MODSRCS_DIR = ../../common + CPPFLAGS += -DMP -D_MACHDEP +CPPFLAGS += -I../../common CPPFLAGS += -I../../../../common CPPFLAGS += -I$(SRC)/uts/intel CPPFLAGS += -I$(SRC)/uts/i86pc diff --git a/usr/src/cmd/mdb/i86pc/modules/uppc/ia32/Makefile b/usr/src/cmd/mdb/i86pc/modules/uppc/ia32/Makefile index e7778d3e05..f10ce9e177 100644 --- a/usr/src/cmd/mdb/i86pc/modules/uppc/ia32/Makefile +++ b/usr/src/cmd/mdb/i86pc/modules/uppc/ia32/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -34,7 +34,10 @@ include ../../../../intel/Makefile.ia32 include ../../../Makefile.i86pc include ../../../../Makefile.module +MODSRCS_DIR = ../../common + CPPFLAGS += -DMP -D_MACHDEP +CPPFLAGS += -I../../common CPPFLAGS += -I../../../../common CPPFLAGS += -I$(SRC)/uts/intel CPPFLAGS += -I$(SRC)/uts/i86pc diff --git a/usr/src/cmd/mdb/i86pc/modules/uppc/uppc.c b/usr/src/cmd/mdb/i86pc/modules/uppc/uppc.c index be910bbcb7..fee48b58f5 100644 --- a/usr/src/cmd/mdb/i86pc/modules/uppc/uppc.c +++ b/usr/src/cmd/mdb/i86pc/modules/uppc/uppc.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -110,7 +110,7 @@ uppc_interrupt_dump(uintptr_t addr, uint_t flags, int argc, /* Print the header first */ if (option_flags & INTR_DISPLAY_INTRSTAT) - mdb_printf("%<u>CPU\t "); + mdb_printf("%<u>CPU "); else mdb_printf("%<u>IRQ Vector IPL(lo/hi) Bus Share "); mdb_printf("%s %</u>\n", option_flags & INTR_DISPLAY_DRVR_INST ? diff --git a/usr/src/cmd/mdb/intel/Makefile.kmdb b/usr/src/cmd/mdb/intel/Makefile.kmdb index 67c6d7c92b..7026ef906c 100644 --- a/usr/src/cmd/mdb/intel/Makefile.kmdb +++ b/usr/src/cmd/mdb/intel/Makefile.kmdb @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -34,9 +34,6 @@ PROMSRCS += \ KMDBSRCS += \ kaif.c \ - kaif_activate.c \ - kaif_idt.c \ - kaif_start_isadep.c \ kmdb_dpi_isadep.c \ kmdb_fault_isadep.c \ kmdb_kdi_isadep.c \ @@ -46,7 +43,6 @@ KMDBSRCS += \ kvm_isadep.c KMDBML += \ - kaif_idthdl.s \ kmdb_asmutil.s \ kmdb_setcontext.s diff --git a/usr/src/cmd/mdb/intel/amd64/Makefile.kmdb b/usr/src/cmd/mdb/intel/amd64/Makefile.kmdb index 93e99f8aa6..324572a024 100644 --- a/usr/src/cmd/mdb/intel/amd64/Makefile.kmdb +++ b/usr/src/cmd/mdb/intel/amd64/Makefile.kmdb @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,27 +19,18 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" # KMDBML += \ - kaif_asmutil.s \ kaif_invoke.s \ - kaif_resume.s \ - kaif_startup.s \ kmdb_start.s KMDBSRCS += \ kmdb_makecontext.c \ mdb_amd64util.c -REGOFFUSERS = \ - kaif_resume.o \ - kaif_startup.o - SACPPFLAGS = -D__$(MACH64) -U__$(MACH) - -$(REGOFFUSERS) $(REGOFFUSERS:%.o=%.ln): kaif_off.h diff --git a/usr/src/cmd/mdb/intel/amd64/genunix/Makefile b/usr/src/cmd/mdb/intel/amd64/genunix/Makefile index 801d16db46..980d83ae29 100644 --- a/usr/src/cmd/mdb/intel/amd64/genunix/Makefile +++ b/usr/src/cmd/mdb/intel/amd64/genunix/Makefile @@ -29,43 +29,10 @@ MODULE = genunix.so MDBTGT = kvm +include ../../../common/modules/genunix/Makefile.files + COMMONSRCS = \ - avl.c \ - bio.c \ - contract.c \ - cpupart.c \ - ctxop.c \ - cyclic.c \ - devinfo.c \ - findstack.c \ - fm.c \ - genunix.c \ - group.c \ - kgrep.c \ - kmem.c \ - ldi.c \ - leaky.c \ - leaky_subr.c \ - lgrp.c \ - list.c \ - log.c \ - mdi.c \ - memory.c \ - mmd.c \ - modhash.c \ - ndievents.c \ - net.c \ - nvpair.c \ - pg.c \ - rctl.c \ - sobj.c \ - streams.c \ - sysevent.c \ - thread.c \ - tsd.c \ - tsol.c \ - vfs.c \ - zone.c + $(GENUNIX_SRCS) KMODSRCS = \ $(COMMONSRCS) diff --git a/usr/src/cmd/mdb/intel/amd64/kmdb/Makefile b/usr/src/cmd/mdb/intel/amd64/kmdb/Makefile index e5094fc27b..c22ed7a256 100644 --- a/usr/src/cmd/mdb/intel/amd64/kmdb/Makefile +++ b/usr/src/cmd/mdb/intel/amd64/kmdb/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -88,9 +88,6 @@ lintprom: $(PROMOBJS:%.o=%.ln) lintkctl: $(KCTLOBJS:%.o=%.ln) $(LINT) $(ALLLINTFLAGS) $(KCTLOBJS:%.o=%.ln) -kaif_off.h: ../../kmdb/kaif_off.in - $(OFFSETS_CREATE) <../../kmdb/kaif_off.in >$@ - kmdb_context_off.h: ../../kmdb/kmdb_context_off.in $(OFFSETS_CREATE) <../../kmdb/kmdb_context_off.in >$@ diff --git a/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.h b/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.h deleted file mode 100644 index 6abe1ba166..0000000000 --- a/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _KAIF_ASMUTIL_H -#define _KAIF_ASMUTIL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/segments.h> - -#include <kmdb/kaif_regs.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _ASM - -/* - * Multiple CPUs won't be present until cross-call initialization has - * completed. Until that time, we just assume we're CPU zero. - * - * This macro returns the CPUID in %rax, and doesn't clobber any other - * registers. - */ -#define GET_CPUID \ - call kmdb_kdi_xc_initialized; \ - cmpq $0, %rax; \ - je 1f; \ - movzbq %gs:CPU_ID, %rax; \ - jmp 2f; \ -1: \ - clrq %rax; \ -2: - -/* clobbers %rdx, %rcx, returns addr in %rax, CPU ID in %rbx */ -#define GET_CPUSAVE_ADDR \ - GET_CPUID; \ - movq %rax, %rbx; \ - movq $KRS_SIZE, %rcx; \ - mulq %rcx; \ - movq $kaif_cpusave, %rdx; \ - /*CSTYLED*/ \ - addq (%rdx), %rax - -/* - * Save copies of the IDT and GDT descriptors. Note that we only save the IDT - * and GDT if the IDT isn't ours, as we may be legitimately re-entering the - * debugger through the trap handler. We don't want to clobber the saved IDT - * in the process, as we'd end up resuming the world on our IDT. - * - * assumes cpusave in %rax, clobbers %rcx - */ -#define SAVE_IDTGDT \ - sidt KRS_TMPDESC(%rax); \ - movq KRS_TMPDESC+2(%rax), %rcx; \ - cmpq $kaif_idt, %rcx; \ - je 1f; \ - sidt KRS_IDTR(%rax); \ - sgdt KRS_GDTR(%rax); \ -1: - -/* %ss, %rsp, %rflags, %cs, %rip, %err, %trapno already on stack */ -#define KAIF_SAVE_REGS(base) \ - movq %rdi, REG_OFF(KREG_RDI)(base); \ - movq %rsi, REG_OFF(KREG_RSI)(base); \ - movq %rdx, REG_OFF(KREG_RDX)(base); \ - movq %rcx, REG_OFF(KREG_RCX)(base); \ - movq %r8, REG_OFF(KREG_R8)(base); \ - movq %r9, REG_OFF(KREG_R9)(base); \ - movq %rax, REG_OFF(KREG_RAX)(base); \ - movq %rbx, REG_OFF(KREG_RBX)(base); \ - movq %rbp, REG_OFF(KREG_RBP)(base); \ - movq %r10, REG_OFF(KREG_R10)(base); \ - movq %r11, REG_OFF(KREG_R11)(base); \ - movq %r12, REG_OFF(KREG_R12)(base); \ - movq %r13, REG_OFF(KREG_R13)(base); \ - movq %r14, REG_OFF(KREG_R14)(base); \ - movq %r15, REG_OFF(KREG_R15)(base); \ - movq %rbp, REG_OFF(KREG_SAVFP)(base); \ - movq REG_OFF(KREG_RIP)(base), %rax; \ - movq %rax, REG_OFF(KREG_SAVPC)(base); \ - \ - movl $MSR_AMD_FSBASE, %ecx; \ - rdmsr; \ - movl %eax, REG_OFF(KREG_FSBASE)(base); \ - movl %edx, _CONST(REG_OFF(KREG_FSBASE)+4)(base); \ - \ - movl $MSR_AMD_GSBASE, %ecx; \ - rdmsr; \ - movl %eax, REG_OFF(KREG_GSBASE)(base); \ - movl %edx, _CONST(REG_OFF(KREG_GSBASE)+4)(base); \ - \ - movl $MSR_AMD_KGSBASE, %ecx; \ - rdmsr; \ - movl %eax, REG_OFF(KREG_KGSBASE)(base); \ - movl %edx, _CONST(REG_OFF(KREG_KGSBASE)+4)(base); \ - \ - clrq %rax; \ - movw %ds, %ax; \ - movq %rax, REG_OFF(KREG_DS)(base); \ - movw %es, %ax; \ - movq %rax, REG_OFF(KREG_ES)(base); \ - movw %fs, %ax; \ - movq %rax, REG_OFF(KREG_FS)(base); \ - movw %gs, %ax; \ - movq %rax, REG_OFF(KREG_GS)(base) - -#define KAIF_RESTORE_REGS(base) \ - movq base, %rdi; \ - movq REG_OFF(KREG_GS)(%rdi), %rax; \ - movw %ax, %gs; \ - movq REG_OFF(KREG_FS)(%rdi), %rax; \ - movw %ax, %fs; \ - movq REG_OFF(KREG_ES)(%rdi), %rax; \ - movw %ax, %es; \ - movq REG_OFF(KREG_DS)(%rdi), %rax; \ - movw %ax, %ds; \ - \ - movl $MSR_AMD_KGSBASE, %ecx; \ - movl REG_OFF(KREG_KGSBASE)(%rdi), %eax; \ - movl _CONST(REG_OFF(KREG_KGSBASE)+4)(%rdi), %edx; \ - wrmsr; \ - \ - movl $MSR_AMD_GSBASE, %ecx; \ - movl REG_OFF(KREG_GSBASE)(%rdi), %eax; \ - movl _CONST(REG_OFF(KREG_GSBASE)+4)(%rdi), %edx; \ - wrmsr; \ - \ - movl $MSR_AMD_FSBASE, %ecx; \ - movl REG_OFF(KREG_FSBASE)(%rdi), %eax; \ - movl _CONST(REG_OFF(KREG_FSBASE)+4)(%rdi), %edx; \ - wrmsr; \ - \ - movq REG_OFF(KREG_R15)(%rdi), %r15; \ - movq REG_OFF(KREG_R14)(%rdi), %r14; \ - movq REG_OFF(KREG_R13)(%rdi), %r13; \ - movq REG_OFF(KREG_R12)(%rdi), %r12; \ - movq REG_OFF(KREG_R11)(%rdi), %r11; \ - movq REG_OFF(KREG_R10)(%rdi), %r10; \ - movq REG_OFF(KREG_RBP)(%rdi), %rbp; \ - movq REG_OFF(KREG_RBX)(%rdi), %rbx; \ - movq REG_OFF(KREG_RAX)(%rdi), %rax; \ - movq REG_OFF(KREG_R9)(%rdi), %r9; \ - movq REG_OFF(KREG_R8)(%rdi), %r8; \ - movq REG_OFF(KREG_RCX)(%rdi), %rcx; \ - movq REG_OFF(KREG_RDX)(%rdi), %rdx; \ - movq REG_OFF(KREG_RSI)(%rdi), %rsi; \ - movq REG_OFF(KREG_RDI)(%rdi), %rdi - -/* - * Each cpusave buffer has an area set aside for a ring buffer of breadcrumbs. - * The following macros manage the buffer. - */ - -/* Advance the ring buffer */ -#define ADVANCE_CRUMB_POINTER(cpusave, tmp1, tmp2) \ - movq KRS_CURCRUMBIDX(cpusave), tmp1; \ - cmpq $[KAIF_NCRUMBS - 1], tmp1; \ - jge 1f; \ - /* Advance the pointer and index */ \ - addq $1, tmp1; \ - movq tmp1, KRS_CURCRUMBIDX(cpusave); \ - movq KRS_CURCRUMB(cpusave), tmp1; \ - addq $KRM_SIZE, tmp1; \ - jmp 2f; \ -1: /* Reset the pointer and index */ \ - movq $0, KRS_CURCRUMBIDX(cpusave); \ - leaq KRS_CRUMBS(cpusave), tmp1; \ -2: movq tmp1, KRS_CURCRUMB(cpusave); \ - /* Clear the new crumb */ \ - movq $KAIF_NCRUMBS, tmp2; \ -3: movq $0, -4(tmp1, tmp2, 4); \ - decq tmp2; \ - jnz 3b - -/* Set a value in the current breadcrumb buffer */ -#define ADD_CRUMB(cpusave, offset, value, tmp) \ - movq KRS_CURCRUMB(cpusave), tmp; \ - movq value, offset(tmp) - -/* Patch point for MSR clearing. */ -#define KAIF_MSR_PATCH \ - nop; nop; nop; nop; \ - nop; nop; nop; nop; \ - nop; nop; nop; nop; \ - nop; nop; nop; nop; \ - nop - -#endif /* _ASM */ - -#define KAIF_MSR_PATCHSZ 17 /* bytes in KAIF_MSR_PATCH, above */ -#define KAIF_MSR_PATCHOFF 8 /* bytes of code before patch point */ - -#ifdef __cplusplus -} -#endif - -#endif /* _KAIF_ASMUTIL_H */ diff --git a/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.s b/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.s deleted file mode 100644 index 4861bcc476..0000000000 --- a/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.s +++ /dev/null @@ -1,86 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/asm_linkage.h> -#include <sys/trap.h> - -#include <kmdb/kaif_asmutil.h> - -#if defined(__lint) -void -kaif_enter(void) -{ -} -#else - - ENTRY(kaif_enter) - pushq %rbp - movq %rsp, %rbp - - pushfq - cli - - int $T_DBGENTR - - popfq - - leave - ret - SET_SIZE(kaif_enter) - -#endif - -#if defined(__lint) -/*ARGSUSED*/ -void -get_idt(desctbr_t *idt) -{ -} -#else - - ENTRY(get_idt) - sidt (%rdi) - ret - SET_SIZE(get_idt) - -#endif - -#if defined(__lint) -/*ARGSUSED*/ -void -set_idt(desctbr_t *idt) -{ -} -#else - - ENTRY(set_idt) - lidt (%rdi) - ret - SET_SIZE(set_idt) - -#endif diff --git a/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_resume.s b/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_resume.s deleted file mode 100644 index 8574be2336..0000000000 --- a/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_resume.s +++ /dev/null @@ -1,239 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/asm_linkage.h> -#include <sys/uadmin.h> -#include <sys/reg.h> -#include <sys/segments.h> -#include <sys/x86_archext.h> -#include <sys/controlregs.h> - -#include <kmdb/kaif.h> -#include <kmdb/kaif_asmutil.h> -#include <kmdb/kaif_off.h> -#include <kmdb/kmdb_dpi_isadep.h> -#include <mdb/mdb_kreg.h> - -/* - * Given the address of the current CPU's cpusave area in %rax, the following - * macro restores the debugging state to said CPU. Restored state includes - * the debug registers from the global %dr variables, and debugging MSRs from - * the CPU save area. This code would be in a separate routine, but for the - * fact that some of the MSRs are jump-sensitive. As such, we need to minimize - * the number of jumps taken subsequent to the update of said MSRs. We can - * remove one jump (the ret) by using a macro instead of a function for the - * debugging state restoration code. - * - * Takes the cpusave area in %rdi as a parameter, clobbers %rax-%rdx - */ -#define KAIF_RESTORE_DEBUGGING_STATE \ - leaq kaif_drreg, %rbx; \ - movq DR_CTL(%rbx), %rcx; \ - movq %rcx, %dr7; \ - movq $KREG_DRSTAT_RESERVED, %rcx; \ - movq %rcx, %dr6; \ - movq DRADDR_OFF(0)(%rbx), %rcx; \ - movq %rcx, %dr0; \ - movq DRADDR_OFF(1)(%rbx), %rcx; \ - movq %rcx, %dr1; \ - movq DRADDR_OFF(2)(%rbx), %rcx; \ - movq %rcx, %dr2; \ - movq DRADDR_OFF(3)(%rbx), %rcx; \ - movq %rcx, %dr3; \ - \ - /* \ - * Write any requested MSRs. \ - */ \ - movq KRS_MSR(%rdi), %rbx; \ - cmpq $0, %rbx; \ - je 3f; \ -1: \ - movl MSR_NUM(%rbx), %ecx; \ - cmpl $0, %ecx; \ - je 3f; \ - \ - movl MSR_TYPE(%rbx), %edx; \ - cmpl $KMDB_MSR_WRITE, %edx; \ - jne 2f; \ - \ - movq MSR_VALP(%rbx), %rdx; \ - movl 0(%rdx), %eax; \ - movl 4(%rdx), %edx; \ - wrmsr; \ -2: \ - addq $MSR_SIZE, %rbx; \ - jmp 1b; \ -3: \ - /* \ - * We must not branch after re-enabling LBR. If \ - * kaif_wsr_wrexit_msr is set, it contains the number \ - * of the MSR that controls LBR. kaif_wsr_wrexit_valp \ - * contains the value that is to be written to enable \ - * LBR. \ - */ \ - movl kaif_msr_wrexit_msr, %ecx; \ - cmpl $0, %ecx; \ - je 1f; \ - \ - movq kaif_msr_wrexit_valp, %rdx; \ - movl 0(%rdx), %eax; \ - movl 4(%rdx), %edx; \ - \ - wrmsr; \ -1: - -#if defined(__lint) -/*ARGSUSED*/ -void -kaif_cpu_debug_init(kaif_cpusave_t *save) -{ -} -#else /* __lint */ - - ENTRY_NP(kaif_cpu_debug_init) - pushq %rbp - movq %rsp, %rbp - - pushq %rbx /* macro will clobber %rbx */ - KAIF_RESTORE_DEBUGGING_STATE - popq %rbx - - leave - ret - - SET_SIZE(kaif_cpu_debug_init) -#endif /* !__lint */ - - /* - * Resume the world. The code that calls kaif_resume has already - * decided whether or not to restore the IDT. - */ -#if defined(__lint) -void -kaif_resume(void) -{ -} -#else /* __lint */ - - ENTRY_NP(kaif_resume) - - /* cpusave in %rdi, debugger command in %rsi */ - - cmpq $KAIF_CPU_CMD_PASS_TO_KERNEL, %rsi - je kaif_pass_to_kernel - - cmpq $KAIF_CPU_CMD_REBOOT, %rsi - je kaif_reboot - - /* - * Send this CPU back into the world - */ - - movq KRS_CR0(%rdi), %rdx - movq %rdx, %cr0 - - KAIF_RESTORE_DEBUGGING_STATE - - movq KRS_GREGS(%rdi), %rsp - KAIF_RESTORE_REGS(%rsp) - addq $REG_OFF(KREG_RIP), %rsp /* Discard state, trapno, err */ - - iretq - - SET_SIZE(kaif_resume) - -#endif /* __lint */ - -#if !defined(__lint) - - ENTRY_NP(kaif_pass_to_kernel) - - /* cpusave is still in %rdi */ - - movq KRS_CR0(%rdi), %rdx - movq %rdx, %cr0 - - /* - * When we replaced the kernel's handlers in the IDT, we made note of - * the handlers being replaced, thus allowing us to pass traps directly - * to said handlers here. We won't have any registers available for use - * after we start popping, and we know we're single-threaded here, so - * we have to use a global to store the handler address. - */ - movq KRS_GREGS(%rdi), %rsp - movq REG_OFF(KREG_TRAPNO)(%rsp), %rdi - call kaif_kernel_trap2hdlr - movq %rax, kaif_kernel_handler - - /* - * The trap handler will expect the stack to be in trap order, with - * %rip being the last entry. Our stack is currently in mdb_kreg.h - * order, so we'll need to pop (and restore) our way back down. - */ - KAIF_RESTORE_REGS(%rsp) - addq $REG_OFF(KREG_RIP), %rsp /* Discard state, trapno, err */ - - jmp *%cs:kaif_kernel_handler - /*NOTREACHED*/ - - SET_SIZE(kaif_pass_to_kernel) - - /* - * Reboot the system. This routine is to be called only by the master - * CPU. - */ - ENTRY_NP(kaif_reboot) - - movq kmdb_kdi_shutdownp, %rax - movq (%rax), %rax - cmpq $0, %rax - je 1f - - /* psm_shutdown is set in the kernel, so we'll try it */ - pushq $AD_BOOT - pushq $A_SHUTDOWN - call *%rax - addq $16, %rsp - -1: /* - * psm_shutdown didn't work or, it wasn't set. Let's try the time- - * honored method for getting things done on Intel machines -- - * sacrifice random bits to random BIOS gods. - */ - ALTENTRY(reset) - movw $0x64, %dx - movb $0xfe, %al - outb (%dx) - - hlt - /*NOTREACHED*/ - - SET_SIZE(reset) - SET_SIZE(kaif_reboot) - -#endif /* !__lint */ diff --git a/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_startup.s b/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_startup.s deleted file mode 100644 index 658f564e02..0000000000 --- a/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_startup.s +++ /dev/null @@ -1,323 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Debugger entry for both master and slave CPUs - */ - -#if defined(__lint) -#include <sys/types.h> -#endif - -#include <sys/segments.h> -#include <sys/asm_linkage.h> -#include <sys/controlregs.h> -#include <sys/x86_archext.h> - -#include <mdb/mdb_kreg.h> -#include <kmdb/kaif.h> -#include <kmdb/kaif_asmutil.h> -#include <kmdb/kaif_regs.h> -#include <kmdb/kaif_off.h> -#include <kmdb/kmdb_dpi_isadep.h> - -#if !defined(__lint) - - /* XXX implement me */ - ENTRY_NP(kaif_nmiint) - clrq %rcx - movq (%rcx), %rcx - SET_SIZE(kaif_nmiint) - - ENTRY_NP(kaif_save_common_state) - - /* - * The state of the world: - * - * The stack has a complete set of saved registers and segment - * selectors, arranged in the order given in mdb_kreg.h. It also has a - * pointer to our cpusave area. - * - * We need to save, into the cpusave area, a pointer to these saved - * registers. After that, we save a few more registers, ready the - * machine for debugger entry, and enter the debugger. - */ - - popq %rax /* the cpusave area */ - movq %rsp, KRS_GREGS(%rax) /* save ptr to current saved regs */ - - SAVE_IDTGDT - - /* Save off %cr0, and clear write protect */ - movq %cr0, %rcx - movq %rcx, KRS_CR0(%rax) - andq $_BITNOT(CR0_WP), %rcx - movq %rcx, %cr0 - - /* Save the debug registers and disable any active watchpoints */ - movq %dr7, %rcx - movq %rcx, KRS_DRCTL(%rax) - andq $_BITNOT(KREG_DRCTL_WPALLEN_MASK), %rcx - movq %rcx, %dr7 - - movq %dr6, %rcx - movq %rcx, KRS_DRSTAT(%rax) - - movq %dr0, %rcx - movq %rcx, KRS_DROFF(0)(%rax) - movq %dr1, %rcx - movq %rcx, KRS_DROFF(1)(%rax) - movq %dr2, %rcx - movq %rcx, KRS_DROFF(2)(%rax) - movq %dr3, %rcx - movq %rcx, KRS_DROFF(3)(%rax) - - /* - * Save any requested MSRs. - */ - movq KRS_MSR(%rax), %rcx - cmpq $0, %rcx - je no_msr - - pushq %rax /* rdmsr clobbers %eax */ - movq %rcx, %rbx - -1: - movl MSR_NUM(%rbx), %ecx - cmpl $0, %ecx - je msr_done - - movl MSR_TYPE(%rbx), %edx - cmpl $KMDB_MSR_READ, %edx - jne msr_next - - rdmsr /* addr in %ecx, value into %edx:%eax */ - movl %eax, MSR_VAL(%rbx) - movl %edx, _CONST(MSR_VAL + 4)(%rbx) - -msr_next: - addq $MSR_SIZE, %rbx - jmp 1b - -msr_done: - popq %rax - -no_msr: - clrq %rbp /* stack traces should end here */ - - pushq %rax - movq %rax, %rdi /* cpusave */ - - call kaif_debugger_entry - - /* Pass cpusave and debugger return code for "call" to resume */ - popq %rdi - movq %rax, %rsi - - jmp kaif_resume - - SET_SIZE(kaif_save_common_state) - -#endif /* !__lint */ - -/* - * The main entry point for master CPUs. It also serves as the trap handler - * for all traps and interrupts taken during single-step. - */ -#if defined(__lint) -void -kaif_cmnint(void) -{ -} -#else /* __lint */ - - ENTRY_NP(kaif_cmnint) - ALTENTRY(kaif_master_entry) - - cli - - /* Save current register state */ - subq $REG_OFF(KREG_TRAPNO), %rsp - KAIF_SAVE_REGS(%rsp) - - /* - * Switch to the kernel's GSBASE. Neither GSBASE nor the ill-named - * KGSBASE can be trusted, as the kernel may or may not have already - * done a swapgs. All is not lost, as the kernel can divine the correct - * value for us. - */ - movq mdb+MDB_KDI, %rax - movq MKDI_GDT2GSBASE(%rax), %rax - subq $10, %rsp - sgdt (%rsp) - movq 2(%rsp), %rdi /* gdt base now in %rdi */ - addq $10, %rsp - call *%rax /* returns kernel's GSBASE in %rax */ - - movq %rax, %rdx - shrq $32, %rdx - movl $MSR_AMD_GSBASE, %ecx - wrmsr - - GET_CPUSAVE_ADDR /* %rax = cpusave, %rbx = CPU ID */ - - ADVANCE_CRUMB_POINTER(%rax, %rcx, %rdx) - - ADD_CRUMB(%rax, KRM_CPU_STATE, $KAIF_CPU_STATE_MASTER, %rdx) - - movq REG_OFF(KREG_RIP)(%rsp), %rcx - ADD_CRUMB(%rax, KRM_PC, %rcx, %rdx) - ADD_CRUMB(%rax, KRM_SP, %rsp, %rdx) - movq REG_OFF(KREG_TRAPNO)(%rsp), %rcx - ADD_CRUMB(%rax, KRM_TRAPNO, %rcx, %rdx) - - movq %rsp, %rbp - pushq %rax - - /* - * Were we in the debugger when we took the trap (i.e. was %esp in one - * of the debugger's memory ranges)? - */ - leaq kaif_memranges, %rcx - movl kaif_nmemranges, %edx -1: cmpq MR_BASE(%rcx), %rsp - jl 2f /* below this range -- try the next one */ - cmpq MR_LIM(%rcx), %rsp - jg 2f /* above this range -- try the next one */ - jmp 3f /* matched within this range */ - -2: decl %edx - jz kaif_save_common_state /* %rsp not within debugger memory */ - addq $MR_SIZE, %rcx - jmp 1b - -3: /* - * The master is still set. That should only happen if we hit a trap - * while running in the debugger. Note that it may be an intentional - * fault. kmdb_dpi_handle_fault will sort it all out. - */ - - movq REG_OFF(KREG_TRAPNO)(%rbp), %rdi - movq REG_OFF(KREG_RIP)(%rbp), %rsi - movq REG_OFF(KREG_RSP)(%rbp), %rdx - movq %rbx, %rcx /* cpuid */ - - call kmdb_dpi_handle_fault - - /* - * If we're here, we ran into a debugger problem, and the user - * elected to solve it by having the debugger debug itself. The - * state we're about to save is that of the debugger when it took - * the fault. - */ - - jmp kaif_save_common_state - - SET_SIZE(kaif_master_entry) - SET_SIZE(kaif_cmnint) - -#endif /* __lint */ - -/* - * The cross-call handler for slave CPUs. - * - * The debugger is single-threaded, so only one CPU, called the master, may be - * running it at any given time. The other CPUs, known as slaves, spin in a - * busy loop until there's something for them to do. This is the entry point - * for the slaves - they'll be sent here in response to a cross-call sent by the - * master. - */ - -#if defined(__lint) -char kaif_slave_entry_patch; - -void -kaif_slave_entry(void) -{ -} -#else /* __lint */ - .globl kaif_slave_entry_patch; - - ENTRY_NP(kaif_slave_entry) - - /* kaif_msr_add_clrentry knows where this is */ -kaif_slave_entry_patch: - KAIF_MSR_PATCH; - - /* - * Cross calls are implemented as function calls, so our stack currently - * looks like one you'd get from a zero-argument function call. That - * is, there's the return %rip at %rsp, and that's about it. We need - * to make it look like an interrupt stack. When we first save, we'll - * reverse the saved %ss and %rip, which we'll fix back up when we've - * freed up some general-purpose registers. We'll also need to fix up - * the saved %rsp. - */ - - pushq %rsp /* pushed value off by 8 */ - pushfq - cli - clrq %rax - movw %cs, %ax - pushq %rax - movw %ss, %ax - pushq %rax /* rip should be here */ - pushq $-1 /* phony trap error code */ - pushq $-1 /* phony trap number */ - - subq $REG_OFF(KREG_TRAPNO), %rsp - KAIF_SAVE_REGS(%rsp) - - movq REG_OFF(KREG_SS)(%rsp), %rax - xchgq REG_OFF(KREG_RIP)(%rsp), %rax - movq %rax, REG_OFF(KREG_SS)(%rsp) - - movq REG_OFF(KREG_RSP)(%rsp), %rax - addq $8, %rax - movq %rax, REG_OFF(KREG_RSP)(%rsp) - - /* - * We've saved all of the general-purpose registers, and have a stack - * that is irettable (after we strip down to the error code) - */ - - GET_CPUSAVE_ADDR /* %rax = cpusave, %rbx = CPU ID */ - - ADVANCE_CRUMB_POINTER(%rax, %rcx, %rdx) - - ADD_CRUMB(%rax, KRM_CPU_STATE, $KAIF_CPU_STATE_SLAVE, %rdx) - - movq REG_OFF(KREG_RIP)(%rsp), %rcx - ADD_CRUMB(%rax, KRM_PC, %rcx, %rdx) - - pushq %rax - jmp kaif_save_common_state - - SET_SIZE(kaif_slave_entry) - -#endif /* __lint */ diff --git a/usr/src/cmd/mdb/intel/ia32/Makefile.kmdb b/usr/src/cmd/mdb/intel/ia32/Makefile.kmdb index d9b792bc58..53b19b535d 100644 --- a/usr/src/cmd/mdb/intel/ia32/Makefile.kmdb +++ b/usr/src/cmd/mdb/intel/ia32/Makefile.kmdb @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,17 +19,14 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" # KMDBML += \ - kaif_asmutil.s \ kaif_invoke.s \ - kaif_resume.s \ - kaif_startup.s \ kmdb_start.s KMDBSRCS += \ @@ -38,10 +34,4 @@ KMDBSRCS += \ kmdb_makecontext.c \ kvm_cpu_p6.c -REGOFFUSERS = \ - kaif_resume.o \ - kaif_startup.o - SACPPFLAGS = -D__$(MACH) - -$(REGOFFUSERS) $(REGOFFUSERS:%.o=%.ln): kaif_off.h diff --git a/usr/src/cmd/mdb/intel/ia32/genunix/Makefile b/usr/src/cmd/mdb/intel/ia32/genunix/Makefile index 63609d42b2..7ca684b524 100644 --- a/usr/src/cmd/mdb/intel/ia32/genunix/Makefile +++ b/usr/src/cmd/mdb/intel/ia32/genunix/Makefile @@ -29,43 +29,10 @@ MODULE = genunix.so MDBTGT = kvm +include ../../../common/modules/genunix/Makefile.files + COMMONSRCS = \ - avl.c \ - bio.c \ - contract.c \ - cpupart.c \ - ctxop.c \ - cyclic.c \ - devinfo.c \ - findstack.c \ - fm.c \ - genunix.c \ - group.c \ - kgrep.c \ - kmem.c \ - ldi.c \ - leaky.c \ - leaky_subr.c \ - lgrp.c \ - list.c \ - log.c \ - mdi.c \ - memory.c \ - mmd.c \ - modhash.c \ - ndievents.c \ - net.c \ - nvpair.c \ - pg.c \ - rctl.c \ - sobj.c \ - streams.c \ - sysevent.c \ - thread.c \ - tsd.c \ - tsol.c \ - vfs.c \ - zone.c + $(GENUNIX_SRCS) KMODSRCS = \ $(COMMONSRCS) diff --git a/usr/src/cmd/mdb/intel/ia32/kmdb/Makefile b/usr/src/cmd/mdb/intel/ia32/kmdb/Makefile index ccd4b446c4..594594ecb5 100644 --- a/usr/src/cmd/mdb/intel/ia32/kmdb/Makefile +++ b/usr/src/cmd/mdb/intel/ia32/kmdb/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -79,9 +79,6 @@ lintprom: $(PROMOBJS:%.o=%.ln) lintkctl: $(KCTLOBJS:%.o=%.ln) $(LINT) $(ALLLINTFLAGS) $(KCTLOBJS:%.o=%.ln) -kaif_off.h: ../../kmdb/kaif_off.in - $(OFFSETS_CREATE) <../../kmdb/kaif_off.in >$@ - kmdb_context_off.h: ../../kmdb/kmdb_context_off.in $(OFFSETS_CREATE) <../../kmdb/kmdb_context_off.in >$@ diff --git a/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.h b/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.h deleted file mode 100644 index 0ed570f1d2..0000000000 --- a/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _KAIF_ASMUTIL_H -#define _KAIF_ASMUTIL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/segments.h> - -#include <kmdb/kaif_regs.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _ASM - -/* - * Multiple CPUs won't be present until a) we're on the kernel's %gs and - * b) cross-call initialization has completed. Until that time, we just assume - * we're CPU zero. - * - * This macro returns the CPUID in %eax, and doesn't clobber any other - * registers. - */ -#define GET_CPUID \ - call kmdb_kdi_xc_initialized; \ - cmpl $0, %eax; \ - je 1f; \ - movw %gs, %ax; \ - cmpw $KGS_SEL, %ax; \ - jne 1f; \ - verr %ax; \ - jnz 1f; \ - ; \ - movzbl %gs:CPU_ID, %eax; \ - jmp 2f; \ -1: \ - clr %eax; \ -2: - -/* clobbers %edx, %ecx, returns addr in %eax, cpu id in %ebx */ -#define GET_CPUSAVE_ADDR \ - GET_CPUID; \ - movl %eax, %ebx; \ - movl $KRS_SIZE, %ecx; \ - mull %ecx; \ - movl $kaif_cpusave, %edx; \ - /*CSTYLED*/ \ - addl (%edx), %eax - -/* - * Save copies of the IDT and GDT descriptors. Note that we only save the IDT - * and GDT if the IDT isn't ours, as we may be legitimately re-entering the - * debugger through the trap handler. We don't want to clobber the saved IDT - * in the process, as we'd end up resuming the world on our IDT. - * - * assumes cpusave in %eax, clobbers %ecx - */ -#define SAVE_IDTGDT \ - sidt KRS_TMPDESC(%eax); \ - movl KRS_TMPDESC+2(%eax), %ecx; \ - cmpl $kaif_idt, %ecx; \ - je 1f; \ - sidt KRS_IDTR(%eax); \ - sgdt KRS_GDTR(%eax); \ -1: - -/* - * Each cpusave buffer has an area set aside for a ring buffer of breadcrumbs. - * The following macros manage the buffer. - */ - -/* Advance the ring buffer */ -#define ADVANCE_CRUMB_POINTER(cpusave, tmp1, tmp2) \ - movl KRS_CURCRUMBIDX(cpusave), tmp1; \ - cmpl $[KAIF_NCRUMBS - 1], tmp1; \ - jge 1f; \ - /* Advance the pointer and index */ \ - addl $1, tmp1; \ - movl tmp1, KRS_CURCRUMBIDX(cpusave); \ - movl KRS_CURCRUMB(cpusave), tmp1; \ - addl $KRM_SIZE, tmp1; \ - jmp 2f; \ -1: /* Reset the pointer and index */ \ - movw $0, KRS_CURCRUMBIDX(cpusave); \ - leal KRS_CRUMBS(cpusave), tmp1; \ -2: movl tmp1, KRS_CURCRUMB(cpusave); \ - /* Clear the new crumb */ \ - movl $KAIF_NCRUMBS, tmp2; \ -3: movl $0, -4(tmp1, tmp2, 4); \ - decl tmp2; \ - jnz 3b - -/* Set a value in the current breadcrumb buffer */ -#define ADD_CRUMB(cpusave, offset, value, tmp) \ - movl KRS_CURCRUMB(cpusave), tmp; \ - movl value, offset(tmp) - -/* Patch point for MSR clearing. */ -#define KAIF_MSR_PATCH \ - nop; nop; nop; nop; \ - nop; nop; nop; nop; \ - nop; nop; nop; nop; \ - nop - -#endif /* _ASM */ - -#define KAIF_MSR_PATCHSZ 13 /* bytes in KAIF_MSR_PATCH, above */ -#define KAIF_MSR_PATCHOFF 8 /* bytes of code before patch point */ - -#ifdef __cplusplus -} -#endif - -#endif /* _KAIF_ASMUTIL_H */ diff --git a/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.s b/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.s deleted file mode 100644 index f695047c52..0000000000 --- a/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.s +++ /dev/null @@ -1,92 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/asm_linkage.h> -#include <sys/trap.h> - -#include <kmdb/kaif_asmutil.h> - -#if defined(__lint) -void -kaif_enter(void) -{ -} -#else - - ENTRY(kaif_enter) - pushl %ebp - movl %esp, %ebp - - pushfl - cli - int $T_DBGENTR - popfl - - leave - ret - SET_SIZE(kaif_enter) - -#endif - -#if defined(__lint) -/*ARGSUSED*/ -void -get_idt(desctbr_t *idt) -{ -} -#else - - ENTRY(get_idt) - pushl %ebp - movl %esp, %ebp - movl 8(%ebp), %edx - sidt (%edx) - leave - ret - SET_SIZE(get_idt) - -#endif - -#if defined(__lint) -/*ARGSUSED*/ -void -set_idt(desctbr_t *idt) -{ -} -#else - - ENTRY(set_idt) - pushl %ebp - movl %esp, %ebp - movl 8(%ebp), %edx - lidt (%edx) - leave - ret - SET_SIZE(set_idt) - -#endif diff --git a/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_resume.s b/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_resume.s deleted file mode 100644 index c9693b8212..0000000000 --- a/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_resume.s +++ /dev/null @@ -1,253 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/asm_linkage.h> -#include <sys/uadmin.h> -#include <sys/reg.h> -#include <sys/segments.h> -#include <sys/x86_archext.h> - -#include <kmdb/kaif.h> -#include <kmdb/kaif_asmutil.h> -#include <kmdb/kaif_off.h> -#include <kmdb/kmdb_dpi_isadep.h> -#include <mdb/mdb_kreg.h> - -/* - * Given the address of the current CPU's cpusave area in %eax, the following - * macro restores the debugging state to said CPU. Restored state includes - * the debug registers from the global %dr variables, and debugging MSRs from - * the CPU save area. This code would be in a separate routine, but for the - * fact that some of the MSRs are jump-sensitive. As such, we need to minimize - * the number of jumps taken subsequent to the update of said MSRs. We can - * remove one jump (the ret) by using a macro instead of a function for the - * debugging state restoration code. - * - * Takes the cpusave area in %eax as a parameter, clobbers %eax-%edx - */ -#define KAIF_RESTORE_DEBUGGING_STATE \ - leal kaif_drreg, %ebx; \ - movl DR_CTL(%ebx), %ecx; \ - movl %ecx, %dr7; \ - movl $KREG_DRSTAT_RESERVED, %ecx; \ - movl %ecx, %dr6; \ - movl DRADDR_OFF(0)(%ebx), %ecx; \ - movl %ecx, %dr0; \ - movl DRADDR_OFF(1)(%ebx), %ecx; \ - movl %ecx, %dr1; \ - movl DRADDR_OFF(2)(%ebx), %ecx; \ - movl %ecx, %dr2; \ - movl DRADDR_OFF(3)(%ebx), %ecx; \ - movl %ecx, %dr3; \ - \ - /* \ - * Write any requested MSRs. \ - */ \ - movl KRS_MSR(%eax), %ebx; \ - cmpl $0, %ebx; \ - je 3f; \ -1: \ - movl MSR_NUM(%ebx), %ecx; \ - cmpl $0, %ecx; \ - je 3f; \ - \ - movl MSR_TYPE(%ebx), %edx; \ - cmpl $KMDB_MSR_WRITE, %edx; \ - jne 2f; \ - \ - movl MSR_VALP(%ebx), %edx; \ - movl 0(%edx), %eax; \ - movl 4(%edx), %edx; \ - wrmsr; \ -2: \ - addl $MSR_SIZE, %ebx; \ - jmp 1b; \ -3: \ - /* \ - * We must not branch after re-enabling LBR. If \ - * kaif_wsr_wrexit_msr is set, it contains the number \ - * of the MSR that controls LBR. kaif_wsr_wrexit_valp \ - * contains the value that is to be written to enable \ - * LBR. \ - */ \ - movl kaif_msr_wrexit_msr, %ecx; \ - cmpl $0, %ecx; \ - je 1f; \ - \ - movl kaif_msr_wrexit_valp, %edx; \ - movl 0(%edx), %eax; \ - movl 4(%edx), %edx; \ - \ - wrmsr; \ -1: - -#if defined(__lint) -/*ARGSUSED*/ -void -kaif_cpu_debug_init(kaif_cpusave_t *save) -{ -} -#else /* __lint */ - - ENTRY_NP(kaif_cpu_debug_init) - pushl %ebp - movl %esp, %ebp - - movl 8(%ebp), %eax - - pushl %ebx - KAIF_RESTORE_DEBUGGING_STATE - popl %ebx - - leave - ret - - SET_SIZE(kaif_cpu_debug_init) -#endif /* !__lint */ - - /* - * Resume the world. The code that calls kaif_resume has already - * decided whether or not to restore the IDT. - */ -#if defined(__lint) -void -kaif_resume(void) -{ -} -#else /* __lint */ - - ENTRY_NP(kaif_resume) - popl %ebx /* command */ - popl %eax /* cpusave */ - - cmpl $KAIF_CPU_CMD_PASS_TO_KERNEL, %ebx - je kaif_pass_to_kernel - - cmpl $KAIF_CPU_CMD_REBOOT, %ebx - je kaif_reboot - - /* - * Send this CPU back into the world - */ - - movl KRS_CR0(%eax), %edx - movl %edx, %cr0 - - KAIF_RESTORE_DEBUGGING_STATE - - addl $8, %esp /* Discard savfp and savpc */ - - popl %ss - popl %gs - popl %fs - popl %es - popl %ds - popal - - addl $8, %esp /* Discard TRAPNO and ERROR */ - - iret - - SET_SIZE(kaif_resume) -#endif /* __lint */ - -#if !defined(__lint) - - ENTRY_NP(kaif_pass_to_kernel) - - /* cpusave is still in %eax */ - - movl KRS_CR0(%eax), %edx - movl %edx, %cr0 - - /* - * When we replaced the kernel's handlers in the IDT, we made note of - * the handlers being replaced, thus allowing us to pass traps directly - * to said handlers here. We won't have any registers available for use - * after we start popping, and we know we're single-threaded here, so - * we have to use a global to store the handler address. - */ - pushl REG_OFF(KREG_TRAPNO)(%esp) - call kaif_kernel_trap2hdlr - addl $4, %esp - movl %eax, kaif_kernel_handler - - /* - * The trap handler will expect the stack to be in trap order, with - * %eip being the last entry. Our stack is currently in mdb_kreg.h - * order, so we'll need to pop (and restore) our way back down. - */ - addl $8, %esp /* Discard savfp and savpc */ - popl %ss - popl %gs - popl %fs - popl %es - popl %ds - popal - addl $8, %esp /* Discard trapno and err */ - - ljmp $KCS_SEL, $1f -1: jmp *%cs:kaif_kernel_handler - /*NOTREACHED*/ - - SET_SIZE(kaif_pass_to_kernel) - - /* - * Reboot the system. This routine is to be called only by the master - * CPU. - */ - ENTRY_NP(kaif_reboot) - - movl kmdb_kdi_shutdownp, %eax - movl (%eax), %eax - cmpl $0, %eax - je 1f - - /* psm_shutdown is set in the kernel, so we'll try it */ - pushl $AD_BOOT - pushl $A_SHUTDOWN - call *%eax - addl $8, %esp - -1: /* - * psm_shutdown didn't work or, it wasn't set. Let's try the time- - * honored method for getting things done on Intel machines -- - * sacrifice random bits to random BIOS gods. - */ - ALTENTRY(reset) - movw $0x64, %dx - movb $0xfe, %al - outb (%dx) - - hlt - /*NOTREACHED*/ - - SET_SIZE(reset) - SET_SIZE(kaif_reboot) - -#endif /* !__lint */ diff --git a/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_startup.s b/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_startup.s deleted file mode 100644 index 196c3b26c4..0000000000 --- a/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_startup.s +++ /dev/null @@ -1,369 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Debugger entry for both master and slave CPUs - */ - -#if defined(__lint) -#include <sys/types.h> -#endif - -#include <sys/segments.h> -#include <sys/asm_linkage.h> -#include <sys/controlregs.h> -#include <sys/x86_archext.h> - -#include <mdb/mdb_kreg.h> -#include <kmdb/kaif.h> -#include <kmdb/kaif_asmutil.h> -#include <kmdb/kaif_regs.h> -#include <kmdb/kaif_off.h> -#include <kmdb/kmdb_dpi_isadep.h> - -#if !defined(__lint) - - /* XXX implement me */ - ENTRY_NP(kaif_nmiint) - clr %ecx - movl (%ecx), %ecx - SET_SIZE(kaif_nmiint) - - ENTRY_NP(kaif_save_common_state) - - /* - * The state of the world: - * - * The stack has a complete set of saved registers and segment - * selectors, arranged in `struct regs' order (or vice-versa), up to - * and including EFLAGS. It also has a pointer to our cpusave area. - * - * We need to save a pointer to these saved registers. We also want - * to adjust the saved %esp - it should point just beyond the saved - * registers to the last frame of the thread we interrupted. Finally, - * we want to clear out bits 16-31 of the saved selectors, as the - * selector pushls don't automatically clear them. - */ - popl %eax /* the cpusave area */ - - movl %esp, KRS_GREGS(%eax) /* save ptr to current saved regs */ - - SAVE_IDTGDT - - addl $REG_OFF(KREG_EFLAGS - KREG_EAX), KREG_OFF(KREG_ESP)(%esp) - - andl $0xffff, KREG_OFF(KREG_SS)(%esp) - andl $0xffff, KREG_OFF(KREG_GS)(%esp) - andl $0xffff, KREG_OFF(KREG_FS)(%esp) - andl $0xffff, KREG_OFF(KREG_ES)(%esp) - andl $0xffff, KREG_OFF(KREG_DS)(%esp) - - /* Save off %cr0, and clear write protect */ - movl %cr0, %ecx - movl %ecx, KRS_CR0(%eax) - andl $_BITNOT(CR0_WP), %ecx - movl %ecx, %cr0 - - /* Save the debug registers and disable any active watchpoints */ - movl %dr7, %ecx - movl %ecx, KRS_DRCTL(%eax) - andl $_BITNOT(KREG_DRCTL_WPALLEN_MASK), %ecx - movl %ecx, %dr7 - - movl %dr6, %ecx - movl %ecx, KRS_DRSTAT(%eax) - - movl %dr0, %ecx - movl %ecx, KRS_DROFF(0)(%eax) - movl %dr1, %ecx - movl %ecx, KRS_DROFF(1)(%eax) - movl %dr2, %ecx - movl %ecx, KRS_DROFF(2)(%eax) - movl %dr3, %ecx - movl %ecx, KRS_DROFF(3)(%eax) - - /* - * Save any requested MSRs. - */ - movl KRS_MSR(%eax), %ecx - cmpl $0, %ecx - je no_msr - - pushl %eax /* rdmsr clobbers %eax */ - movl %ecx, %ebx - -1: - movl MSR_NUM(%ebx), %ecx - cmpl $0, %ecx - je msr_done - - movl MSR_TYPE(%ebx), %edx - cmpl $KMDB_MSR_READ, %edx - jne msr_next - - rdmsr /* addr in %ecx, value into %edx:%eax */ - movl %eax, MSR_VAL(%ebx) - movl %edx, _CONST(MSR_VAL + 4)(%ebx) - -msr_next: - addl $MSR_SIZE, %ebx - jmp 1b - -msr_done: - popl %eax - -no_msr: - clr %ebp /* stack traces should end here */ - - pushl %eax - call kaif_debugger_entry - pushl %eax /* leave cpusave on the stack */ - - jmp kaif_resume - - SET_SIZE(kaif_save_common_state) - -#endif /* !__lint */ - -/* - * The main entry point for master CPUs. It also serves as the trap handler - * for all traps and interrupts taken during single-step. - */ -#if defined(__lint) -void -kaif_cmnint(void) -{ -} -#else /* __lint */ - - ENTRY_NP(kaif_cmnint) - ALTENTRY(kaif_master_entry) - - cli - - /* Save all registers and selectors */ - pushal - pushl %ds - pushl %es - pushl %fs - pushl %gs - pushl %ss - - subl $8, %esp - movl %ebp, REG_OFF(KREG_SAVFP)(%esp) - movl REG_OFF(KREG_EIP)(%esp), %eax - movl %eax, REG_OFF(KREG_SAVPC)(%esp) - - /* - * If the kernel has started using its own selectors, we should too. - * Update our saved selectors if they haven't been updated already. - */ - movw %cs, %ax - cmpw $KCS_SEL, %ax - jne 1f /* The kernel hasn't switched yet */ - - movw $KDS_SEL, %ax - movw %ax, %ds - movw kaif_cs, %ax - cmpw $KCS_SEL, %ax - je 1f /* We already switched */ - - /* - * The kernel switched, but we haven't. Update our saved selectors - * to match the kernel's copies for use below. - */ - movl $KCS_SEL, kaif_cs - movl $KDS_SEL, kaif_ds - movl $KFS_SEL, kaif_fs - movl $KGS_SEL, kaif_gs - -1: - /* - * Set the selectors to a known state. If we come in from kmdb's IDT, - * we'll be on boot's %cs. This will cause GET_CPUSAVE_ADDR to return - * CPU 0's cpusave, regardless of which CPU we're on, and chaos will - * ensue. So, if we've got $KCSSEL in kaif_cs, switch to it. The other - * selectors are restored normally. - */ - movw %cs:kaif_cs, %ax - cmpw $KCS_SEL, %ax - jne 1f - ljmp $KCS_SEL, $1f -1: - movw %cs:kaif_ds, %ds - movw kaif_ds, %es - movw kaif_fs, %fs - movw kaif_gs, %gs - movw kaif_ds, %ss - - GET_CPUSAVE_ADDR /* %eax = cpusave, %ebx = CPU ID */ - - ADVANCE_CRUMB_POINTER(%eax, %ecx, %edx) - - ADD_CRUMB(%eax, KRM_CPU_STATE, $KAIF_CPU_STATE_MASTER, %edx) - - movl REG_OFF(KREG_EIP)(%esp), %ecx - ADD_CRUMB(%eax, KRM_PC, %ecx, %edx) - ADD_CRUMB(%eax, KRM_SP, %esp, %edx) - movl REG_OFF(KREG_TRAPNO)(%esp), %ecx - ADD_CRUMB(%eax, KRM_TRAPNO, %ecx, %edx) - - movl %esp, %ebp - pushl %eax - - /* - * Were we in the debugger when we took the trap (i.e. was %esp in one - * of the debugger's memory ranges)? - */ - leal kaif_memranges, %ecx - movl kaif_nmemranges, %edx -1: cmpl MR_BASE(%ecx), %esp - jl 2f /* below this range -- try the next one */ - cmpl MR_LIM(%ecx), %esp - jg 2f /* above this range -- try the next one */ - jmp 3f /* matched within this range */ - -2: decl %edx - jz kaif_save_common_state /* %esp not within debugger memory */ - addl $MR_SIZE, %ecx - jmp 1b - -3: /* - * %esp was within one of the debugger's memory ranges. This should only - * happen when we take a trap while running in the debugger. - * kmdb_dpi_handle_fault will determine whether or not it was an expected - * trap, and will take the appropriate action. - */ - - pushl %ebx /* cpuid */ - - movl REG_OFF(KREG_ESP)(%ebp), %ecx - addl $REG_OFF(KREG_EFLAGS - KREG_EAX), %ecx - pushl %ecx - - pushl REG_OFF(KREG_EIP)(%ebp) - pushl REG_OFF(KREG_TRAPNO)(%ebp) - - call kmdb_dpi_handle_fault - addl $16, %esp - - /* - * If we're here, we ran into a debugger problem, and the user - * elected to solve it by having the debugger debug itself. The - * state we're about to save is that of the debugger when it took - * the fault. - */ - - jmp kaif_save_common_state - - SET_SIZE(kaif_master_entry) - SET_SIZE(kaif_cmnint) - -#endif /* __lint */ - -/* - * The cross-call handler for slave CPUs. - * - * The debugger is single-threaded, so only one CPU, called the master, may be - * running it at any given time. The other CPUs, known as slaves, spin in a - * busy loop until there's something for them to do. This is the entry point - * for the slaves - they'll be sent here in response to a cross-call sent by the - * master. - */ - -#if defined(__lint) -char kaif_slave_entry_patch; - -void -kaif_slave_entry(void) -{ -} -#else /* __lint */ - .globl kaif_slave_entry_patch; - - ENTRY_NP(kaif_slave_entry) - - /* kaif_msr_add_clrentry knows where this is */ -kaif_slave_entry_patch: - KAIF_MSR_PATCH; - - /* - * Cross calls are implemented as function calls, so our stack currently - * looks like one you'd get from a zero-argument function call. There's - * an %eip at %esp, and that's about it. We want to make it look like the - * master CPU's stack. By doing this, we can use the same resume code for - * both master and slave. We need to make our stack look like a `struct - * regs' before we jump into the common save routine. - */ - - pushl %cs - pushfl - cli - pushl $-1 /* A phony trap error code */ - pushl $-1 /* A phony trap number */ - pushal - pushl %ds - pushl %es - pushl %fs - pushl %gs - pushl %ss - - subl $8, %esp - movl %ebp, REG_OFF(KREG_SAVFP)(%esp) - movl REG_OFF(KREG_EIP)(%esp), %eax - movl %eax, REG_OFF(KREG_SAVPC)(%esp) - - /* Swap our saved EFLAGS and %eip. Each is where the other should be */ - movl REG_OFF(KREG_EFLAGS)(%esp), %eax - xchgl REG_OFF(KREG_EIP)(%esp), %eax - movl %eax, REG_OFF(KREG_EFLAGS)(%esp) - - /* Our stack now matches struct regs, and is irettable */ - - /* Load sanitized segment selectors */ - movw kaif_ds, %ds - movw kaif_ds, %es - movw kaif_fs, %fs - movw kaif_gs, %gs - movw kaif_ds, %ss - - GET_CPUSAVE_ADDR /* %eax = cpusave, %ebx = CPU ID */ - - ADVANCE_CRUMB_POINTER(%eax, %ecx, %edx) - - ADD_CRUMB(%eax, KRM_CPU_STATE, $KAIF_CPU_STATE_SLAVE, %edx) - - movl REG_OFF(KREG_EIP)(%esp), %ecx - ADD_CRUMB(%eax, KRM_PC, %ecx, %edx) - - pushl %eax - jmp kaif_save_common_state - - SET_SIZE(kaif_slave_entry) - -#endif /* __lint */ diff --git a/usr/src/cmd/mdb/intel/ia32/kmdb/kvm_cpu_p6.c b/usr/src/cmd/mdb/intel/ia32/kmdb/kvm_cpu_p6.c index 732142e85a..b3c3982ca6 100644 --- a/usr/src/cmd/mdb/intel/ia32/kmdb/kvm_cpu_p6.c +++ b/usr/src/cmd/mdb/intel/ia32/kmdb/kvm_cpu_p6.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -91,13 +90,13 @@ kmt_p6_branches(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) * MSRs that we want to track. These will be read each time the debugger is * entered. */ -static const kmdb_msr_t kmt_p6_msr[] = { - { MSR_DEBUGCTL, KMDB_MSR_CLEARENTRY }, - { MSR_DEBUGCTL, KMDB_MSR_WRITEDELAY, &kmt_cpu_p6.p6_debugctl }, - { MSR_LBR_TO, KMDB_MSR_READ }, - { MSR_LBR_FROM, KMDB_MSR_READ }, - { MSR_LEX_TO, KMDB_MSR_READ }, - { MSR_LEX_FROM, KMDB_MSR_READ }, +static const kdi_msr_t kmt_p6_msr[] = { + { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY }, + { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_p6.p6_debugctl }, + { MSR_LBR_TO, KDI_MSR_READ }, + { MSR_LBR_FROM, KDI_MSR_READ }, + { MSR_LEX_TO, KDI_MSR_READ }, + { MSR_LEX_FROM, KDI_MSR_READ }, { NULL } }; diff --git a/usr/src/cmd/mdb/intel/kmdb/kaif.c b/usr/src/cmd/mdb/intel/kmdb/kaif.c index ceedccc96f..207ddca12a 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kaif.c +++ b/usr/src/cmd/mdb/intel/kmdb/kaif.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -28,58 +28,43 @@ /* * The debugger/"PROM" interface layer * - * (it makes more sense on SPARC) + * It makes more sense on SPARC. In reality, these interfaces deal with three + * things: setting break/watchpoints, stepping, and interfacing with the KDI to + * set up kmdb's IDT handlers. */ #include <kmdb/kmdb_dpi_impl.h> #include <kmdb/kmdb_kdi.h> #include <kmdb/kmdb_umemglue.h> #include <kmdb/kaif.h> -#include <kmdb/kaif_asmutil.h> #include <kmdb/kmdb_io.h> +#include <kmdb/kaif_start.h> #include <mdb/mdb_err.h> #include <mdb/mdb_debug.h> #include <mdb/mdb_isautil.h> #include <mdb/mdb_io_impl.h> -#include <mdb/mdb_kreg.h> +#include <mdb/mdb_kreg_impl.h> #include <mdb/mdb.h> #include <sys/types.h> -#include <sys/segments.h> #include <sys/bitmap.h> #include <sys/termios.h> +#include <sys/kdi_impl.h> -kaif_cpusave_t *kaif_cpusave; +/* + * This is the area containing the saved state when we enter + * via kmdb's IDT entries. + */ +kdi_cpusave_t *kaif_cpusave; int kaif_ncpusave; - -kaif_drreg_t kaif_drreg; +kdi_drreg_t kaif_drreg; uint32_t kaif_waptmap; -#ifndef __amd64 -/* Used to track the current set of valid kernel selectors. */ -uint32_t kaif_cs; -uint32_t kaif_ds; -uint32_t kaif_fs; -uint32_t kaif_gs; -#endif - -uint_t kaif_msr_wrexit_msr; -uint64_t *kaif_msr_wrexit_valp; - -uintptr_t kaif_kernel_handler; -uintptr_t kaif_sys_sysenter; -uintptr_t kaif_brand_sys_sysenter; - int kaif_trap_switch; void (*kaif_modchg_cb)(struct modctl *, int); -#define KAIF_MEMRANGES_MAX 2 - -kaif_memrange_t kaif_memranges[KAIF_MEMRANGES_MAX]; -int kaif_nmemranges; - enum { M_SYSRET = 0x07, /* after M_ESC */ M_ESC = 0x0f, @@ -181,15 +166,25 @@ kaif_get_master_cpuid(void) return (kaif_master_cpuid); } -static const mdb_tgt_gregset_t * -kaif_get_gregs(int cpuid) +static mdb_tgt_gregset_t * +kaif_kdi_to_gregs(int cpuid) { kaif_cpusave_t *save; if ((save = kaif_cpuid2save(cpuid)) == NULL) return (NULL); /* errno is set for us */ - return (save->krs_gregs); + /* + * The saved registers are actually identical to an mdb_tgt_gregset, + * so we can directly cast here. + */ + return ((mdb_tgt_gregset_t *)save->krs_gregs); +} + +static const mdb_tgt_gregset_t * +kaif_get_gregs(int cpuid) +{ + return (kaif_kdi_to_gregs(cpuid)); } typedef struct kaif_reg_synonyms { @@ -212,11 +207,11 @@ kaif_find_regp(const char *regname) #endif { "tt", "trapno" } }; - - kaif_cpusave_t *save; + mdb_tgt_gregset_t *regs; int i; - save = kaif_cpuid2save(DPI_MASTER_CPUID); + if ((regs = kaif_kdi_to_gregs(DPI_MASTER_CPUID)) == NULL) + return (NULL); for (i = 0; i < sizeof (synonyms) / sizeof (synonyms[0]); i++) { if (strcmp(synonyms[i].rs_syn, regname) == 0) @@ -227,7 +222,7 @@ kaif_find_regp(const char *regname) const mdb_tgt_regdesc_t *rd = &mdb_isa_kregs[i]; if (strcmp(rd->rd_name, regname) == 0) - return (&save->krs_gregs->kregs[rd->rd_num]); + return (®s->kregs[rd->rd_num]); } (void) set_errno(ENOENT); @@ -361,7 +356,7 @@ kaif_wapt_reserve(kmdb_wapt_t *wp) { int id; - for (id = 0; id <= KREG_MAXWPIDX; id++) { + for (id = 0; id <= KDI_MAXWPIDX; id++) { if (!BT_TEST(&kaif_waptmap, id)) { /* found one */ BT_SET(&kaif_waptmap, id); @@ -405,6 +400,7 @@ kaif_wapt_arm(kmdb_wapt_t *wp) kaif_drreg.dr_ctl &= ~KREG_DRCTL_WP_MASK(hwid); kaif_drreg.dr_ctl |= KREG_DRCTL_WP_LENRW(hwid, wp->wp_size - 1, rw); kaif_drreg.dr_ctl |= KREG_DRCTL_WPEN(hwid); + kmdb_kdi_update_drreg(&kaif_drreg); } /*ARGSUSED*/ @@ -418,6 +414,7 @@ kaif_wapt_disarm(kmdb_wapt_t *wp) kaif_drreg.dr_addr[hwid] = 0; kaif_drreg.dr_ctl &= ~(KREG_DRCTL_WP_MASK(hwid) | KREG_DRCTL_WPEN_MASK(hwid)); + kmdb_kdi_update_drreg(&kaif_drreg); } /*ARGSUSED*/ @@ -523,7 +520,7 @@ kaif_step(void) case M_POPF: /* * popfl will restore a pushed EFLAGS from the stack, and could - * in so doing cause IF to be turned on, if only for a a brief + * in so doing cause IF to be turned on, if only for a brief * period. To avoid this, we'll secretly replace the stack's * EFLAGS with our decaffeinated brand. We'll then manually * load our EFLAGS copy with the real verion after the step. @@ -646,12 +643,12 @@ kaif_call(uintptr_t funcva, uint_t argc, const uintptr_t argv[]) } static void -dump_crumb(kaif_crumb_t *krmp) +dump_crumb(kdi_crumb_t *krmp) { - kaif_crumb_t krm; + kdi_crumb_t krm; - if (mdb_vread(&krm, sizeof (kaif_crumb_t), (uintptr_t)krmp) != - sizeof (kaif_crumb_t)) { + if (mdb_vread(&krm, sizeof (kdi_crumb_t), (uintptr_t)krmp) != + sizeof (kdi_crumb_t)) { warn("failed to read crumb at %p", krmp); return; } @@ -677,8 +674,8 @@ dump_crumbs(kaif_cpusave_t *save) { int i; - for (i = KAIF_NCRUMBS; i > 0; i--) { - uint_t idx = (save->krs_curcrumbidx + i) % KAIF_NCRUMBS; + for (i = KDI_NCRUMBS; i > 0; i--) { + uint_t idx = (save->krs_curcrumbidx + i) % KDI_NCRUMBS; dump_crumb(&save->krs_crumbs[idx]); } } @@ -690,7 +687,7 @@ kaif_dump_crumbs(uintptr_t addr, int cpuid) if (addr != NULL) { /* dump_crumb will protect us against bogus addresses */ - dump_crumb((kaif_crumb_t *)addr); + dump_crumb((kdi_crumb_t *)addr); } else if (cpuid != -1) { if (cpuid < 0 || cpuid >= kaif_ncpusave) @@ -727,101 +724,32 @@ kaif_modchg_cancel(void) kaif_modchg_cb = NULL; } -void -kaif_mod_loaded(struct modctl *modp) -{ - if (kaif_modchg_cb != NULL) - kaif_modchg_cb(modp, 1); -} - -void -kaif_mod_unloading(struct modctl *modp) -{ - if (kaif_modchg_cb != NULL) - kaif_modchg_cb(modp, 0); -} - -/* - * On some processors, we'll need to clear a certain MSR before proceeding into - * the debugger. Complicating matters, this MSR must be cleared before we take - * any branches. We have patch points in every trap handler, which will cover - * all entry paths for master CPUs. We also have a patch point in the slave - * entry code. - */ static void -kaif_msr_add_clrentry(uint_t msr) +kaif_msr_add(const kdi_msr_t *msrs) { -#ifdef __amd64 - uchar_t code[] = { - 0x51, 0x50, 0x52, /* pushq %rcx, %rax, %rdx */ - 0xb9, 0x00, 0x00, 0x00, 0x00, /* movl $MSRNUM, %ecx */ - 0x31, 0xc0, /* clr %eax */ - 0x31, 0xd2, /* clr %edx */ - 0x0f, 0x30, /* wrmsr */ - 0x5a, 0x58, 0x59 /* popq %rdx, %rax, %rcx */ - }; - uchar_t *patch = &code[4]; -#else - uchar_t code[] = { - 0x60, /* pushal */ - 0xb9, 0x00, 0x00, 0x00, 0x00, /* movl $MSRNUM, %ecx */ - 0x31, 0xc0, /* clr %eax */ - 0x31, 0xd2, /* clr %edx */ - 0x0f, 0x30, /* wrmsr */ - 0x61 /* popal */ - }; - uchar_t *patch = &code[2]; -#endif - - bcopy(&msr, patch, sizeof (uint32_t)); - - kaif_idt_patch((caddr_t)code, sizeof (code)); - - bcopy(code, &kaif_slave_entry_patch, sizeof (code)); -} - -static void -kaif_msr_add_wrexit(uint_t msr, uint64_t *valp) -{ - kaif_msr_wrexit_msr = msr; - kaif_msr_wrexit_valp = valp; -} - -static void -kaif_msr_add(const kmdb_msr_t *msrs) -{ - kmdb_msr_t *save; - int nmsrs, i; - - ASSERT(kaif_cpusave[0].krs_msr == NULL); + kdi_msr_t *save; + size_t nr_msrs = 0; + size_t i; - for (i = 0; msrs[i].msr_num != 0; i++) { - switch (msrs[i].msr_type) { - case KMDB_MSR_CLEARENTRY: - kaif_msr_add_clrentry(msrs[i].msr_num); - break; + while (msrs[nr_msrs].msr_num != 0) + nr_msrs++; + /* we want to copy the terminating kdi_msr_t too */ + nr_msrs++; - case KMDB_MSR_WRITEDELAY: - kaif_msr_add_wrexit(msrs[i].msr_num, msrs[i].msr_valp); - break; - } - } - nmsrs = i + 1; /* we want to copy the terminating kmdb_msr_t too */ - - save = mdb_zalloc(sizeof (kmdb_msr_t) * nmsrs * kaif_ncpusave, + save = mdb_zalloc(sizeof (kdi_msr_t) * nr_msrs * kaif_ncpusave, UM_SLEEP); - for (i = 0; i < kaif_ncpusave; i++) { - bcopy(msrs, &save[nmsrs * i], sizeof (kmdb_msr_t) * nmsrs); - kaif_cpusave[i].krs_msr = &save[nmsrs * i]; - } + for (i = 0; i < kaif_ncpusave; i++) + bcopy(msrs, &save[nr_msrs * i], sizeof (kdi_msr_t) * nr_msrs); + + kmdb_kdi_set_debug_msrs(save); } static uint64_t kaif_msr_get(int cpuid, uint_t num) { - kaif_cpusave_t *save; - kmdb_msr_t *msr; + kdi_cpusave_t *save; + kdi_msr_t *msr; int i; if ((save = kaif_cpuid2save(cpuid)) == NULL) @@ -830,109 +758,115 @@ kaif_msr_get(int cpuid, uint_t num) msr = save->krs_msr; for (i = 0; msr[i].msr_num != 0; i++) { - if (msr[i].msr_num == num && - (msr[i].msr_type & KMDB_MSR_READ)) - return (msr[i].msr_val); + if (msr[i].msr_num == num && (msr[i].msr_type & KDI_MSR_READ)) + return (msr[i].kdi_msr_val); } return (0); } -int -kaif_memrange_add(caddr_t base, size_t len) +void +kaif_trap_set_debugger(void) { - kaif_memrange_t *mr = &kaif_memranges[kaif_nmemranges]; + kmdb_kdi_idt_switch(NULL); +} - if (kaif_nmemranges == KAIF_MEMRANGES_MAX) - return (set_errno(ENOSPC)); +void +kaif_trap_set_saved(kaif_cpusave_t *cpusave) +{ + kmdb_kdi_idt_switch(cpusave); +} +static void +kaif_vmready(void) +{ +} + +void +kaif_memavail(caddr_t base, size_t len) +{ + int ret; /* * In the unlikely event that someone is stepping through this routine, - * we need to make sure that kaif_memranges knows about the new range - * before umem gets it. That way the entry code can recognize stacks + * we need to make sure that the KDI knows about the new range before + * umem gets it. That way the entry code can recognize stacks * allocated from the new region. */ - mr->mr_base = base; - mr->mr_lim = base + len - 1; - kaif_nmemranges++; + kmdb_kdi_memrange_add(base, len); + ret = mdb_umem_add(base, len); + ASSERT(ret == 0); +} - if (mdb_umem_add(base, len) < 0) { - kaif_nmemranges--; - return (-1); /* errno is set for us */ - } +void +kaif_mod_loaded(struct modctl *modp) +{ + if (kaif_modchg_cb != NULL) + kaif_modchg_cb(modp, 1); +} - return (0); +void +kaif_mod_unloading(struct modctl *modp) +{ + if (kaif_modchg_cb != NULL) + kaif_modchg_cb(modp, 0); } void -kaif_trap_set_debugger(void) +kaif_handle_fault(greg_t trapno, greg_t pc, greg_t sp, int cpuid) +{ + kmdb_dpi_handle_fault((kreg_t)trapno, (kreg_t)pc, + (kreg_t)sp, cpuid); +} + +static kdi_debugvec_t kaif_dvec = { + NULL, /* dv_kctl_vmready */ + NULL, /* dv_kctl_memavail */ + NULL, /* dv_kctl_modavail */ + NULL, /* dv_kctl_thravail */ + kaif_vmready, + kaif_memavail, + kaif_mod_loaded, + kaif_mod_unloading, + kaif_handle_fault +}; + +void +kaif_kdi_entry(kdi_cpusave_t *cpusave) { - set_idt(&kaif_idtr); + int ret = kaif_main_loop(cpusave); + ASSERT(ret == KAIF_CPU_CMD_RESUME || + ret == KAIF_CPU_CMD_RESUME_MASTER); } +/*ARGSUSED*/ void -kaif_trap_set_saved(kaif_cpusave_t *cpusave) +kaif_activate(kdi_debugvec_t **dvecp, uint_t flags) { - set_idt(&cpusave->krs_idtr); + kmdb_kdi_activate(kaif_kdi_entry, kaif_cpusave, kaif_ncpusave); + *dvecp = &kaif_dvec; } static int kaif_init(kmdb_auxv_t *kav) { - int i; - /* Allocate the per-CPU save areas */ kaif_cpusave = mdb_zalloc(sizeof (kaif_cpusave_t) * kav->kav_ncpu, UM_SLEEP); kaif_ncpusave = kav->kav_ncpu; - for (i = 0; i < kaif_ncpusave; i++) { - kaif_cpusave_t *save = &kaif_cpusave[i]; - - save->krs_cpu_id = i; - save->krs_curcrumbidx = KAIF_NCRUMBS - 1; - save->krs_curcrumb = &save->krs_crumbs[save->krs_curcrumbidx]; - } - - kaif_idt_init(); - - /* The initial selector set. Updated by the debugger-entry code */ -#ifndef __amd64 - kaif_cs = BOOTCODE_SEL; - kaif_ds = kaif_fs = kaif_gs = BOOTFLAT_SEL; -#endif - - kaif_memranges[0].mr_base = kav->kav_dseg; - kaif_memranges[0].mr_lim = kav->kav_dseg + kav->kav_dseg_size - 1; - kaif_nmemranges = 1; - kaif_modchg_cb = NULL; kaif_waptmap = 0; - kaif_drreg.dr_ctl = KREG_DRCTL_RESERVED; - kaif_drreg.dr_stat = KREG_DRSTAT_RESERVED; - - kaif_msr_wrexit_msr = 0; - kaif_msr_wrexit_valp = NULL; - kaif_trap_switch = (kav->kav_flags & KMDB_AUXV_FL_NOTRPSWTCH) == 0; - if ((kaif_sys_sysenter = kmdb_kdi_lookup_by_name("unix", - "sys_sysenter")) == NULL) - return (set_errno(ENOENT)); - - if ((kaif_brand_sys_sysenter = kmdb_kdi_lookup_by_name("unix", - "brand_sys_sysenter")) == NULL) - return (set_errno(ENOENT)); - return (0); } dpi_ops_t kmdb_dpi_ops = { kaif_init, kaif_activate, - kaif_deactivate, + kmdb_kdi_deactivate, kaif_enter_mon, kaif_modchg_register, kaif_modchg_cancel, @@ -953,7 +887,6 @@ dpi_ops_t kmdb_dpi_ops = { kaif_step_branch, kaif_call, kaif_dump_crumbs, - kaif_memrange_add, kaif_msr_add, kaif_msr_get, }; diff --git a/usr/src/cmd/mdb/intel/kmdb/kaif.h b/usr/src/cmd/mdb/intel/kmdb/kaif.h index c5392e7889..a7af3a6911 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kaif.h +++ b/usr/src/cmd/mdb/intel/kmdb/kaif.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,84 +32,32 @@ #include <sys/kdi.h> #include <sys/types.h> #include <sys/segments.h> -#include <kmdb/kaif_regs.h> +#include <sys/kdi_machimpl.h> #endif #ifdef __cplusplus extern "C" { #endif -#define KAIF_MASTER_CPUID_UNSET -1 +typedef kdi_cpusave_t kaif_cpusave_t; -#define KAIF_CPU_CMD_RESUME 0 -#define KAIF_CPU_CMD_RESUME_MASTER 1 -#define KAIF_CPU_CMD_SWITCH 2 -#define KAIF_CPU_CMD_PASS_TO_KERNEL 3 -#define KAIF_CPU_CMD_REBOOT 4 - -#define KAIF_CPU_STATE_NONE 0 -#define KAIF_CPU_STATE_MASTER 1 -#define KAIF_CPU_STATE_SLAVE 2 +#define KAIF_CPU_STATE_NONE KDI_CPU_STATE_NONE +#define KAIF_CPU_STATE_MASTER KDI_CPU_STATE_MASTER +#define KAIF_CPU_STATE_SLAVE KDI_CPU_STATE_SLAVE #ifndef _ASM -typedef struct kaif_memrange { - caddr_t mr_base; - caddr_t mr_lim; -} kaif_memrange_t; - -extern kaif_memrange_t kaif_memranges[]; -extern int kaif_nmemranges; - -extern kaif_cpusave_t *kaif_cpusave; +extern kdi_cpusave_t *kaif_cpusave; extern int kaif_ncpusave; extern int kaif_master_cpuid; -extern uint32_t kaif_cs; -extern uint32_t kaif_ds; -extern uint32_t kaif_fs; -extern uint32_t kaif_gs; - -extern char kaif_slave_entry_patch; - -extern struct gate_desc kaif_idt[]; -extern desctbr_t kaif_idtr; -extern size_t kaif_ivct_size; extern int kaif_trap_switch; -extern uintptr_t kaif_kernel_handler; -extern uintptr_t kaif_sys_sysenter; -extern uintptr_t kaif_brand_sys_sysenter; - extern void kaif_trap_set_debugger(void); -extern void kaif_trap_set_saved(kaif_cpusave_t *); +extern void kaif_trap_set_saved(kdi_cpusave_t *); extern uintptr_t kaif_invoke(uintptr_t, uint_t, const uintptr_t[]); -extern void kaif_nmiint(void); -extern void kaif_cmnint(void); -extern void kaif_enter(void); -extern void kaif_slave_entry(void); -extern int kaif_debugger_entry(kaif_cpusave_t *); - -extern void kaif_mod_loaded(struct modctl *); -extern void kaif_mod_unloading(struct modctl *); - -extern void kaif_cpu_debug_init(kaif_cpusave_t *); - -extern void kaif_idt_init(void); -extern void kaif_idt_write(gate_desc_t *, uint_t); -extern void kaif_idt_patch(caddr_t, size_t); -extern uintptr_t kaif_kernel_trap2hdlr(int); - -extern void kaif_activate(kdi_debugvec_t **, uint_t); -extern void kaif_deactivate(void); - -extern int kaif_memrange_add(caddr_t, size_t); - -extern void get_idt(desctbr_t *); -extern void set_idt(desctbr_t *); - #endif #ifdef __cplusplus diff --git a/usr/src/cmd/mdb/intel/kmdb/kaif_activate.c b/usr/src/cmd/mdb/intel/kmdb/kaif_activate.c deleted file mode 100644 index 17294e5bb7..0000000000 --- a/usr/src/cmd/mdb/intel/kmdb/kaif_activate.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * The debugger/"PROM" interface layer - debugger activation - * - * Debugger activation has two flavors, which cover the cases where KMDB is - * loaded at boot, and when it is loaded after boot. In brief, in both cases, - * to interpose upon several handlers in the IDT. When mod-loaded KMDB is - * deactivated, we undo the IDT interposition, restoring the handlers to what - * they were before we started. - * - * Boot-loaded KMDB - * - * When we're first activated, we're running on boot's IDT. We need to be able - * to function in this world, so we'll install our handlers into boot's IDT. - * Later, when we're about to switch to the kernel's IDT, it'll call us, - * allowing us to add our handlers to the new IDT. While boot-loaded KMDB can't - * be unloaded, we still need to save the descriptors we replace so we can pass - * traps back to the kernel as necessary. - * - * The last phase of boot-loaded KMDB activation occurs at non-boot CPU startup. - * We will be called on each non-boot CPU, thus allowing us to set up any - * watchpoints that may have been configured on the boot CPU and interpose on - * the given CPU's IDT. We don't save the interposed descriptors in this - * case -- see kaif_cpu_init() for details. - * - * Mod-loaded KMDB - * - * This style of activation is much simpler, as the CPUs are already running, - * and are using their own copy of the kernel's IDT. We simply interpose upon - * each CPU's IDT. We save the handlers we replace, both for deactivation and - * for passing traps back to the kernel. - */ - -#include <kmdb/kmdb_asmutil.h> -#include <kmdb/kmdb_start.h> -#include <kmdb/kmdb_kdi.h> -#include <kmdb/kaif_asmutil.h> -#include <kmdb/kaif_regs.h> -#include <kmdb/kaif.h> - -#include <strings.h> -#include <sys/types.h> -#include <sys/segments.h> -#include <sys/trap.h> -#include <sys/cpuvar.h> -#include <sys/machcpuvar.h> -#include <sys/kdi_impl.h> - -#define KAIF_GATE_NVECS 3 - -#define KAIF_IDT_NOSAVE 0 -#define KAIF_IDT_SAVEOLD 1 - -#define KAIF_IDT_DTYPE_KERNEL 0 -#define KAIF_IDT_DTYPE_BOOT 1 - -typedef struct kaif_gate_spec { - uint_t kgs_vec; - uint_t kgs_dpl; -} kaif_gate_spec_t; - -static const kaif_gate_spec_t kaif_gate_specs[KAIF_GATE_NVECS] = { - { T_SGLSTP, SEL_KPL }, - { T_BPTFLT, SEL_UPL }, - { T_DBGENTR, SEL_KPL } -}; - -static gate_desc_t kaif_kgates[KAIF_GATE_NVECS]; - -static void -kaif_idt_gates_create(gate_desc_t *gates, int useboot) -{ - int i; - - for (i = 0; i < KAIF_GATE_NVECS; i++) { - const kaif_gate_spec_t *gs = &kaif_gate_specs[i]; - kmdb_kdi_idt_init_gate(&gates[i], - (void (*)())GATESEG_GETOFFSET(&kaif_idt[gs->kgs_vec]), - gs->kgs_dpl, useboot); - } -} - -static void -kaif_idt_gates_install(gate_desc_t *idt, gate_desc_t *gates, int saveold) -{ - int i; - - for (i = 0; i < KAIF_GATE_NVECS; i++) { - uint_t vec = kaif_gate_specs[i].kgs_vec; - - if (saveold) - kmdb_kdi_idt_read(idt, &kaif_kgates[i], vec); - - kmdb_kdi_idt_write(idt, &gates[i], vec); - } -} - -static void -kaif_idt_gates_install_by_cpu(cpu_t *cp, gate_desc_t *gates, int saveold) -{ - kaif_idt_gates_install(kmdb_kdi_cpu2idt(cp), gates, saveold); -} - -static void -kaif_idt_gates_restore(cpu_t *cp) -{ - gate_desc_t *idt = kmdb_kdi_cpu2idt(cp); - int i; - - for (i = 0; i < KAIF_GATE_NVECS; i++) { - kmdb_kdi_idt_write(idt, &kaif_kgates[i], - kaif_gate_specs[i].kgs_vec); - } -} - -/* - * Used by the code which passes traps back to the kernel to retrieve the - * address of the kernel's handler for a given trap. We get this address - * from the descriptor save area, which we populated when we loaded the - * debugger (mod-loaded) or initialized the kernel's IDT (boot-loaded). - */ -uintptr_t -kaif_kernel_trap2hdlr(int vec) -{ - int i; - - for (i = 0; i < KAIF_GATE_NVECS; i++) { - if (kaif_gate_specs[i].kgs_vec == vec) - return (GATESEG_GETOFFSET(&kaif_kgates[i])); - } - - return (NULL); -} - -/* - * We're still in single-CPU mode on CPU zero. Install our handlers in the - * current IDT. - */ -static void -kaif_boot_activate(void) -{ - gate_desc_t gates[KAIF_GATE_NVECS]; - - kaif_idt_gates_create(gates, KAIF_IDT_DTYPE_BOOT); - kaif_idt_gates_install(NULL, gates, KAIF_IDT_NOSAVE); -} - -/* Per-CPU debugger activation for boot-loaded and mod-loaded KMDB */ -/*ARGSUSED*/ -static void -kaif_cpu_activate(cpu_t *cp, uint_t saveold) -{ - gate_desc_t gates[KAIF_GATE_NVECS]; - - kaif_idt_gates_create(gates, KAIF_IDT_DTYPE_KERNEL); - kaif_idt_gates_install_by_cpu(cp, gates, saveold); -} - -/* Per-CPU debugger de-activation for mod-loaded KMDB */ -/*ARGSUSED*/ -static void -kaif_cpu_deactivate(cpu_t *cp, uint_t arg) -{ - kaif_idt_gates_restore(cp); -} - -/* - * Called on each non-boot CPU during CPU initialization. We saved the kernel's - * descriptors when we initialized the boot CPU, so we don't want to do it - * again. Saving the handlers from this CPU's IDT would actually be dangerous - * with the CPU initialization method in use at the time of this writing. With - * that method, the startup code creates the IDTs for slave CPUs by copying - * the one used by the boot CPU, which has already been interposed upon by - * KMDB. Were we to interpose again, we'd replace the kernel's descriptors - * with our own in the save area. By not saving, but still overwriting, we'll - * work in the current world, and in any future world where the IDT is generated - * from scratch. - */ -/*ARGSUSED*/ -static void -kaif_cpu_init(cpu_t *cp) -{ - kaif_cpu_activate(cp, KAIF_IDT_NOSAVE); - - /* Load the debug registers and MSRs */ - kaif_cpu_debug_init(&kaif_cpusave[cp->cpu_id]); -} - -/* - * Called very early in _start, just before we switch to the kernel's IDT. We - * need to interpose on the kernel's IDT entries and we need to update our copy - * of the #df handler. - */ -static void -kaif_idt_sync(gate_desc_t *idt) -{ - gate_desc_t gates[KAIF_GATE_NVECS]; - gate_desc_t kdfgate; - - kaif_idt_gates_create(gates, KAIF_IDT_DTYPE_KERNEL); - kaif_idt_gates_install(idt, gates, KAIF_IDT_SAVEOLD); - - kmdb_kdi_idt_read(idt, &kdfgate, T_DBLFLT); - kaif_idt_write(&kdfgate, T_DBLFLT); -} - -static void -kaif_vmready(void) -{ -} - -static kdi_debugvec_t kaif_dvec = { - kaif_enter, - kaif_cpu_init, - NULL, /* dv_kctl_cpu_init */ - kaif_idt_sync, - kaif_vmready, - NULL, /* dv_kctl_vmready */ - NULL, /* dv_kctl_memavail */ - kaif_memrange_add, - NULL, /* dv_kctl_modavail */ - NULL, /* dv_kctl_thravail */ - kaif_mod_loaded, - kaif_mod_unloading -}; - -void -kaif_activate(kdi_debugvec_t **dvecp, uint_t flags) -{ - gate_desc_t kdfgate; - - /* Copy the kernel's #df handler to our IDT */ - kmdb_kdi_idt_read(NULL, &kdfgate, T_DBLFLT); - kaif_idt_write(&kdfgate, T_DBLFLT); - - if (flags & KMDB_ACT_F_BOOT) - kaif_boot_activate(); - else - kmdb_kdi_cpu_iter(kaif_cpu_activate, KAIF_IDT_SAVEOLD); - - *dvecp = &kaif_dvec; -} - -void -kaif_deactivate(void) -{ - kmdb_kdi_cpu_iter(kaif_cpu_deactivate, 0); -} diff --git a/usr/src/cmd/mdb/intel/kmdb/kaif_idt.c b/usr/src/cmd/mdb/intel/kmdb/kaif_idt.c deleted file mode 100644 index 43e218e1a6..0000000000 --- a/usr/src/cmd/mdb/intel/kmdb/kaif_idt.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * kmdb's IDT - */ - -#include <sys/types.h> -#include <sys/segments.h> -#include <sys/trap.h> -#include <strings.h> - -#include <kmdb/kaif.h> -#include <mdb/mdb_debug.h> -#include <kmdb/kaif_asmutil.h> - -#if defined(__amd64) -#define KMDBCODE_SEL B64CODE_SEL -#else -#define KMDBCODE_SEL BOOTCODE_SEL -#endif - -typedef void idt_hdlr_f(void); - -extern idt_hdlr_f kaif_trap0, kaif_trap1, kaif_int2, kaif_trap3, kaif_trap4; -extern idt_hdlr_f kaif_trap5, kaif_trap6, kaif_trap7, kaif_traperr8, kaif_trap9; -extern idt_hdlr_f kaif_traperr10, kaif_traperr11, kaif_traperr12; -extern idt_hdlr_f kaif_traperr13, kaif_traperr14, kaif_trap16, kaif_trap17; -extern idt_hdlr_f kaif_trap18, kaif_trap19, kaif_trap20, kaif_ivct32; -extern idt_hdlr_f kaif_invaltrap; - -gate_desc_t kaif_idt[NIDT]; -desctbr_t kaif_idtr; - -struct idt_description { - uint_t id_low; - uint_t id_high; - idt_hdlr_f *id_basehdlr; - size_t *id_incrp; - uint_t id_type; -} idt_description[] = { - { T_ZERODIV, 0, kaif_trap0, NULL, SDT_SYSIGT }, - { T_SGLSTP, 0, kaif_trap1, NULL, SDT_SYSIGT }, - { T_NMIFLT, 0, kaif_int2, NULL, SDT_SYSIGT }, - { T_BPTFLT, 0, kaif_trap3, NULL, SDT_SYSIGT }, - { T_OVFLW, 0, kaif_trap4, NULL, SDT_SYSIGT }, - { T_BOUNDFLT, 0, kaif_trap5, NULL, SDT_SYSIGT }, - { T_ILLINST, 0, kaif_trap6, NULL, SDT_SYSIGT }, - { T_NOEXTFLT, 0, kaif_trap7, NULL, SDT_SYSIGT }, - { T_DBLFLT, 0, kaif_traperr8, NULL, SDT_SYSIGT }, - { T_EXTOVRFLT, 0, kaif_trap9, NULL, SDT_SYSIGT }, - { T_TSSFLT, 0, kaif_traperr10, NULL, SDT_SYSIGT }, - { T_SEGFLT, 0, kaif_traperr11, NULL, SDT_SYSIGT }, - { T_STKFLT, 0, kaif_traperr12, NULL, SDT_SYSIGT }, - { T_GPFLT, 0, kaif_traperr13, NULL, SDT_SYSIGT }, - { T_PGFLT, 0, kaif_traperr14, NULL, SDT_SYSIGT }, - { 15, 0, kaif_invaltrap, NULL, SDT_SYSIGT }, - { T_EXTERRFLT, 0, kaif_trap16, NULL, SDT_SYSIGT }, - { T_ALIGNMENT, 0, kaif_trap17, NULL, SDT_SYSIGT }, - { T_MCE, 0, kaif_trap18, NULL, SDT_SYSIGT }, - { T_SIMDFPE, 0, kaif_trap19, NULL, SDT_SYSIGT }, - { T_DBGENTR, 0, kaif_trap20, NULL, SDT_SYSIGT }, - { 21, 31, kaif_invaltrap, NULL, SDT_SYSIGT }, - { 32, 255, kaif_ivct32, &kaif_ivct_size, SDT_SYSIGT }, - { 0, 0, NULL }, -}; - -static void -kaif_set_gatesegd(gate_desc_t *dp, void (*func)(void), selector_t sel, - uint_t type) -{ - bzero(dp, sizeof (gate_desc_t)); - - dp->sgd_looffset = ((uintptr_t)func) & 0xffff; - dp->sgd_hioffset = ((uintptr_t)func >> 16) & 0xffff; -#ifdef __amd64 - dp->sgd_hi64offset = (uintptr_t)func >> 32; -#endif - - dp->sgd_selector = (uint16_t)sel; - dp->sgd_type = type; - dp->sgd_dpl = SEL_KPL; - dp->sgd_p = 1; - -#ifdef __amd64 - dp->sgd_ist = 0; -#else - dp->sgd_stkcpy = 0; -#endif -} - -void -kaif_idt_init(void) -{ - struct idt_description *id; - int i; - - for (id = idt_description; id->id_basehdlr != NULL; id++) { - uint_t high = id->id_high != 0 ? id->id_high : id->id_low; - size_t incr = id->id_incrp != NULL ? *id->id_incrp : 0; - - for (i = id->id_low; i <= high; i++) { - caddr_t hdlr = (caddr_t)id->id_basehdlr + - incr * (i - id->id_low); - kaif_set_gatesegd(&kaif_idt[i], (void (*)(void))hdlr, - KMDBCODE_SEL, id->id_type); - } - } - - kaif_idtr.dtr_limit = sizeof (kaif_idt) - 1; - kaif_idtr.dtr_base = (uint64_t)kaif_idt; -} - -/* - * Patch caller-provided code into the debugger's IDT handlers. This code is - * used to save MSRs that must be saved before the first branch. All handlers - * are essentially the same, and end with a branch to kaif_cmnint. To save the - * MSR, we need to patch in before the branch. The handlers have the following - * structure: KAIF_MSR_PATCHOFF bytes of code, KAIF_MSR_PATCHSZ bytes of - * patchable space, followed by more code. - */ -void -kaif_idt_patch(caddr_t code, size_t sz) -{ - int i; - - ASSERT(sz <= KAIF_MSR_PATCHSZ); - - for (i = 0; i < sizeof (kaif_idt) / sizeof (struct gate_desc); i++) { - gate_desc_t *gd; - uchar_t *patch; - - if (i == T_DBLFLT) - continue; /* uses kernel's handler */ - - gd = &kaif_idt[i]; - patch = (uchar_t *)GATESEG_GETOFFSET(gd) + KAIF_MSR_PATCHOFF; - - /* - * We can't ASSERT that there's a nop here, because this may be - * a debugger restart. In that case, we're copying the new - * patch point over the old one. - */ - bcopy(code, patch, sz); - - /* Fill the rest with nops to be sure */ - while (sz < KAIF_MSR_PATCHSZ) - patch[sz++] = 0x90; /* nop */ - } -} - -void -kaif_idt_write(gate_desc_t *gate, uint_t vec) -{ - kaif_idt[vec] = *gate; -} diff --git a/usr/src/cmd/mdb/intel/kmdb/kaif_regs.h b/usr/src/cmd/mdb/intel/kmdb/kaif_regs.h deleted file mode 100644 index 9d5b64a240..0000000000 --- a/usr/src/cmd/mdb/intel/kmdb/kaif_regs.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _KAIF_REGS_H -#define _KAIF_REGS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifndef _ASM -#include <sys/types.h> -#include <sys/segments.h> - -#include <mdb/mdb_kreg_impl.h> -#include <mdb/mdb_target.h> -#include <kmdb/kmdb_dpi.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define KAIF_NCRUMBS 5 - -#ifndef _ASM - -/* - * We maintain a ring buffer of bread crumbs for debugging purposes. The - * current buffer pointer is advanced along the ring with each intercepted - * trap (debugger entry, invalid memory access, fault during step, etc). - * The macros used to populate the crumb buffers assume that all members are - * 32 bits wide. - */ -typedef struct kaif_crumb { - kreg_t krm_cpu_state; /* This CPU's state at last entry */ - kreg_t krm_pc; /* Instruction pointer at trap */ - kreg_t krm_sp; /* Stack pointer at trap */ - kreg_t krm_trapno; /* The last trap number */ - kreg_t krm_flag; /* KAIF_CRUMB_F_* */ -} kaif_crumb_t; - -/* - * Storage for %dr0-3, %dr6, and %dr7. - */ -typedef struct kaif_drreg { - kreg_t dr_ctl; - kreg_t dr_stat; - kreg_t dr_addr[KREG_MAXWPIDX + 1]; -} kaif_drreg_t; - -/* - * Data structure used to hold all of the state for a given CPU. - */ -typedef struct kaif_cpusave { - mdb_tgt_gregset_t *krs_gregs; /* saved registers */ - - kaif_drreg_t krs_dr; /* saved debug registers */ - - desctbr_t krs_gdtr; /* saved GDT register */ - desctbr_t krs_idtr; /* saved IDT register */ - desctbr_t krs_tmpdesc; /* pre-save *DT comparisons */ - - kreg_t krs_cr0; /* saved %cr0 */ - - kmdb_msr_t *krs_msr; /* ptr to MSR save area */ - - uint_t krs_cpu_state; /* KAIF_CPU_STATE_* mstr/slv */ - uint_t krs_cpu_flushed; /* Have caches been flushed? */ - uint_t krs_cpu_id; /* this CPU's ID */ - - /* Bread crumb ring buffer */ - ulong_t krs_curcrumbidx; /* Current krs_crumbs idx */ - kaif_crumb_t *krs_curcrumb; /* Pointer to current crumb */ - kaif_crumb_t krs_crumbs[KAIF_NCRUMBS]; /* Crumbs */ -} kaif_cpusave_t; - -#endif /* !_ASM */ - -#ifdef __cplusplus -} -#endif - -#endif /* _KAIF_REGS_H */ diff --git a/usr/src/cmd/mdb/intel/kmdb/kaif_start_isadep.c b/usr/src/cmd/mdb/intel/kmdb/kaif_start_isadep.c deleted file mode 100644 index 708cbb390c..0000000000 --- a/usr/src/cmd/mdb/intel/kmdb/kaif_start_isadep.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * The Intel-specific interface to the main CPU-control loops - */ - -#include <sys/types.h> -#include <sys/trap.h> -#include <sys/segments.h> -#include <ia32/sys/psw.h> - -#include <kmdb/kaif.h> -#include <kmdb/kaif_regs.h> -#include <kmdb/kaif_start.h> -#include <kmdb/kmdb_dpi_impl.h> -#include <kmdb/kmdb_kdi.h> -#include <mdb/mdb.h> - -/* - * We receive all breakpoints and single step traps. Some of them, - * including those from userland and those induced by DTrace providers, - * are intended for the kernel, and must be processed there. We adopt - * this ours-until-proven-otherwise position due to the painful - * consequences of sending the kernel an unexpected breakpoint or - * single step. Unless someone can prove to us that the kernel is - * prepared to handle the trap, we'll assume there's a problem and will - * give the user a chance to debug it. - */ -static int -kaif_trap_pass(kaif_cpusave_t *cpusave) -{ - kreg_t tt = cpusave->krs_gregs->kregs[KREG_TRAPNO]; - kreg_t pc = cpusave->krs_gregs->kregs[KREG_PC]; - kreg_t cs = cpusave->krs_gregs->kregs[KREG_CS]; - - if (tt != T_BPTFLT && tt != T_SGLSTP) - return (0); - - if (USERMODE(cs)) - return (1); - - if (tt == T_BPTFLT && kmdb_kdi_dtrace_get_state() == - KDI_DTSTATE_DTRACE_ACTIVE) - return (1); - - /* - * See the comments in the kernel's T_SGLSTP handler for why we need to - * do this. - */ - if (tt == T_SGLSTP && - (pc == kaif_sys_sysenter || pc == kaif_brand_sys_sysenter)) - return (1); - - return (0); -} - -/* - * State has been saved, and all CPUs are on the CPU-specific stacks. All - * CPUs enter here, and head off to the slave spin loop or into the debugger - * as appropriate. This routine also handles the various flavors of resume. - * - * Returns 1 for the master CPU if there's work to be done by the driver, 0 - * otherwise. - */ -int -kaif_debugger_entry(kaif_cpusave_t *cpusave) -{ - if (kaif_trap_pass(cpusave)) { - cpusave->krs_cpu_state = KAIF_CPU_STATE_NONE; - return (KAIF_CPU_CMD_PASS_TO_KERNEL); - } - - /* - * BPTFLT gives us control with %eip set to the instruction *after* - * the int 3. Back it off, so we're looking at the instruction that - * triggered the fault. - */ - if (cpusave->krs_gregs->kregs[KREG_TRAPNO] == T_BPTFLT) - cpusave->krs_gregs->kregs[KREG_PC]--; - - return (kaif_main_loop(cpusave)); -} diff --git a/usr/src/cmd/mdb/intel/kmdb/kctl/kctl_isadep.c b/usr/src/cmd/mdb/intel/kmdb/kctl/kctl_isadep.c index 542b5b69e1..44b2248755 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kctl/kctl_isadep.c +++ b/usr/src/cmd/mdb/intel/kmdb/kctl/kctl_isadep.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,16 +38,11 @@ #include <sys/controlregs.h> #include <sys/archsystm.h> -#if defined(__i386) -/* Copied from stand/i386/sys/bootdef.h */ -#define GS_GDT 0x38 /* dummy cpu_t pointer descriptor */ -#endif - static int kctl_boot_prop_read(char *pname, char *prop_buf, int buf_len) { - int len; struct bootops *ops = kctl.kctl_boot_ops; + int len; len = BOP_GETPROPLEN(ops, pname); if (len > 0 && len <= buf_len) { @@ -144,12 +139,6 @@ kctl_pcache_destroy(kmdb_auxv_nv_t *pnv) kobj_free(pnv, sizeof (kmdb_auxv_nv_t) * KCTL_PROPNV_NENT); } -/*ARGSUSED*/ -static void -kctl_cpu_init(void) -{ -} - void kctl_auxv_init_isadep(kmdb_auxv_t *kav, void *romp) { @@ -171,16 +160,13 @@ kctl_preactivate_isadep(void) } /*ARGSUSED*/ -int +void kctl_activate_isadep(kdi_debugvec_t *dvec) { - dvec->dv_kctl_cpu_init = kctl_cpu_init; dvec->dv_kctl_vmready = hat_kdi_init; if (!kctl.kctl_boot_loaded) hat_kdi_init(); - - return (0); } void @@ -188,64 +174,20 @@ kctl_depreactivate_isadep(void) { } -void -kctl_deactivate_isadep(void) -{ - hat_kdi_fini(); -} - -#if defined(__amd64) -void * -kctl_boot_tmpinit(void) -{ - /* - * Many common kernel functions assume that GSBASE has been initialized, - * and fail horribly if it hasn't. We'll install a pointer to a dummy - * cpu_t for use during our initialization. - */ - cpu_t *old = (cpu_t *)rdmsr(MSR_AMD_GSBASE); - - wrmsr(MSR_AMD_GSBASE, (uint64_t)kobj_zalloc(sizeof (cpu_t), KM_TMP)); - return (old); -} - -void -kctl_boot_tmpfini(void *old) -{ - wrmsr(MSR_AMD_GSBASE, (uint64_t)old); -} - -#else - +/* + * Many common kernel functions assume that %gs can be deferenced, and + * fail horribly if it cannot. Ask the kernel to set up a temporary + * mapping to a fake cpu_t so that we can call such functions during + * initialization. + */ void * kctl_boot_tmpinit(void) { - /* - * Many common kernel functions assume that %gs has been initialized, - * and fail horribly if it hasn't. Boot has reserved a descriptor for - * us (GS_GDT) in its GDT, a descriptor which we'll use to describe our - * dummy cpu_t. We then set %gs to refer to this descriptor. - */ - cpu_t *cpu = kobj_zalloc(sizeof (cpu_t), KM_TMP); - uintptr_t old; - desctbr_t bgdt; - user_desc_t *gsdesc; - - rd_gdtr(&bgdt); - gsdesc = (user_desc_t *)(bgdt.dtr_base + GS_GDT); - - USEGD_SETBASE(gsdesc, (uintptr_t)cpu); - USEGD_SETLIMIT(gsdesc, sizeof (cpu_t)); - - old = getgs(); - setgs(GS_GDT); - - return ((void *)old); + return (boot_kdi_tmpinit()); } void kctl_boot_tmpfini(void *old) { - setgs((uintptr_t)old); + boot_kdi_tmpfini(old); } -#endif diff --git a/usr/src/cmd/mdb/intel/kmdb/kmdb_dpi_isadep.c b/usr/src/cmd/mdb/intel/kmdb/kmdb_dpi_isadep.c index f5b7a3a679..719e36b8dc 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kmdb_dpi_isadep.c +++ b/usr/src/cmd/mdb/intel/kmdb/kmdb_dpi_isadep.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -145,7 +144,7 @@ kmdb_dpi_reboot(void) } void -kmdb_dpi_msr_add(const kmdb_msr_t *msrs) +kmdb_dpi_msr_add(const kdi_msr_t *msrs) { mdb.m_dpi->dpo_msr_add(msrs); } diff --git a/usr/src/cmd/mdb/intel/kmdb/kmdb_dpi_isadep.h b/usr/src/cmd/mdb/intel/kmdb/kmdb_dpi_isadep.h index 952960060f..2565c1f843 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kmdb_dpi_isadep.h +++ b/usr/src/cmd/mdb/intel/kmdb/kmdb_dpi_isadep.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,36 +30,20 @@ #ifndef _ASM #include <mdb/mdb_isautil.h> +#include <sys/kdi_machimpl.h> #endif #ifdef __cplusplus extern "C" { #endif -#define KMDB_MSR_READ 0x1 /* read during entry (unlimited) */ -#define KMDB_MSR_WRITE 0x2 /* write during exit (unlimited) */ -#define KMDB_MSR_WRITEDELAY 0x4 /* write after last branch (<= 1) */ -#define KMDB_MSR_CLEARENTRY 0x3 /* clear before 1st branch (<= 1) */ - #ifndef _ASM -typedef struct kmdb_msr { - uint_t msr_num; - uint_t msr_type; - union { - uint64_t *_msr_valp; - uint64_t _msr_val; - } _u; -} kmdb_msr_t; - -#define msr_val _u._msr_val -#define msr_valp _u._msr_valp - extern void kmdb_dpi_handle_fault(kreg_t, kreg_t, kreg_t, int); extern void kmdb_dpi_reboot(void) __NORETURN; -extern void kmdb_dpi_msr_add(const kmdb_msr_t *); +extern void kmdb_dpi_msr_add(const kdi_msr_t *); extern uint64_t kmdb_dpi_msr_get(uint_t); extern uint64_t kmdb_dpi_msr_get_by_cpu(int, uint_t); diff --git a/usr/src/cmd/mdb/intel/kmdb/kmdb_kdi_isadep.c b/usr/src/cmd/mdb/intel/kmdb/kmdb_kdi_isadep.c index ef001fff68..a556c90041 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kmdb_kdi_isadep.c +++ b/usr/src/cmd/mdb/intel/kmdb/kmdb_kdi_isadep.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -35,30 +34,26 @@ #include <mdb/mdb_err.h> #include <mdb/mdb_umem.h> #include <kmdb/kmdb_dpi.h> -#include <kmdb/kmdb_kdi_impl.h> #include <mdb/mdb.h> -void (**kmdb_kdi_shutdownp)(int, int); - -int -kmdb_kdi_xc_initialized(void) +/*ARGSUSED*/ +void +kmdb_kdi_stop_slaves(int my_cpuid, int doxc) { - return (mdb.m_kdi->mkdi_xc_initialized()); + /* Stop other CPUs if there are CPUs to stop */ + mdb.m_kdi->mkdi_stop_slaves(my_cpuid, doxc); } -/*ARGSUSED*/ void -kmdb_kdi_stop_other_cpus(int my_cpuid, void (*slave_saver)(void)) +kmdb_kdi_start_slaves(void) { - /* Stop other CPUs if there are CPUs to stop */ - if (mdb.m_kdi->mkdi_xc_initialized()) - mdb.m_kdi->mkdi_xc_others(my_cpuid, slave_saver); + mdb.m_kdi->mkdi_start_slaves(); } void -kmdb_kdi_cpu_iter(void (*iter)(struct cpu *, uint_t), uint_t arg) +kmdb_kdi_slave_wait(void) { - mdb.m_kdi->mkdi_cpu_iter(iter, arg); + mdb.m_kdi->mkdi_slave_wait(); } uintptr_t @@ -67,51 +62,61 @@ kmdb_kdi_get_userlimit(void) return (mdb.m_kdi->mkdi_get_userlimit()); } -void -kmdb_kdi_idt_init_gate(gate_desc_t *gate, void (*hdlr)(void), uint_t dpl, - int useboot) +int +kmdb_kdi_get_cpuinfo(uint_t *vendorp, uint_t *familyp, uint_t *modelp) { - mdb.m_kdi->mkdi_idt_init_gate(gate, hdlr, dpl, useboot); + int err; + + if ((err = mdb.m_kdi->mkdi_get_cpuinfo(vendorp, familyp, modelp)) != 0) + return (set_errno(err)); + + return (0); } +/*ARGSUSED*/ void -kmdb_kdi_idt_read(gate_desc_t *idt, gate_desc_t *gatep, uint_t vec) +kmdb_kdi_init_isadep(kdi_t *kdi, kmdb_auxv_t *kav) { - mdb.m_kdi->mkdi_idt_read(idt, gatep, vec); } void -kmdb_kdi_idt_write(gate_desc_t *idt, gate_desc_t *gate, uint_t vec) +kmdb_kdi_activate(kdi_main_t main, kdi_cpusave_t *cpusave, int ncpusave) { - mdb.m_kdi->mkdi_idt_write(idt, gate, vec); + mdb.m_kdi->mkdi_activate(main, cpusave, ncpusave); } -gate_desc_t * -kmdb_kdi_cpu2idt(cpu_t *cp) +void +kmdb_kdi_deactivate(void) { - return (mdb.m_kdi->mkdi_cpu2idt(cp)); + mdb.m_kdi->mkdi_deactivate(); } -int -kmdb_kdi_get_cpuinfo(uint_t *vendorp, uint_t *familyp, uint_t *modelp) +void +kmdb_kdi_idt_switch(kdi_cpusave_t *cpusave) { - int err; + mdb.m_kdi->mkdi_idt_switch(cpusave); +} - if ((err = mdb.m_kdi->mkdi_get_cpuinfo(vendorp, familyp, modelp)) != 0) - return (set_errno(err)); +void +kmdb_kdi_update_drreg(kdi_drreg_t *drreg) +{ + mdb.m_kdi->mkdi_update_drreg(drreg); +} - return (0); +void +kmdb_kdi_set_debug_msrs(kdi_msr_t *msrs) +{ + mdb.m_kdi->mkdi_set_debug_msrs(msrs); } -/*ARGSUSED*/ void -kdi_cpu_init(void) +kmdb_kdi_memrange_add(caddr_t base, size_t len) { + mdb.m_kdi->mkdi_memrange_add(base, len); } -/*ARGSUSED1*/ void -kmdb_kdi_init_isadep(kdi_t *kdi, kmdb_auxv_t *kav) +kmdb_kdi_reboot(void) { - kmdb_kdi_shutdownp = kdi->mkdi_shutdownp; + mdb.m_kdi->mkdi_reboot(); } diff --git a/usr/src/cmd/mdb/intel/kmdb/kmdb_kdi_isadep.h b/usr/src/cmd/mdb/intel/kmdb/kmdb_kdi_isadep.h index 6807a4809c..1813b382e3 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kmdb_kdi_isadep.h +++ b/usr/src/cmd/mdb/intel/kmdb/kmdb_kdi_isadep.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -30,6 +29,7 @@ #pragma ident "%Z%%M% %I% %E% SMI" #include <sys/types.h> +#include <sys/kdi_machimpl.h> #include <mdb/mdb_target.h> @@ -39,24 +39,21 @@ extern "C" { struct gate_desc; -extern void (**kdi_shutdownp)(int, int); +extern void kmdb_kdi_activate(kdi_main_t, kdi_cpusave_t *, int); +extern void kmdb_kdi_deactivate(void); -extern uintptr_t kmdb_kdi_get_userlimit(void); -extern int kmdb_kdi_xc_initialized(void); +extern void kmdb_kdi_idt_switch(kdi_cpusave_t *); + +extern void kmdb_kdi_update_drreg(kdi_drreg_t *); +extern void kmdb_kdi_set_debug_msrs(kdi_msr_t *); -extern void kmdb_kdi_idt_init_gate(struct gate_desc *, void (*)(void), uint_t, - int); -extern void kmdb_kdi_idt_read(struct gate_desc *, struct gate_desc *, uint_t); -extern void kmdb_kdi_idt_write(struct gate_desc *, struct gate_desc *, uint_t); -extern struct gate_desc *kmdb_kdi_cpu2idt(struct cpu *); +extern uintptr_t kmdb_kdi_get_userlimit(void); extern int kmdb_kdi_get_cpuinfo(uint_t *, uint_t *, uint_t *); -/* - * To be used only when the kernel is running - */ -extern void kmdb_kdi_cpu_iter(void (*)(struct cpu *, uint_t), - uint_t); +extern void kmdb_kdi_memrange_add(caddr_t, size_t); + +extern void kmdb_kdi_reboot(void); #ifdef __cplusplus } diff --git a/usr/src/cmd/mdb/intel/kmdb/kvm_cpu_amd.c b/usr/src/cmd/mdb/intel/kmdb/kvm_cpu_amd.c index 7d05c02265..6b67853220 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kvm_cpu_amd.c +++ b/usr/src/cmd/mdb/intel/kmdb/kvm_cpu_amd.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,7 +40,7 @@ typedef struct kmt_cpu_amd { uint64_t amd_debugctl; /* value for debugctl MSR */ - const kmdb_msr_t *amd_msrs; /* MSR r/w list */ + const kdi_msr_t *amd_msrs; /* MSR r/w list */ uint_t amd_family; /* CPUID family */ uint_t amd_model; /* CPUID model */ } kmt_cpu_amd_t; @@ -72,22 +71,22 @@ kmt_amd_branch(uint_t cpuid, const char *label, uint_t msr) * MSRs for AMD processors with simple branch tracing facilities. We'll use * this array if we can access listed LBR/LEX MSRs. */ -static const kmdb_msr_t kmt_amd_msrs[] = { - { MSR_DEBUGCTL, KMDB_MSR_CLEARENTRY }, - { MSR_DEBUGCTL, KMDB_MSR_WRITEDELAY, &kmt_cpu_amd.amd_debugctl }, - { MSR_LBR_TO, KMDB_MSR_READ }, - { MSR_LBR_FROM, KMDB_MSR_READ }, - { MSR_LEX_TO, KMDB_MSR_READ }, - { MSR_LEX_FROM, KMDB_MSR_READ }, +static const kdi_msr_t kmt_amd_msrs[] = { + { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY }, + { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_amd.amd_debugctl }, + { MSR_LBR_TO, KDI_MSR_READ }, + { MSR_LBR_FROM, KDI_MSR_READ }, + { MSR_LEX_TO, KDI_MSR_READ }, + { MSR_LEX_FROM, KDI_MSR_READ }, { NULL } }; /* * Fallback MSR list for use if we can't read the LBR/LEX MSRs. */ -static const kmdb_msr_t kmt_amdunk_msrs[] = { - { MSR_DEBUGCTL, KMDB_MSR_CLEARENTRY }, - { MSR_DEBUGCTL, KMDB_MSR_WRITEDELAY, &kmt_cpu_amd.amd_debugctl }, +static const kdi_msr_t kmt_amdunk_msrs[] = { + { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY }, + { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_amd.amd_debugctl }, { NULL } }; diff --git a/usr/src/cmd/mdb/intel/kmdb/kvm_cpu_p4.c b/usr/src/cmd/mdb/intel/kmdb/kvm_cpu_p4.c index 39d5ea175a..653b4a31f5 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kvm_cpu_p4.c +++ b/usr/src/cmd/mdb/intel/kmdb/kvm_cpu_p4.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -51,7 +50,7 @@ */ typedef struct kmt_p4_flavor { const char *p4f_name; /* name for CPU support */ - const kmdb_msr_t *p4f_msrs; /* MSR r/w list */ + const kdi_msr_t *p4f_msrs; /* MSR r/w list */ int (*p4f_branches)(const struct kmt_p4_flavor *, uint_t, intptr_t, int); /* dumper for CPU branch stk */ uint_t p4f_msr_tos; /* branch stk index MSR */ @@ -164,14 +163,14 @@ kmt_p4_branches_split(const kmt_p4_flavor_t *p4f, uint_t tos, intptr_t cpuid, } #ifndef __amd64 -static const kmdb_msr_t kmt_p4orig_msrs[] = { - { MSR_DEBUGCTL, KMDB_MSR_CLEARENTRY }, - { MSR_DEBUGCTL, KMDB_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl }, - { MSR_P4_LBSTK_TOS, KMDB_MSR_READ }, - { MSR_P4_LBSTK_0, KMDB_MSR_READ }, - { MSR_P4_LBSTK_1, KMDB_MSR_READ }, - { MSR_P4_LBSTK_2, KMDB_MSR_READ }, - { MSR_P4_LBSTK_3, KMDB_MSR_READ }, +static const kdi_msr_t kmt_p4orig_msrs[] = { + { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY }, + { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl }, + { MSR_P4_LBSTK_TOS, KDI_MSR_READ }, + { MSR_P4_LBSTK_0, KDI_MSR_READ }, + { MSR_P4_LBSTK_1, KDI_MSR_READ }, + { MSR_P4_LBSTK_2, KDI_MSR_READ }, + { MSR_P4_LBSTK_3, KDI_MSR_READ }, { NULL } }; @@ -181,18 +180,18 @@ static const kmt_p4_flavor_t kmt_p4_original = { MSR_P4_LBSTK_0, MSR_P4_LBSTK_0, 4 }; -static const kmdb_msr_t kmt_p6m_msrs[] = { - { MSR_DEBUGCTL, KMDB_MSR_CLEARENTRY }, - { MSR_DEBUGCTL, KMDB_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl }, - { MSR_P6M_LBSTK_TOS, KMDB_MSR_READ }, - { MSR_P6M_LBSTK_0, KMDB_MSR_READ }, - { MSR_P6M_LBSTK_1, KMDB_MSR_READ }, - { MSR_P6M_LBSTK_2, KMDB_MSR_READ }, - { MSR_P6M_LBSTK_3, KMDB_MSR_READ }, - { MSR_P6M_LBSTK_4, KMDB_MSR_READ }, - { MSR_P6M_LBSTK_5, KMDB_MSR_READ }, - { MSR_P6M_LBSTK_6, KMDB_MSR_READ }, - { MSR_P6M_LBSTK_7, KMDB_MSR_READ }, +static const kdi_msr_t kmt_p6m_msrs[] = { + { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY }, + { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl }, + { MSR_P6M_LBSTK_TOS, KDI_MSR_READ }, + { MSR_P6M_LBSTK_0, KDI_MSR_READ }, + { MSR_P6M_LBSTK_1, KDI_MSR_READ }, + { MSR_P6M_LBSTK_2, KDI_MSR_READ }, + { MSR_P6M_LBSTK_3, KDI_MSR_READ }, + { MSR_P6M_LBSTK_4, KDI_MSR_READ }, + { MSR_P6M_LBSTK_5, KDI_MSR_READ }, + { MSR_P6M_LBSTK_6, KDI_MSR_READ }, + { MSR_P6M_LBSTK_7, KDI_MSR_READ }, { NULL } }; @@ -203,42 +202,42 @@ static const kmt_p4_flavor_t kmt_p6_m = { }; #endif /* __amd64 */ -static const kmdb_msr_t kmt_prp4_msrs[] = { - { MSR_DEBUGCTL, KMDB_MSR_CLEARENTRY }, - { MSR_DEBUGCTL, KMDB_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl }, - { MSR_PRP4_LBSTK_TOS, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_0, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_1, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_2, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_3, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_4, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_5, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_6, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_7, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_8, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_9, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_10, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_11, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_12, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_13, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_14, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_FROM_15, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_0, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_1, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_2, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_3, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_4, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_5, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_6, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_7, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_8, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_9, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_10, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_11, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_12, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_13, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_14, KMDB_MSR_READ }, - { MSR_PRP4_LBSTK_TO_15, KMDB_MSR_READ }, +static const kdi_msr_t kmt_prp4_msrs[] = { + { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY }, + { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl }, + { MSR_PRP4_LBSTK_TOS, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_0, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_1, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_2, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_3, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_4, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_5, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_6, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_7, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_8, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_9, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_10, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_11, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_12, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_13, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_14, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_FROM_15, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_0, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_1, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_2, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_3, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_4, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_5, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_6, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_7, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_8, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_9, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_10, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_11, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_12, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_13, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_14, KDI_MSR_READ }, + { MSR_PRP4_LBSTK_TO_15, KDI_MSR_READ }, { NULL } }; @@ -248,9 +247,9 @@ static const kmt_p4_flavor_t kmt_p4_prescott = { MSR_PRP4_LBSTK_FROM_0, MSR_PRP4_LBSTK_TO_0, 16 }; -static const kmdb_msr_t kmt_p4unk_msrs[] = { - { MSR_DEBUGCTL, KMDB_MSR_CLEARENTRY }, - { MSR_DEBUGCTL, KMDB_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl }, +static const kdi_msr_t kmt_p4unk_msrs[] = { + { MSR_DEBUGCTL, KDI_MSR_CLEARENTRY }, + { MSR_DEBUGCTL, KDI_MSR_WRITEDELAY, &kmt_cpu_p4.p4_debugctl }, { NULL } }; diff --git a/usr/src/cmd/mdb/intel/kmdb/kvm_isadep.c b/usr/src/cmd/mdb/intel/kmdb/kvm_isadep.c index e80b2243ef..3f32502080 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kvm_isadep.c +++ b/usr/src/cmd/mdb/intel/kmdb/kvm_isadep.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -377,7 +377,7 @@ kmt_wrmsr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) } int -kmt_msr_validate(const kmdb_msr_t *msr) +kmt_msr_validate(const kdi_msr_t *msr) { uint64_t val; diff --git a/usr/src/cmd/mdb/intel/kmdb/kvm_isadep.h b/usr/src/cmd/mdb/intel/kmdb/kvm_isadep.h index d03ae5eafa..e944c6ca8b 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kvm_isadep.h +++ b/usr/src/cmd/mdb/intel/kmdb/kvm_isadep.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -46,8 +45,7 @@ extern int kmt_wrmsr(uintptr_t, uint_t, int, const mdb_arg_t *); extern int kmt_rdpcicfg(uintptr_t, uint_t, int, const mdb_arg_t *); extern int kmt_wrpcicfg(uintptr_t, uint_t, int, const mdb_arg_t *); - -extern int kmt_msr_validate(const kmdb_msr_t *); +extern int kmt_msr_validate(const kdi_msr_t *); #ifdef __cplusplus } diff --git a/usr/src/cmd/mdb/intel/mdb/kvm_amd64dep.c b/usr/src/cmd/mdb/intel/mdb/kvm_amd64dep.c index a2f965f424..43468af924 100644 --- a/usr/src/cmd/mdb/intel/mdb/kvm_amd64dep.c +++ b/usr/src/cmd/mdb/intel/mdb/kvm_amd64dep.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -320,8 +319,6 @@ kt_amd64_init(mdb_tgt_t *t) kregs[KREG_R13] = regs.r_r13; kregs[KREG_R14] = regs.r_r14; kregs[KREG_R15] = regs.r_r15; - kregs[KREG_FSBASE] = regs.r_fsbase; - kregs[KREG_GSBASE] = regs.r_gsbase; kregs[KREG_DS] = regs.r_ds; kregs[KREG_ES] = regs.r_es; kregs[KREG_FS] = regs.r_fs; diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c b/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c index 93ab6bf92b..303923f236 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c +++ b/usr/src/cmd/mdb/intel/mdb/mdb_amd64util.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -64,9 +64,6 @@ const mdb_tgt_regdesc_t mdb_amd64_kregs[] = { { "r13", KREG_R13, MDB_TGT_R_EXPORT }, { "r14", KREG_R14, MDB_TGT_R_EXPORT }, { "r15", KREG_R15, MDB_TGT_R_EXPORT }, - { "fsbase", KREG_FSBASE, MDB_TGT_R_EXPORT | MDB_TGT_R_PRIV }, - { "gsbase", KREG_GSBASE, MDB_TGT_R_EXPORT | MDB_TGT_R_PRIV }, - { "kgsbase", KREG_KGSBASE, MDB_TGT_R_EXPORT | MDB_TGT_R_PRIV }, { "ds", KREG_DS, MDB_TGT_R_EXPORT }, { "es", KREG_ES, MDB_TGT_R_EXPORT }, { "fs", KREG_FS, MDB_TGT_R_EXPORT }, @@ -134,10 +131,10 @@ mdb_amd64_printregs(const mdb_tgt_gregset_t *gregs) mdb_printf("%24s%%cs = 0x%04x\t%%ds = 0x%04x\t%%es = 0x%04x\n", " ", kregs[KREG_CS], kregs[KREG_DS], kregs[KREG_ES]); - mdb_printf("%%trapno = 0x%x\t\t%%fs = 0x%04x\tfsbase = 0x%0?p\n", - kregs[KREG_TRAPNO], (kregs[KREG_FS] & 0xffff), kregs[KREG_FSBASE]); - mdb_printf(" %%err = 0x%x\t\t%%gs = 0x%04x\tgsbase = 0x%0?p\n", - kregs[KREG_ERR], (kregs[KREG_GS] & 0xffff), kregs[KREG_GSBASE]); + mdb_printf("%%trapno = 0x%x\t\t%%fs = 0x%04x\t%%gs = 0x%04x\n", + kregs[KREG_TRAPNO], (kregs[KREG_FS] & 0xffff), + (kregs[KREG_GS] & 0xffff)); + mdb_printf(" %%err = 0x%x\n", kregs[KREG_ERR]); } diff --git a/usr/src/cmd/mdb/intel/mdb/mdb_kreg.h b/usr/src/cmd/mdb/intel/mdb/mdb_kreg.h index 3e7d79f462..4ba5fb567c 100644 --- a/usr/src/cmd/mdb/intel/mdb/mdb_kreg.h +++ b/usr/src/cmd/mdb/intel/mdb/mdb_kreg.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -29,6 +28,7 @@ #pragma ident "%Z%%M% %I% %E% SMI" +#include <sys/kdi_regs.h> #ifndef _ASM #include <sys/types.h> #endif @@ -37,51 +37,51 @@ extern "C" { #endif -#ifdef __amd64 -#define KREG_NGREG 31 #ifndef _ASM +#ifdef __amd64 typedef uint64_t kreg_t; -#endif /* !_ASM */ #else /* __amd64 */ -#define KREG_NGREG 21 -#ifndef _ASM typedef uint32_t kreg_t; -#endif /* !_ASM */ #endif /* __amd64 */ +#endif /* !_ASM */ + +#define KREG_NGREG KDIREG_NGREG + +/* + * The order of these registers corresponds to a slightly altered struct regs, + * in the order kmdb entry pushes onto the stack. + */ #ifdef __amd64 -#define KREG_SAVFP 0 -#define KREG_SAVPC 1 -#define KREG_RDI 2 -#define KREG_RSI 3 -#define KREG_RDX 4 -#define KREG_RCX 5 -#define KREG_R8 6 -#define KREG_R9 7 -#define KREG_RAX 8 -#define KREG_RBX 9 -#define KREG_RBP 10 -#define KREG_R10 11 -#define KREG_R11 12 -#define KREG_R12 13 -#define KREG_R13 14 -#define KREG_R14 15 -#define KREG_R15 16 -#define KREG_FSBASE 17 -#define KREG_GSBASE 18 -#define KREG_KGSBASE 19 -#define KREG_DS 20 -#define KREG_ES 21 -#define KREG_FS 22 -#define KREG_GS 23 -#define KREG_TRAPNO 24 -#define KREG_ERR 25 -#define KREG_RIP 26 -#define KREG_CS 27 -#define KREG_RFLAGS 28 -#define KREG_RSP 29 -#define KREG_SS 30 +#define KREG_SAVFP KDIREG_SAVFP +#define KREG_SAVPC KDIREG_SAVPC +#define KREG_RDI KDIREG_RDI +#define KREG_RSI KDIREG_RSI +#define KREG_RDX KDIREG_RDX +#define KREG_RCX KDIREG_RCX +#define KREG_R8 KDIREG_R8 +#define KREG_R9 KDIREG_R9 +#define KREG_RAX KDIREG_RAX +#define KREG_RBX KDIREG_RBX +#define KREG_RBP KDIREG_RBP +#define KREG_R10 KDIREG_R10 +#define KREG_R11 KDIREG_R11 +#define KREG_R12 KDIREG_R12 +#define KREG_R13 KDIREG_R13 +#define KREG_R14 KDIREG_R14 +#define KREG_R15 KDIREG_R15 +#define KREG_DS KDIREG_DS +#define KREG_ES KDIREG_ES +#define KREG_FS KDIREG_FS +#define KREG_GS KDIREG_GS +#define KREG_TRAPNO KDIREG_TRAPNO +#define KREG_ERR KDIREG_ERR +#define KREG_RIP KDIREG_RIP +#define KREG_CS KDIREG_CS +#define KREG_RFLAGS KDIREG_RFLAGS +#define KREG_RSP KDIREG_RSP +#define KREG_SS KDIREG_SS #define KREG_PC KREG_RIP #define KREG_SP KREG_RSP @@ -89,33 +89,27 @@ typedef uint32_t kreg_t; #else /* __amd64 */ -/* - * The order of these registers corresponds to a slightly altered struct regs. - * %ss appears first, and is followed by the remainder of the struct regs. This - * change is necessary to support kmdb state saving. - */ - -#define KREG_SAVFP 0 -#define KREG_SAVPC 1 -#define KREG_SS 2 -#define KREG_GS 3 -#define KREG_FS 4 -#define KREG_ES 5 -#define KREG_DS 6 -#define KREG_EDI 7 -#define KREG_ESI 8 -#define KREG_EBP 9 -#define KREG_ESP 10 -#define KREG_EBX 11 -#define KREG_EDX 12 -#define KREG_ECX 13 -#define KREG_EAX 14 -#define KREG_TRAPNO 15 -#define KREG_ERR 16 -#define KREG_EIP 17 -#define KREG_CS 18 -#define KREG_EFLAGS 19 -#define KREG_UESP 20 +#define KREG_SAVFP KDIREG_SAVFP +#define KREG_SAVPC KDIREG_SAVPC +#define KREG_SS KDIREG_SS +#define KREG_GS KDIREG_GS +#define KREG_FS KDIREG_FS +#define KREG_ES KDIREG_ES +#define KREG_DS KDIREG_DS +#define KREG_EDI KDIREG_EDI +#define KREG_ESI KDIREG_ESI +#define KREG_EBP KDIREG_EBP +#define KREG_ESP KDIREG_ESP +#define KREG_EBX KDIREG_EBX +#define KREG_EDX KDIREG_EDX +#define KREG_ECX KDIREG_ECX +#define KREG_EAX KDIREG_EAX +#define KREG_TRAPNO KDIREG_TRAPNO +#define KREG_ERR KDIREG_ERR +#define KREG_EIP KDIREG_EIP +#define KREG_CS KDIREG_CS +#define KREG_EFLAGS KDIREG_EFLAGS +#define KREG_UESP KDIREG_UESP #define KREG_PC KREG_EIP #define KREG_SP KREG_ESP @@ -174,8 +168,6 @@ typedef uint32_t kreg_t; #define KREG_EFLAGS_CF_MASK 0x00000001 #define KREG_EFLAGS_CF_SHIFT 0 -#define KREG_MAXWPIDX 3 - /* %dr7 */ #define KREG_DRCTL_WP_BASESHIFT 16 #define KREG_DRCTL_WP_INCRSHIFT 4 @@ -199,12 +191,6 @@ typedef uint32_t kreg_t; (3 << (KREG_DRCTL_WPEN_INCRSHIFT * (n))) #define KREG_DRCTL_WPEN(n) KREG_DRCTL_WPEN_MASK(n) -#define KREG_DRCTL_WPALLEN_MASK 0x000000ff - -#define KREG_DRCTL_GD_MASK 0x00002000 - -#define KREG_DRCTL_RESERVED 0x00000700 - /* %dr6 */ #define KREG_DRSTAT_BT_MASK 0x00008000 #define KREG_DRSTAT_BS_MASK 0x00004000 @@ -212,8 +198,6 @@ typedef uint32_t kreg_t; #define KREG_DRSTAT_WP_MASK(n) (1 << (n)) -#define KREG_DRSTAT_RESERVED 0xffff0ff0 - #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/mdb/sparc/kmdb/kaif.c b/usr/src/cmd/mdb/sparc/kmdb/kaif.c index 92eaec51f1..729d1fdd1d 100644 --- a/usr/src/cmd/mdb/sparc/kmdb/kaif.c +++ b/usr/src/cmd/mdb/sparc/kmdb/kaif.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -875,14 +875,6 @@ kaif_mod_unloading(struct modctl *modp) kaif_modchg_cb(modp, 0); } -/*ARGSUSED*/ -int -kaif_memrange_add(caddr_t base, size_t len) -{ - /* We don't support multiple memory ranges on SPARC */ - return (set_errno(ENOTSUP)); -} - void kaif_trap_set_debugger(void) { @@ -1017,6 +1009,5 @@ dpi_ops_t kmdb_dpi_ops = { kaif_step, kaif_call, kaif_dump_crumbs, - kaif_memrange_add, kaif_kernpanic }; diff --git a/usr/src/cmd/mdb/sparc/kmdb/kaif.h b/usr/src/cmd/mdb/sparc/kmdb/kaif.h index 98d196192c..50445df8a3 100644 --- a/usr/src/cmd/mdb/sparc/kmdb/kaif.h +++ b/usr/src/cmd/mdb/sparc/kmdb/kaif.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,16 +41,10 @@ extern "C" { #endif -#define KAIF_MASTER_CPUID_UNSET -1 - #define KAIF_CPU_STATE_NONE 0 #define KAIF_CPU_STATE_MASTER 1 #define KAIF_CPU_STATE_SLAVE 2 -#define KAIF_CPU_CMD_RESUME 0 -#define KAIF_CPU_CMD_RESUME_MASTER 1 -#define KAIF_CPU_CMD_SWITCH 2 - #define KAIF_LSUCTL_VWAPT_MASK (LSU_VM|LSU_VR|LSU_VW) #define KAIF_LSUCTL_PWAPT_MASK (LSU_PM|LSU_PR|LSU_PW) #define KAIF_LSUCTL_WAPT_MASK (LSU_PM|LSU_VM|LSU_PR|LSU_PW|LSU_VR|LSU_VW) @@ -111,8 +105,6 @@ extern void kaif_slave_entry(void); extern void kaif_prom_rearm(void); extern void kaif_debugger_entry(kaif_cpusave_t *); -extern int kaif_memrange_add(caddr_t, size_t); - extern void kaif_slave_loop_barrier(void); #endif diff --git a/usr/src/cmd/mdb/sparc/kmdb/kaif_activate.c b/usr/src/cmd/mdb/sparc/kmdb/kaif_activate.c index a17431d53f..e7bcf7e68f 100644 --- a/usr/src/cmd/mdb/sparc/kmdb/kaif_activate.c +++ b/usr/src/cmd/mdb/sparc/kmdb/kaif_activate.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -278,18 +278,17 @@ kaif_cpr_restart(void) } static kdi_debugvec_t kaif_dvec = { - kaif_enter, - kaif_cpu_init, - NULL, /* dv_kctl_cpu_init */ - kaif_vmready, NULL, /* dv_kctl_vmready */ NULL, /* dv_kctl_memavail */ - kaif_memrange_add, - kaif_cpr_restart, NULL, /* dv_kctl_modavail */ NULL, /* dv_kctl_thravail */ + kaif_vmready, + NULL, /* dv_memavail */ kaif_mod_loaded, - kaif_mod_unloading + kaif_mod_unloading, + NULL, /* dv_kctl_cpu_init */ + kaif_cpu_init, + kaif_cpr_restart }; /*ARGSUSED1*/ diff --git a/usr/src/cmd/mdb/sparc/kmdb/kaif_enter.s b/usr/src/cmd/mdb/sparc/kmdb/kaif_enter.s deleted file mode 100644 index 4275773a71..0000000000 --- a/usr/src/cmd/mdb/sparc/kmdb/kaif_enter.s +++ /dev/null @@ -1,48 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/asm_linkage.h> - -#if defined(__lint) -#include <kmdb/kaif.h> -#endif /* __lint */ - -#if defined(__lint) -void -kaif_enter(void) -{ -} -#else /* __lint */ - - ENTRY(kaif_enter) - t ST_KMDB_TRAP - retl - nop - SET_SIZE(kaif_enter) - -#endif diff --git a/usr/src/cmd/mdb/sparc/kmdb/kctl/kctl_isadep.c b/usr/src/cmd/mdb/sparc/kmdb/kctl/kctl_isadep.c index 5ae674e26e..f50016389c 100644 --- a/usr/src/cmd/mdb/sparc/kmdb/kctl/kctl_isadep.c +++ b/usr/src/cmd/mdb/sparc/kmdb/kctl/kctl_isadep.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -195,18 +195,11 @@ kctl_depreactivate_isadep(void) kdi_watchdog_restore(); } -int +void kctl_activate_isadep(kdi_debugvec_t *dvec) { dvec->dv_kctl_cpu_init = kctl_cpu_init; dvec->dv_kctl_vmready = kctl_ttable_init; - - return (0); -} - -void -kctl_deactivate_isadep(void) -{ } void diff --git a/usr/src/cmd/mdb/sparc/kmdb/kmdb_kdi_isadep.c b/usr/src/cmd/mdb/sparc/kmdb/kmdb_kdi_isadep.c index c82095ada5..15ceeeff1f 100644 --- a/usr/src/cmd/mdb/sparc/kmdb/kmdb_kdi_isadep.c +++ b/usr/src/cmd/mdb/sparc/kmdb/kmdb_kdi_isadep.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,7 +32,7 @@ #include <sys/types.h> #include <sys/kdi_impl.h> -#include <kmdb/kmdb_kdi_impl.h> +#include <kmdb/kaif.h> #include <kmdb/kmdb_dpi.h> #include <kmdb/kmdb_promif.h> #include <mdb/mdb_debug.h> @@ -49,6 +49,8 @@ static size_t kdi_icache_linesize; static uint_t kdi_max_cpu_freq; static uint_t kdi_sticks_per_usec; +/* XXX needs to go into a header */ + void kdi_usecwait(clock_t n) { @@ -139,36 +141,6 @@ kdi_init_cpus_cb(pnode_t node, void *arg, void *result) return (0); } -void -kdi_cpu_init(void) -{ - kdi_dcache_size = kdi_dcache_linesize = - kdi_icache_size = kdi_icache_linesize = 0; - - kdi_max_cpu_freq = kdi_sticks_per_usec = 0; - - mdb_dprintf(MDB_DBG_KDI, "Initializing CPUs\n"); - - kmdb_prom_walk_cpus(kdi_init_cpus_cb, NULL, NULL); - - /* - * If we can't find one, guess high. The CPU frequency is going to be - * used to determine the length of various delays, such as the mondo - * interrupt retry delay. Too long is generally better than too short. - */ - if (kdi_max_cpu_freq == 0) { - mdb_dprintf(MDB_DBG_KDI, "No CPU freq found - assuming " - "500MHz\n"); - kdi_max_cpu_freq = 500 * MICROSEC; - } - - kdi_sticks_per_usec = - MAX((kdi_max_cpu_freq + (MICROSEC - 1)) / MICROSEC, 1); - - mdb.m_kdi->mkdi_cpu_init(kdi_dcache_size, kdi_dcache_linesize, - kdi_icache_size, kdi_icache_linesize); -} - /* * Called on an individual CPU. Tries to send it off to the state saver if it * hasn't already entered the debugger. Returns non-zero if it *fails* to stop @@ -217,12 +189,13 @@ kdi_report_unhalted(int cpuid, void *junk) /*ARGSUSED*/ void -kmdb_kdi_stop_other_cpus(int my_cpuid, void (*slave_saver)(void)) +kmdb_kdi_stop_slaves(int my_cpuid, int doxc) { int i; for (i = 0; i < KDI_XC_RETRIES; i++) { - if (kdi_cpu_ready_iter(kdi_halt_cpu, (void *)slave_saver) == 0) + if (kdi_cpu_ready_iter(kdi_halt_cpu, + (void *)kaif_slave_entry) == 0) break; kdi_usecwait(2000); @@ -230,6 +203,16 @@ kmdb_kdi_stop_other_cpus(int my_cpuid, void (*slave_saver)(void)) (void) kdi_cpu_ready_iter(kdi_report_unhalted, NULL); } +void +kmdb_kdi_start_slaves(void) +{ +} + +void +kmdb_kdi_slave_wait(void) +{ +} + int kmdb_kdi_get_stick(uint64_t *stickp) { @@ -257,4 +240,29 @@ kmdb_kdi_kernpanic(struct regs *regs, uint_t tt) void kmdb_kdi_init_isadep(kdi_t *kdi, kmdb_auxv_t *kav) { + kdi_dcache_size = kdi_dcache_linesize = + kdi_icache_size = kdi_icache_linesize = 0; + + kdi_max_cpu_freq = kdi_sticks_per_usec = 0; + + mdb_dprintf(MDB_DBG_KDI, "Initializing CPUs\n"); + + kmdb_prom_walk_cpus(kdi_init_cpus_cb, NULL, NULL); + + /* + * If we can't find one, guess high. The CPU frequency is going to be + * used to determine the length of various delays, such as the mondo + * interrupt retry delay. Too long is generally better than too short. + */ + if (kdi_max_cpu_freq == 0) { + mdb_dprintf(MDB_DBG_KDI, "No CPU freq found - assuming " + "500MHz\n"); + kdi_max_cpu_freq = 500 * MICROSEC; + } + + kdi_sticks_per_usec = + MAX((kdi_max_cpu_freq + (MICROSEC - 1)) / MICROSEC, 1); + + mdb.m_kdi->mkdi_cpu_init(kdi_dcache_size, kdi_dcache_linesize, + kdi_icache_size, kdi_icache_linesize); } diff --git a/usr/src/cmd/mdb/sparc/v9/genunix/Makefile b/usr/src/cmd/mdb/sparc/v9/genunix/Makefile index 2cf7038d9e..564244d298 100644 --- a/usr/src/cmd/mdb/sparc/v9/genunix/Makefile +++ b/usr/src/cmd/mdb/sparc/v9/genunix/Makefile @@ -29,43 +29,10 @@ MODULE = genunix.so MDBTGT = kvm +include ../../../common/modules/genunix/Makefile.files + COMMONSRCS = \ - avl.c \ - bio.c \ - contract.c \ - cpupart.c \ - ctxop.c \ - cyclic.c \ - devinfo.c \ - findstack.c \ - fm.c \ - genunix.c \ - group.c \ - kgrep.c \ - kmem.c \ - ldi.c \ - leaky.c \ - leaky_subr.c \ - lgrp.c \ - list.c \ - log.c \ - mdi.c \ - memory.c \ - mmd.c \ - modhash.c \ - ndievents.c \ - net.c \ - nvpair.c \ - pg.c \ - rctl.c \ - sobj.c \ - streams.c \ - sysevent.c \ - thread.c \ - tsd.c \ - tsol.c \ - vfs.c \ - zone.c + $(GENUNIX_SRCS) KMODSRCS = \ $(COMMONSRCS) diff --git a/usr/src/cmd/mdb/sun4u/Makefile.kmdb b/usr/src/cmd/mdb/sun4u/Makefile.kmdb index 43471fe808..152e0e736b 100644 --- a/usr/src/cmd/mdb/sun4u/Makefile.kmdb +++ b/usr/src/cmd/mdb/sun4u/Makefile.kmdb @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -63,7 +62,6 @@ KMDBSRCS += \ kvm_isadep.c KMDBML += \ - kaif_enter.s \ kmdb_asmutil.s KCTLSRCS += \ diff --git a/usr/src/cmd/mdb/sun4v/Makefile.kmdb b/usr/src/cmd/mdb/sun4v/Makefile.kmdb index d307d5f6f8..52ea632d90 100644 --- a/usr/src/cmd/mdb/sun4v/Makefile.kmdb +++ b/usr/src/cmd/mdb/sun4v/Makefile.kmdb @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -71,7 +71,6 @@ KMDBSRCS += \ kvm_isadep.c KMDBML += \ - kaif_enter.s \ kmdb_asmutil.s KCTLSRCS += \ diff --git a/usr/src/cmd/prtdiag/Makefile b/usr/src/cmd/prtdiag/Makefile index 2265dbd099..5a094f0213 100644 --- a/usr/src/cmd/prtdiag/Makefile +++ b/usr/src/cmd/prtdiag/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -42,10 +41,6 @@ _msg := TARGET = _msg all install clean clobber lint _msg: $(SUBDIRS) -install: $(SUBDIRS) - $(RM) $(ROOTUSRSBINPROG) - $(LN) $(PLATEXEC) $(ROOTUSRSBINPROG) - $(SUBDIRS): FRC @cd $@; pwd; $(MAKE) $(TARGET) diff --git a/usr/src/cmd/prtdiag/Makefile.com b/usr/src/cmd/prtdiag/Makefile.com index 732ab9e7eb..46d21d2338 100644 --- a/usr/src/cmd/prtdiag/Makefile.com +++ b/usr/src/cmd/prtdiag/Makefile.com @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -37,13 +37,13 @@ DIRMODE = 755 OWNER = root GROUP = sys -LINTFILES = $(OBJS:%.o=%.ln) -POFILE = prtdiag_$(PLATFORM).po +LINT_OBJS = $(OBJS:%.o=%.ln) +POFILE = prtdiag.po POFILES = $(OBJS:%.o=%.po) LIBPRTDIAG = $(SRC)/lib/libprtdiag -.PARALLEL: $(OBJS) $(LINTFILES) +.PARALLEL: $(OBJS) $(LINT_OBJS) %.o: %.c $(COMPILE.c) -o $@ $< diff --git a/usr/src/cmd/prtdiag/i386/Makefile b/usr/src/cmd/prtdiag/i386/Makefile index 985fd3411a..10bbed0d40 100644 --- a/usr/src/cmd/prtdiag/i386/Makefile +++ b/usr/src/cmd/prtdiag/i386/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -19,27 +18,22 @@ # # CDDL HEADER END # - # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" -SUBDIRS = i86pc +SRCDIR = .. -all := TARGET = all -install := TARGET = install -clean := TARGET = clean -clobber := TARGET = clobber -lint := TARGET = lint -_msg := TARGET = _msg +include $(SRCDIR)/Makefile.com -.KEEP_STATE: +OBJS += smbios.o +LDLIBS += -lsmbios -all install clean clobber lint _msg: $(SUBDIRS) +.KEEP_STATE: -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) +all: $(PROG) -FRC: +include $(SRCDIR)/i386/Makefile.targ diff --git a/usr/src/cmd/prtdiag/i386/Makefile.targ b/usr/src/cmd/prtdiag/i386/Makefile.targ new file mode 100644 index 0000000000..61b0ad98da --- /dev/null +++ b/usr/src/cmd/prtdiag/i386/Makefile.targ @@ -0,0 +1,46 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" + +install: all $(ROOTUSRSBIN) $(ROOTUSRSBINPROG) + +$(PROG): $(OBJS) + $(LINK.c) -o $@ $(OBJS) $(LDLIBS) + $(POST_PROCESS) + +clean: + -$(RM) $(OBJS) + -$(RM) $(LINT_OBJS) + -$(RM) $(PROG) + +lint: $(LINT_OBJS) + $(LINT.c) $(LINT_OBJS) $(LDLIBS) + +$(POFILE): $(POFILES) + $(RM) $@ + cat $(POFILES) > $@ + +include $(SRCDIR)/../Makefile.targ diff --git a/usr/src/cmd/prtdiag/i386/i86pc/smbios.c b/usr/src/cmd/prtdiag/i386/smbios.c index 819cd04551..819cd04551 100644 --- a/usr/src/cmd/prtdiag/i386/i86pc/smbios.c +++ b/usr/src/cmd/prtdiag/i386/smbios.c diff --git a/usr/src/cmd/prtdiag/Makefile.targ b/usr/src/cmd/prtdiag/sparc/Makefile.targ index 4cc5938f24..19a930a8ec 100644 --- a/usr/src/cmd/prtdiag/Makefile.targ +++ b/usr/src/cmd/prtdiag/sparc/Makefile.targ @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -21,22 +20,24 @@ # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" install: all $(USR_PSM_SBIN_PROG) $(USR_PSM_SBIN_PROG_LINKS) + $(RM) $(ROOTUSRSBINPROG) + $(LN) $(PLATEXEC) $(ROOTUSRSBINPROG) $(PROG): $(OBJS) $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(POST_PROCESS) clean: - -$(RM) $(OBJS) $(LINTFILES) + -$(RM) $(OBJS) $(LINT_OBJS) $(PROG) -lint: $(LINTFILES) - $(LINT) $(LINTFILES) $(LDLIBS) +lint: $(LINT_OBJS) + $(LINT) $(LINT_OBJS) $(LDLIBS) $(POFILE): $(POFILES) $(RM) $@ diff --git a/usr/src/cmd/prtdiag/sparc/sun4u/Makefile b/usr/src/cmd/prtdiag/sparc/sun4u/Makefile index 17f6f71ac7..c7c6157dad 100644 --- a/usr/src/cmd/prtdiag/sparc/sun4u/Makefile +++ b/usr/src/cmd/prtdiag/sparc/sun4u/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -48,4 +47,4 @@ LINTFLAGS += -u all: $(LIBPRTDIAG) $(PROG) -include $(SRCDIR)/Makefile.targ +include $(SRCDIR)/sparc/Makefile.targ diff --git a/usr/src/cmd/prtdiag/sparc/sun4v/Makefile b/usr/src/cmd/prtdiag/sparc/sun4v/Makefile index 04deb33a76..1da627801a 100644 --- a/usr/src/cmd/prtdiag/sparc/sun4v/Makefile +++ b/usr/src/cmd/prtdiag/sparc/sun4v/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -48,4 +47,4 @@ LINTFLAGS += -u all: $(LIBPRTDIAG) $(PROG) -include $(SRCDIR)/Makefile.targ +include $(SRCDIR)/sparc/Makefile.targ diff --git a/usr/src/cmd/svc/profile/Makefile b/usr/src/cmd/svc/profile/Makefile index d193399b68..18b1e40f87 100644 --- a/usr/src/cmd/svc/profile/Makefile +++ b/usr/src/cmd/svc/profile/Makefile @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -50,7 +50,6 @@ PROFILESRCS = \ platform_SUNW,Sun-Fire.xml \ platform_SUNW,Ultra-Enterprise-10000.xml \ platform_SUNW,UltraSPARC-IIi-Netract.xml \ - platform_i86pc.xml \ platform_none.xml \ platform_sun4v.xml diff --git a/usr/src/cmd/svc/profile/platform_i86pc.xml b/usr/src/cmd/svc/profile/platform_i86pc.xml deleted file mode 100644 index 3c196487c1..0000000000 --- a/usr/src/cmd/svc/profile/platform_i86pc.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version='1.0'?> -<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'> -<!-- - Copyright 2005 Sun Microsystems, Inc. All rights reserved. - Use is subject to license terms. - - CDDL HEADER START - - The contents of this file are subject to the terms of the - Common Development and Distribution License, Version 1.0 only - (the "License"). You may not use this file except in compliance - with the License. - - You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - or http://www.opensolaris.org/os/licensing. - See the License for the specific language governing permissions - and limitations under the License. - - When distributing Covered Code, include this CDDL HEADER in each - file and include the License file at usr/src/OPENSOLARIS.LICENSE. - If applicable, add the following below this CDDL HEADER, with the - fields enclosed by brackets "[]" replaced with your own identifying - information: Portions Copyright [yyyy] [name of copyright owner] - - CDDL HEADER END - - ident "%Z%%M% %I% %E% SMI" - - NOTE: This service profile is not editable; its contents will be - overwritten by package or patch operations, including operating - system upgrade. - - Platform service profile for the i86pc platform. ---> -<service_bundle type='profile' name='i86pc'> - <service name='platform/i86pc/eeprom' version='1' type='service'> - <instance name='default' enabled='true'/> - </service> -</service_bundle> diff --git a/usr/src/common/elfcap/elfcap.c b/usr/src/common/elfcap/elfcap.c index 67be6eb882..f3262a2cc3 100644 --- a/usr/src/common/elfcap/elfcap.c +++ b/usr/src/common/elfcap/elfcap.c @@ -18,10 +18,12 @@ * * CDDL HEADER END */ + /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ + #pragma ident "%Z%%M% %I% %E% SMI" /* LINTLIBRARY */ @@ -144,6 +146,8 @@ static const char Hw1_i_pause[] = "PAUSE"; static const char Hw1_i_sse3[] = "SSE3"; static const char Hw1_i_mon[] = "MON"; static const char Hw1_i_cx16[] = "CX16"; +static const char Hw1_i_ahf[] = "AHF"; +static const char Hw1_i_tscp[] = "TSCP"; #elif CAP_LOWERCASE static const char Hw1_i_fpu[] = "fpu"; static const char Hw1_i_tsc[] = "tsc"; @@ -162,6 +166,8 @@ static const char Hw1_i_pause[] = "pause"; static const char Hw1_i_sse3[] = "sse3"; static const char Hw1_i_mon[] = "mon"; static const char Hw1_i_cx16[] = "cx16"; +static const char Hw1_i_ahf[] = "ahf"; +static const char Hw1_i_tscp[] = "tscp"; #else #error "Hardware Capabilities (intel) - what case do you want?" #endif @@ -189,12 +195,14 @@ static const Cap_desc hw1_i[] = { { AV_386_PAUSE, Hw1_i_pause, sizeof (Hw1_i_pause) - 1 }, { AV_386_SSE3, Hw1_i_sse3, sizeof (Hw1_i_sse3) - 1 }, { AV_386_MON, Hw1_i_mon, sizeof (Hw1_i_mon) - 1 }, - { AV_386_CX16, Hw1_i_cx16, sizeof (Hw1_i_cx16) - 1 } + { AV_386_CX16, Hw1_i_cx16, sizeof (Hw1_i_cx16) - 1 }, + { AV_386_AHF, Hw1_i_ahf, sizeof (Hw1_i_ahf) - 1 }, + { AV_386_TSCP, Hw1_i_tscp, sizeof (Hw1_i_tscp) - 1 } }; static const uint_t hw1_i_num = sizeof (hw1_i) / sizeof (Cap_desc); /* - * Concatenate a token to the string buffer. This can be a capailities token + * Concatenate a token to the string buffer. This can be a capabilities token * or a separator token. */ static int diff --git a/usr/src/common/fs/decompress.c b/usr/src/common/fs/decompress.c new file mode 100644 index 0000000000..8c78302c6f --- /dev/null +++ b/usr/src/common/fs/decompress.c @@ -0,0 +1,308 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Decompression module for stand alone file systems. + */ + +#include <sys/param.h> +#include <sys/sysmacros.h> +#include <sys/vnode.h> +#include <sys/bootvfs.h> +#include <sys/filep.h> +#include <zmod/zlib.h> + +#ifdef _BOOT +#include "../common/util.h" +#else +#include <sys/sunddi.h> +#endif + +#define MAX_DECOMP_BUFS 8 +#define GZIP_ID_BYTE_1 0x1f +#define GZIP_ID_BYTE_2 0x8b +#define GZIP_CM_DEFLATE 0x08 +#define SEEKBUFSIZE 8192 + +#ifdef _BOOT +#define dprintf if (cf_debug) printf +#else +#define dprintf if (cf_debug) printf + +#endif + +extern int bootrd_debug; +extern void *bkmem_alloc(size_t); +extern void bkmem_free(void *, size_t); + +caddr_t scratch_bufs[MAX_DECOMP_BUFS]; /* array of free scratch mem bufs */ +int decomp_bufcnt; /* total no, of allocated decomp bufs */ +int free_dcomp_bufs; /* no. of free decomp bufs */ +char seek_scrbuf[SEEKBUFSIZE]; /* buffer for seeking */ +int cf_debug; /* non-zero enables debug prints */ + +void * +cf_alloc(void *opaque, unsigned int items, unsigned int size) +{ + fileid_t *filep; + unsigned int nbytes; + caddr_t ptr; + + filep = (fileid_t *)opaque; + nbytes = roundup(items * size, sizeof (long)); + if (nbytes > (DECOMP_BUFSIZE - filep->fi_dcscrused)) { + ptr = bkmem_alloc(nbytes); + } else { + ptr = &filep->fi_dcscrbuf[filep->fi_dcscrused]; + filep->fi_dcscrused += nbytes; + } + bzero(ptr, nbytes); + return (ptr); +} + +/* + * Decompression scratch memory free routine, does nothing since we free + * the entire scratch area all at once on file close. + */ +/* ARGSUSED */ +void +cf_free(void *opaque, void *addr) +{ +} + +/* + * Read the first block of the file described by filep and determine if + * the file is gzip-compressed. If so, the compressed flag will be set + * in the fileid_t struct pointed to by filep and it will be initialized + * for doing decompression on reads to the file. + */ +int +cf_check_compressed(fileid_t *filep) +{ + unsigned char *filebytes; + z_stream *zsp; + + filep->fi_offset = 0; + if ((filep->fi_getblock)(filep) == -1) + return (-1); + filep->fi_offset = 0; + filep->fi_count = 0; + filep->fi_cfoff = 0; + filebytes = (unsigned char *)filep->fi_memp; + if (filebytes[0] != GZIP_ID_BYTE_1 || filebytes[1] != GZIP_ID_BYTE_2 || + filebytes[2] != GZIP_CM_DEFLATE) + return (0); /* not compressed */ + filep->fi_flags |= FI_COMPRESSED; + + dprintf("file %s is compressed\n", filep->fi_path); + + /* + * Allocate decompress scratch buffer + */ + if (free_dcomp_bufs) { + filep->fi_dcscrbuf = scratch_bufs[--free_dcomp_bufs]; + } else { + filep->fi_dcscrbuf = bkmem_alloc(DECOMP_BUFSIZE); + decomp_bufcnt++; + } + filep->fi_dcscrused = 0; + zsp = bkmem_alloc(sizeof (*zsp)); + filep->fi_dcstream = zsp; + /* + * Initialize the decompression stream + */ + bzero(zsp, sizeof (*zsp)); + zsp->opaque = filep; + zsp->zalloc = cf_alloc; + zsp->zfree = cf_free; + zsp->avail_in = 0; + zsp->next_in = NULL; + zsp->avail_out = 0; + zsp->next_out = NULL; + if (inflateInit2(zsp, -MAX_WBITS) != Z_OK) + return (-1); + return (0); +} + +/* + * If the file described by fileid_t struct at *filep is compressed + * free any resources associated with the decompression. (decompression + * buffer, etc.). + */ +void +cf_close(fileid_t *filep) +{ + if ((filep->fi_flags & FI_COMPRESSED) == 0) + return; + dprintf("cf_close: %s\n", filep->fi_path); + (void) inflateEnd(filep->fi_dcstream); + bkmem_free(filep->fi_dcstream, sizeof (z_stream)); + if (free_dcomp_bufs == MAX_DECOMP_BUFS) { + bkmem_free(filep->fi_dcscrbuf, DECOMP_BUFSIZE); + } else { + scratch_bufs[free_dcomp_bufs++] = filep->fi_dcscrbuf; + } +} + +void +cf_rewind(fileid_t *filep) +{ + z_stream *zsp; + + dprintf("cf_rewind: %s\n", filep->fi_path); + zsp = filep->fi_dcstream; + zsp->avail_in = 0; + zsp->next_in = NULL; + (void) inflateReset(zsp); + filep->fi_cfoff = 0; +} + +#define FLG_FHCRC 0x02 /* crc field present */ +#define FLG_FEXTRA 0x04 /* "extra" field present */ +#define FLG_FNAME 0x08 /* file name field present */ +#define FLG_FCOMMENT 0x10 /* comment field present */ + +/* + * Calculate the header length of a gzip compressed file + */ +static int +cf_headerlen(unsigned char *hp) +{ + unsigned char flag; + int xlen, hlen = 0; + + hlen += 3; /* skip ID bytes and compression method */ + flag = hp[hlen]; + hlen += 7; /* skip flag, mtime(4 bytes), xfl, and os */ + if (flag & FLG_FEXTRA) { + xlen = hp[hlen++]; + xlen += hp[hlen++] << 8; + hlen += xlen; /* skip extra field */ + } + if (flag & FLG_FNAME) + hlen += strlen((char *)&hp[hlen]) + 1; /* skip file name */ + if (flag & FLG_FCOMMENT) + hlen += strlen((char *)&hp[hlen]) + 1; /* skip comment */ + if (flag & FLG_FHCRC) + hlen += 2; /* skip crc */ + return (hlen); +} + +/* + * Read at the current uncompressed offset from the compressed file described + * by *filep. Will return decompressed data. + */ +int +cf_read(fileid_t *filep, caddr_t buf, size_t count) +{ + z_stream *zsp; + struct inode *ip; + int err = Z_OK; + int hlen, infbytes; + off_t soff; + caddr_t smemp; + + dprintf("cf_read: %s ", filep->fi_path); + dprintf("%lx bytes\n", count); + zsp = filep->fi_dcstream; + ip = filep->fi_inode; + dprintf(" reading at offset %lx\n", zsp->total_out); + zsp->next_out = (unsigned char *)buf; + zsp->avail_out = count; + while (zsp->avail_out != 0) { + if (zsp->avail_in == 0 && filep->fi_cfoff < ip->i_size) { + /* + * read a block of the file to inflate + */ + soff = filep->fi_offset; + smemp = filep->fi_memp; + filep->fi_memp = NULL; + filep->fi_offset = filep->fi_cfoff; + filep->fi_count = 0; + if ((*filep->fi_getblock)(filep) == -1) + return (-1); + filep->fi_offset = soff; + zsp->next_in = (unsigned char *)filep->fi_memp; + zsp->avail_in = filep->fi_count; + filep->fi_memp = smemp; + /* + * If we are reading the first block of the file, we + * need to skip over the header bytes before inflating + */ + if (filep->fi_cfoff == 0) { + hlen = cf_headerlen(zsp->next_in); + zsp->next_in += hlen; + zsp->avail_in -= hlen; + } + filep->fi_cfoff += filep->fi_count; + } + infbytes = zsp->avail_out; + dprintf("attempting inflate of %x bytes to buf at: %lx\n", + zsp->avail_out, (unsigned long)zsp->next_out); + err = inflate(zsp, Z_NO_FLUSH); + infbytes -= zsp->avail_out; + dprintf("inflated %x bytes, errcode=%d\n", infbytes, err); + /* + * break out if we hit end of the compressed file + * or the end of the compressed byte stream + */ + if (filep->fi_cfoff >= ip->i_size || err == Z_STREAM_END) + break; + } + dprintf("cf_read: returned %lx bytes\n", count - zsp->avail_out); + return (count - zsp->avail_out); +} + +/* + * Seek to the location specified by addr + */ +void +cf_seek(fileid_t *filep, off_t addr, int whence) +{ + z_stream *zsp; + int readsz; + + dprintf("cf_seek: %s ", filep->fi_path); + dprintf("to %lx\n", addr); + zsp = filep->fi_dcstream; + if (whence == SEEK_CUR) + addr += zsp->total_out; + /* + * To seek backwards, must rewind and seek forwards + */ + if (addr < zsp->total_out) { + cf_rewind(filep); + filep->fi_offset = 0; + } else { + addr -= zsp->total_out; + } + while (addr > 0) { + readsz = MIN(addr, SEEKBUFSIZE); + (void) cf_read(filep, seek_scrbuf, readsz); + addr -= readsz; + } +} diff --git a/usr/src/common/fs/hsfs.c b/usr/src/common/fs/hsfs.c index b625c0aba9..9efe265cfa 100644 --- a/usr/src/common/fs/hsfs.c +++ b/usr/src/common/fs/hsfs.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -84,6 +84,10 @@ extern void kobj_printf(char *, ...); extern int bootrd_debug; extern void *bkmem_alloc(size_t); extern void bkmem_free(void *, size_t); +extern int cf_check_compressed(fileid_t *); +extern void cf_close(fileid_t *); +extern void cf_seek(fileid_t *, off_t, int); +extern int cf_read(fileid_t *, caddr_t, size_t); struct dirstuff { int loc; @@ -353,30 +357,39 @@ bhsfs_read(int fd, caddr_t buf, size_t count) struct inode *ip; caddr_t n; - dprintf("bhsfs_read %d, count 0x%lx\n", fd, count); + dprintf("bhsfs_read %d, ", fd); + dprintf("count 0x%lx\n", count); filep = find_fp(fd); if (filep == NULL) return (-1); ip = filep->fi_inode; n = buf; - if (filep->fi_offset + count > ip->i_size) + if ((filep->fi_flags & FI_COMPRESSED) == 0 && + filep->fi_offset + count > ip->i_size) count = ip->i_size - filep->fi_offset; if ((i = count) <= 0) return (0); while (i > 0) { - if (filep->fi_count == 0) { - if (getblock(filep) == -1) - return (0); + if (filep->fi_flags & FI_COMPRESSED) { + if ((j = cf_read(filep, buf, count)) < 0) + return (0); /* encountered an error */ + if (j < i) + i = j; /* short read, must have hit EOF */ + } else { + if (filep->fi_count == 0) { + if (getblock(filep) == -1) + return (0); + } + j = MIN(i, filep->fi_count); + bcopy(filep->fi_memp, buf, (uint_t)j); } - j = MIN(i, filep->fi_count); - bcopy(filep->fi_memp, buf, (uint_t)j); - buf += j; filep->fi_memp += j; filep->fi_offset += j; filep->fi_count -= j; + buf += j; i -= j; } @@ -477,6 +490,8 @@ bhsfs_open(char *str, int flags) (void) strcpy(filep->fi_path, str); filep->fi_inode = NULL; bzero(filep->fi_buf, MAXBSIZE); + filep->fi_getblock = getblock; + filep->fi_flags = 0; ino = find(str, filep); if (ino == 0) { @@ -489,6 +504,8 @@ bhsfs_open(char *str, int flags) filep->fi_count = 0; filep->fi_memp = 0; + if (cf_check_compressed(filep) != 0) + return (-1); dprintf("open done\n"); return (filep->fi_filedes); } @@ -503,10 +520,11 @@ bhsfs_close(int fd) return (-1); if (filep->fi_taken == 0 || filep == head) { - printf("File descripter %d no allocated!\n", fd); + printf("File descripter %d not allocated!\n", fd); return (-1); } + cf_close(filep); /* unlink and deallocate node */ filep->fi_forw->fi_back = filep->fi_back; filep->fi_back->fi_forw = filep->fi_forw; @@ -541,24 +559,29 @@ bhsfs_lseek(int fd, off_t addr, int whence) { fileid_t *filep; - dprintf("lseek %d, off = %lx\n", fd, addr); + dprintf("lseek %d, ", fd); + dprintf("off = %lx\n", addr); if (!(filep = find_fp(fd))) return (-1); - switch (whence) { - case SEEK_CUR: - filep->fi_offset += addr; - break; - case SEEK_SET: - filep->fi_offset = addr; - break; - default: - case SEEK_END: - printf("lseek(): invalid whence value %d\n", whence); - break; + if (filep->fi_flags & FI_COMPRESSED) { + cf_seek(filep, addr, whence); + } else { + switch (whence) { + case SEEK_CUR: + filep->fi_offset += addr; + break; + case SEEK_SET: + filep->fi_offset = addr; + break; + default: + case SEEK_END: + printf("lseek(): invalid whence value %d\n", whence); + break; + } + filep->fi_blocknum = addr / DEV_BSIZE; } - filep->fi_blocknum = addr / DEV_BSIZE; filep->fi_count = 0; return (0); } @@ -590,6 +613,11 @@ bhsfs_fstat(int fd, struct bootstat *stp) default: break; } + /* + * NOTE: this size will be the compressed size for a compressed file + * This could confuse the caller since we decompress the file behind + * the scenes when the file is read. + */ stp->st_size = ip->i_size; /* file times */ diff --git a/usr/src/common/fs/ufsops.c b/usr/src/common/fs/ufsops.c index ba0a60dbdd..8cdd5d6e79 100644 --- a/usr/src/common/fs/ufsops.c +++ b/usr/src/common/fs/ufsops.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -43,6 +43,10 @@ extern void *bkmem_alloc(size_t); extern void bkmem_free(void *, size_t); +extern int cf_check_compressed(fileid_t *); +extern void cf_close(fileid_t *); +extern void cf_seek(fileid_t *, off_t, int); +extern int cf_read(fileid_t *, caddr_t, size_t); int bootrd_debug; #ifdef _BOOT @@ -419,6 +423,59 @@ getblock(fileid_t *filep, caddr_t buf, int count, int *rcount) return (0); } +/* + * Get the next block of data from the file. Don't attempt to go directly + * to user's buffer. + */ +static int +getblock_noopt(fileid_t *filep) +{ + struct fs *fs; + caddr_t p; + int off, size, diff; + daddr32_t lbn; + devid_t *devp; + + dprintf("getblock_noopt: start\n"); + + devp = filep->fi_devp; + p = filep->fi_memp; + if ((signed)filep->fi_count <= 0) { + + /* find the amt left to be read in the file */ + diff = filep->fi_inode->i_size - filep->fi_offset; + if (diff <= 0) { + printf("Short read\n"); + return (-1); + } + + fs = &devp->un_fs.di_fs; + /* which block (or frag) in the file do we read? */ + lbn = lblkno(fs, filep->fi_offset); + + /* which physical block on the device do we read? */ + filep->fi_blocknum = fsbtodb(fs, sbmap(filep, lbn)); + + off = blkoff(fs, filep->fi_offset); + + /* either blksize or fragsize */ + size = blksize(fs, filep->fi_inode, lbn); + filep->fi_count = size; + /* reading on a ramdisk, just get a pointer to the data */ + filep->fi_memp = NULL; + + if (diskread(filep)) + return (-1); + + if (filep->fi_offset - off + size >= filep->fi_inode->i_size) + filep->fi_count = diff + off; + filep->fi_count -= off; + p = &filep->fi_memp[off]; + } + filep->fi_memp = p; + return (0); +} + /* * This is the high-level read function. It works like this. @@ -441,7 +498,8 @@ bufs_read(int fd, caddr_t buf, size_t count) return (-1); } - if (filep->fi_offset + count > filep->fi_inode->i_size) + if ((filep->fi_flags & FI_COMPRESSED) == 0 && + filep->fi_offset + count > filep->fi_inode->i_size) count = filep->fi_inode->i_size - filep->fi_offset; /* that was easy */ @@ -450,22 +508,30 @@ bufs_read(int fd, caddr_t buf, size_t count) n = buf; while (i > 0) { - /* If we need to reload the buffer, do so */ - if ((j = filep->fi_count) == 0) { - (void) getblock(filep, buf, i, &rcount); - i -= rcount; - buf += rcount; - filep->fi_offset += rcount; + if (filep->fi_flags & FI_COMPRESSED) { + if ((j = cf_read(filep, buf, count)) < 0) + return (0); /* encountered an error */ + if (j < i) + i = j; /* short read, must have hit EOF */ } else { - /* else just bcopy from our buffer */ - j = MIN(i, j); - bcopy(filep->fi_memp, buf, (unsigned)j); - buf += j; - filep->fi_memp += j; - filep->fi_offset += j; - filep->fi_count -= j; - i -= j; + /* If we need to reload the buffer, do so */ + if ((j = filep->fi_count) == 0) { + (void) getblock(filep, buf, i, &rcount); + i -= rcount; + buf += rcount; + filep->fi_offset += rcount; + continue; + } else { + /* else just bcopy from our buffer */ + j = MIN(i, j); + bcopy(filep->fi_memp, buf, (unsigned)j); + } } + buf += j; + filep->fi_memp += j; + filep->fi_offset += j; + filep->fi_count -= j; + i -= j; } return (buf - n); } @@ -564,6 +630,8 @@ bufs_open(char *filename, int flags) filep->fi_devp = ufs_devp; /* dev is already "mounted" */ filep->fi_inode = NULL; bzero(filep->fi_buf, MAXBSIZE); + filep->fi_getblock = getblock_noopt; + filep->fi_flags = 0; inode = find(filep, (char *)filename); if (inode == (ino_t)0) { @@ -579,6 +647,8 @@ bufs_open(char *filename, int flags) filep->fi_offset = filep->fi_count = 0; + if (cf_check_compressed(filep) != 0) + return (-1); return (filep->fi_filedes); } @@ -596,20 +666,24 @@ bufs_lseek(int fd, off_t addr, int whence) if (!(filep = find_fp(fd))) return (-1); - switch (whence) { - case SEEK_CUR: - filep->fi_offset += addr; - break; - case SEEK_SET: - filep->fi_offset = addr; - break; - default: - case SEEK_END: - printf("lseek(): invalid whence value %d\n", whence); - break; + if (filep->fi_flags & FI_COMPRESSED) { + cf_seek(filep, addr, whence); + } else { + switch (whence) { + case SEEK_CUR: + filep->fi_offset += addr; + break; + case SEEK_SET: + filep->fi_offset = addr; + break; + default: + case SEEK_END: + printf("lseek(): invalid whence value %d\n", whence); + break; + } + filep->fi_blocknum = addr / DEV_BSIZE; } - filep->fi_blocknum = addr / DEV_BSIZE; filep->fi_count = 0; return (0); @@ -643,6 +717,11 @@ bufs_fstat(int fd, struct bootstat *stp) default: break; } + /* + * NOTE: this size will be the compressed size for a compressed file + * This could confuse the caller since we decompress the file behind + * the scenes when the file is read. + */ stp->st_size = ip->i_size; stp->st_atim.tv_sec = ip->i_atime.tv_sec; stp->st_atim.tv_nsec = ip->i_atime.tv_usec * 1000; @@ -675,6 +754,7 @@ bufs_close(int fd) /* unlink and deallocate node */ filep->fi_forw->fi_back = filep->fi_back; filep->fi_back->fi_forw = filep->fi_forw; + cf_close(filep); bkmem_free((char *)filep, sizeof (fileid_t)); return (0); diff --git a/usr/src/common/util/bzero.c b/usr/src/common/util/bzero.c index a9d30adad1..3bd96aa029 100644 --- a/usr/src/common/util/bzero.c +++ b/usr/src/common/util/bzero.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T @@ -35,7 +34,7 @@ #if !defined(_KMDB) && !defined(_BOOT) #include "synonyms.h" -#endif /* !_KMDB || _BOOT */ +#endif /* !_KMDB && !_BOOT */ #include <sys/types.h> #include <string.h> diff --git a/usr/src/common/util/memcpy.c b/usr/src/common/util/memcpy.c index a9051f3e84..9580401335 100644 --- a/usr/src/common/util/memcpy.c +++ b/usr/src/common/util/memcpy.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -51,10 +51,12 @@ #if defined(_KERNEL) #include <sys/systm.h> -#else +#elif !defined(_BOOT) #include <stddef.h> #include <string.h> -#endif /* !_KERNEL */ +#endif + +#include "memcpy.h" /* * Copy s0 to s, always copy n bytes. diff --git a/usr/src/cmd/mdb/common/kmdb/kmdb_kdi_impl.h b/usr/src/common/util/memcpy.h index 3ff5deb4ee..de7756825e 100644 --- a/usr/src/cmd/mdb/common/kmdb/kmdb_kdi_impl.h +++ b/usr/src/common/util/memcpy.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,27 +18,27 @@ * * CDDL HEADER END */ + /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#ifndef _KMDB_KDI_IMPL_H -#define _KMDB_KDI_IMPL_H +#ifndef _COMMON_UTIL_MEMCPY_H +#define _COMMON_UTIL_MEMCPY_H #pragma ident "%Z%%M% %I% %E% SMI" -#include <kmdb/kmdb_kdi.h> +#include <sys/types.h> #ifdef __cplusplus extern "C" { #endif -extern void kdi_cpu_init(void); -extern void kdi_usecwait(clock_t); +extern void *memcpy(void *, const void *, size_t); #ifdef __cplusplus } #endif -#endif /* _KMDB_KDI_IMPL_H */ +#endif /* _COMMON_UTIL_MEMCPY_H */ diff --git a/usr/src/common/util/memset.c b/usr/src/common/util/memset.c index f18f8cb0e3..9258a5fa0f 100644 --- a/usr/src/common/util/memset.c +++ b/usr/src/common/util/memset.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,9 +41,11 @@ #if defined(_KERNEL) #include <sys/systm.h> -#else +#elif !defined(_BOOT) #include <string.h> -#endif /* !_KERNEL */ +#endif + +#include "string.h" /* * Set an array of n chars starting at sp to the character c. diff --git a/usr/src/psm/stand/boot/amd64/amd64/alloc.h b/usr/src/common/util/memset.h index ba6a8c8da5..93436f2ac1 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/alloc.h +++ b/usr/src/common/util/memset.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,27 +18,27 @@ * * CDDL HEADER END */ + /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#ifndef _AMD64_ALLOC_H -#define _AMD64_ALLOC_H +#ifndef _COMMON_UTIL_MEMSET_H +#define _COMMON_UTIL_MEMSET_H #pragma ident "%Z%%M% %I% %E% SMI" -#ifdef __cplusplus +#include <sys/types.h> + +#ifdef __cplusplus extern "C" { #endif -#include <sys/types.h> - -extern void *amd64_alloc_identity(size_t); -extern void *amd64_zalloc_identity(size_t); +extern void *memset(void *, int, size_t); -#ifdef __cplusplus +#ifdef __cplusplus } #endif -#endif /* _AMD64_ALLOC_H */ +#endif /* _COMMON_UTIL_MEMSET_H */ diff --git a/usr/src/common/util/sscanf.c b/usr/src/common/util/sscanf.c new file mode 100644 index 0000000000..df800aaf87 --- /dev/null +++ b/usr/src/common/util/sscanf.c @@ -0,0 +1,633 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * From: Id: vfscanf.c,v 1.13 1998/09/25 12:20:27 obrien Exp + * From: static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93"; + * From: static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93"; + */ + + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/ctype.h> +#include <sys/sunddi.h> +#include <util/sscanf.h> + +#define BUF 32 /* Maximum length of numeric string. */ + +/* + * Flags used during conversion. + */ +#define LONG 0x01 /* l: long or double */ +#define SHORT 0x04 /* h: short */ +#define SUPPRESS 0x08 /* suppress assignment */ +#define POINTER 0x10 /* weird %p pointer (`fake hex') */ +#define NOSKIP 0x20 /* do not skip blanks */ + +/* + * The following are used in numeric conversions only: + * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point; + * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral. + */ +#define SIGNOK 0x40 /* +/- is (still) legal */ +#define NDIGITS 0x80 /* no digits detected */ + +#define DPTOK 0x100 /* (float) decimal point is still legal */ +#define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */ + +#define PFXOK 0x100 /* 0x prefix is (still) legal */ +#define NZDIGITS 0x200 /* no zero digits detected */ + +/* + * Conversion types. + */ +#define CT_CHAR 0 /* %c conversion */ +#define CT_CCL 1 /* %[...] conversion */ +#define CT_STRING 2 /* %s conversion */ +#define CT_INT 3 /* integer, i.e., strtoq or strtouq */ + +static const uchar_t *set_ccl(char *, const uchar_t *); + +#define isspace(ch) (((ch) == ' ') || ((ch) == '\r') || ((ch) == '\n') || \ + ((ch) == '\t') || ((ch) == '\f')) + +int +vsscanf(const char *inp, char const *fmt0, va_list ap) +{ + int inr; + const uchar_t *fmt = (const uchar_t *)fmt0; + int c; /* character from format, or conversion */ + size_t width; /* field width, or 0 */ + char *p; /* points into all kinds of strings */ + int n; /* handy integer */ + int flags; /* flags as defined above */ + char *p0; /* saves original value of p when necessary */ + int nassigned; /* number of fields assigned */ + int nconversions; /* number of conversions */ + int nread; /* number of characters consumed from fp */ + int base; /* base argument to strtoq/strtouq */ + int sconv; /* do signed conversion */ + char ccltab[256]; /* character class table for %[...] */ + char buf[BUF]; /* buffer for numeric conversions */ + + /* `basefix' is used to avoid `if' tests in the integer scanner */ + static short basefix[17] = + { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + + inr = strlen(inp); + + sconv = 0; + nassigned = 0; + nconversions = 0; + nread = 0; + base = 0; + for (;;) { + c = *fmt++; + if (c == 0) + return (nassigned); + if (isspace(c)) { + while (inr > 0 && isspace(*inp)) + nread++, inr--, inp++; + continue; + } + if (c != '%') + goto literal; + width = 0; + flags = 0; + /* + * switch on the format. continue if done; + * break once format type is derived. + */ +again: c = *fmt++; + switch (c) { + case '%': +literal: + if (inr <= 0) + goto input_failure; + if (*inp != c) + goto match_failure; + inr--, inp++; + nread++; + continue; + + case '*': + flags |= SUPPRESS; + goto again; + case 'l': + flags |= LONG; + goto again; + case 'h': + flags |= SHORT; + goto again; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + width = width * 10 + c - '0'; + goto again; + + /* + * Conversions. + * + */ + case 'd': + c = CT_INT; + sconv = 1; + base = 10; + break; + + case 'i': + c = CT_INT; + sconv = 1; + base = 0; + break; + + case 'o': + c = CT_INT; + base = 8; + break; + + case 'u': + c = CT_INT; + base = 10; + break; + + case 'x': + flags |= PFXOK; /* enable 0x prefixing */ + c = CT_INT; + base = 16; + break; + + case 's': + c = CT_STRING; + break; + + case '[': + fmt = set_ccl(ccltab, fmt); + flags |= NOSKIP; + c = CT_CCL; + break; + + case 'c': + flags |= NOSKIP; + c = CT_CHAR; + break; + + case 'p': /* pointer format is like hex */ + flags |= POINTER | PFXOK; + c = CT_INT; + base = 16; + break; + + case 'n': + nconversions++; + if (flags & SUPPRESS) /* ??? */ + continue; + if (flags & SHORT) + *va_arg(ap, short *) = (short)nread; + else if (flags & LONG) + *va_arg(ap, long *) = (long)nread; + else + *va_arg(ap, int *) = nread; + continue; + } + + /* + * We have a conversion that requires input. + */ + if (inr <= 0) + goto input_failure; + + /* + * Consume leading white space, except for formats + * that suppress this. + */ + if ((flags & NOSKIP) == 0) { + while (isspace(*inp)) { + nread++; + if (--inr > 0) + inp++; + else + goto input_failure; + } + /* + * Note that there is at least one character in + * the buffer, so conversions that do not set NOSKIP + * can no longer result in an input failure. + */ + } + + /* + * Do the conversion. + */ + switch (c) { + + case CT_CHAR: + /* scan arbitrary characters (sets NOSKIP) */ + if (width == 0) + width = 1; + if (flags & SUPPRESS) { + size_t sum = 0; + + if ((n = inr) < width) { + sum += n; + width -= n; + inp += n; + if (sum == 0) + goto input_failure; + } else { + sum += width; + inr -= width; + inp += width; + } + nread += sum; + } else { + bcopy(inp, va_arg(ap, char *), width); + inr -= width; + inp += width; + nread += width; + nassigned++; + } + nconversions++; + break; + + case CT_CCL: + /* scan a (nonempty) character class (sets NOSKIP) */ + if (width == 0) + width = (size_t)~0; /* `infinity' */ + /* take only those things in the class */ + if (flags & SUPPRESS) { + n = 0; + while (ccltab[(unsigned char)*inp]) { + n++, inr--, inp++; + if (--width == 0) + break; + if (inr <= 0) { + if (n == 0) + goto input_failure; + break; + } + } + if (n == 0) + goto match_failure; + } else { + p0 = p = va_arg(ap, char *); + while (ccltab[(unsigned char)*inp]) { + inr--; + *p++ = *inp++; + if (--width == 0) + break; + if (inr <= 0) { + if (p == p0) + goto input_failure; + break; + } + } + n = p - p0; + if (n == 0) + goto match_failure; + *p = 0; + nassigned++; + } + nread += n; + nconversions++; + break; + + case CT_STRING: + /* like CCL, but zero-length string OK, & no NOSKIP */ + if (width == 0) + width = (size_t)~0; + if (flags & SUPPRESS) { + n = 0; + while (!isspace(*inp)) { + n++, inr--, inp++; + if (--width == 0) + break; + if (inr <= 0) + break; + } + nread += n; + } else { + p0 = p = va_arg(ap, char *); + while (!isspace(*inp)) { + inr--; + *p++ = *inp++; + if (--width == 0) + break; + if (inr <= 0) + break; + } + *p = 0; + nread += p - p0; + nassigned++; + } + nconversions++; + continue; + + case CT_INT: + /* scan an integer as if by strtoq/strtouq */ + /* size_t is unsigned, hence this optimisation */ + if (--width > sizeof (buf) - 2) + width = sizeof (buf) - 2; + width++; + flags |= SIGNOK | NDIGITS | NZDIGITS; + for (p = buf; width; width--) { + c = *inp; + /* + * Switch on the character; `goto ok' + * if we accept it as a part of number. + */ + switch (c) { + + /* + * The digit 0 is always legal, but is + * special. For %i conversions, if no + * digits (zero or nonzero) have been + * scanned (only signs), we will have + * base==0. In that case, we should set + * it to 8 and enable 0x prefixing. + * Also, if we have not scanned zero digits + * before this, do not turn off prefixing + * (someone else will turn it off if we + * have scanned any nonzero digits). + */ + case '0': + if (base == 0) { + base = 8; + flags |= PFXOK; + } + if (flags & NZDIGITS) + flags &= ~(SIGNOK|NZDIGITS|NDIGITS); + else + flags &= ~(SIGNOK|PFXOK|NDIGITS); + goto ok; + + /* 1 through 7 always legal */ + case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + base = basefix[base]; + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* digits 8 and 9 ok iff decimal or hex */ + case '8': case '9': + base = basefix[base]; + if (base <= 8) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* letters ok iff hex */ + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': + /* no need to fix base here */ + if (base <= 10) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* sign ok only as first character */ + case '+': case '-': + if (flags & SIGNOK) { + flags &= ~SIGNOK; + goto ok; + } + break; + + /* x ok iff flag still set & 2nd char */ + case 'x': case 'X': + if (flags & PFXOK && p == buf + 1) { + base = 16; /* if %i */ + flags &= ~PFXOK; + goto ok; + } + break; + } + + /* + * If we got here, c is not a legal character + * for a number. Stop accumulating digits. + */ + break; + ok: + /* + * c is legal: store it and look at the next. + */ + *p++ = c; + if (--inr > 0) + inp++; + else + break; /* end of input */ + } + /* + * If we had only a sign, it is no good; push + * back the sign. If the number ends in `x', + * it was [sign] '0' 'x', so push back the x + * and treat it as [sign] '0'. + */ + if (flags & NDIGITS) { + if (p > buf) { + inp--; + inr++; + } + goto match_failure; + } + c = ((uchar_t *)p)[-1]; + if (c == 'x' || c == 'X') { + --p; + inp--; + inr++; + } + if ((flags & SUPPRESS) == 0) { + ulong_t res; + + *p = 0; + if (sconv) + (void) ddi_strtol(buf, (char **)NULL, + base, (long *)(&res)); + else + (void) ddi_strtoul(buf, (char **)NULL, + base, &res); + if (flags & POINTER) + *va_arg(ap, void **) = + (void *)(uintptr_t)res; + else if (flags & SHORT) + *va_arg(ap, short *) = (short)res; + else if (flags & LONG) + *va_arg(ap, long *) = (long)res; + else + *va_arg(ap, int *) = (int)res; + nassigned++; + } + nread += p - buf; + nconversions++; + break; + + } + } +input_failure: + return (nconversions != 0 ? nassigned : -1); +match_failure: + return (nassigned); +} + +/* + * Fill in the given table from the scanset at the given format + * (just after `['). Return a pointer to the character past the + * closing `]'. The table has a 1 wherever characters should be + * considered part of the scanset. + */ +static const uchar_t * +set_ccl(char *tab, const uchar_t *fmt) +{ + int c, n, v; + + /* first `clear' the whole table */ + c = *fmt++; /* first char hat => negated scanset */ + if (c == '^') { + v = 1; /* default => accept */ + c = *fmt++; /* get new first char */ + } else + v = 0; /* default => reject */ + + /* XXX: Will not work if sizeof(tab*) > sizeof(char) */ + for (n = 0; n < 256; n++) + tab[n] = v; /* memset(tab, v, 256) */ + + if (c == 0) + return (fmt - 1); /* format ended before closing ] */ + + /* + * Now set the entries corresponding to the actual scanset + * to the opposite of the above. + * + * The first character may be ']' (or '-') without being special; + * the last character may be '-'. + */ + v = 1 - v; + for (;;) { + tab[c] = v; /* take character c */ +doswitch: + n = *fmt++; /* and examine the next */ + switch (n) { + + case 0: /* format ended too soon */ + return (fmt - 1); + + case '-': + /* + * A scanset of the form + * [01+-] + * is defined as `the digit 0, the digit 1, + * the character +, the character -', but + * the effect of a scanset such as + * [a-zA-Z0-9] + * is implementation defined. The V7 Unix + * scanf treats `a-z' as `the letters a through + * z', but treats `a-a' as `the letter a, the + * character -, and the letter a'. + * + * For compatibility, the `-' is not considerd + * to define a range if the character following + * it is either a close bracket (required by ANSI) + * or is not numerically greater than the character + * we just stored in the table (c). + */ + n = *fmt; + if (n == ']' || n < c) { + c = '-'; + break; /* resume the for(;;) */ + } + fmt++; + /* fill in the range */ + do { + tab[++c] = v; + } while (c < n); + c = n; + /* + * Alas, the V7 Unix scanf also treats formats + * such as [a-c-e] as `the letters a through e'. + * This too is permitted by the standard.... + */ + goto doswitch; + /* NOTREACHED */ + + case ']': /* end of scanset */ + return (fmt); + + default: /* just another character */ + c = n; + break; + } + } + /* NOTREACHED */ +} + +int +sscanf(const char *ibuf, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = vsscanf(ibuf, fmt, ap); + va_end(ap); + return (ret); +} diff --git a/usr/src/psm/stand/boot/amd64/amd64/auxv64.h b/usr/src/common/util/sscanf.h index 42e897e7ce..8ca717b9c1 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/auxv64.h +++ b/usr/src/common/util/sscanf.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,34 +18,30 @@ * * CDDL HEADER END */ + /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#ifndef _AMD64_AUXV64_H -#define _AMD64_AUXV64_H +#ifndef _COMMON_UTIL_SSCANF_H +#define _COMMON_UTIL_SSCANF_H #pragma ident "%Z%%M% %I% %E% SMI" -#ifdef __cplusplus +#include <sys/types.h> +#include <sys/varargs.h> + +#ifdef __cplusplus extern "C" { #endif -#include <sys/types.h> -#include <sys/auxv.h> - -typedef struct { - int a_type; - int a_pad; /* XX64 */ - union { - int64_t a_val; - uint64_t a_ptr; - } a_un; -} auxv64_t; - -#ifdef __cplusplus +/*SCANFLIKE2*/ +extern int sscanf(const char *, const char *, ...); +extern int vsscanf(const char *, const char *, va_list); + +#ifdef __cplusplus } #endif -#endif /* _AMD64_AUXV64_H */ +#endif /* _COMMON_UTIL_SSCANF_H */ diff --git a/usr/src/common/util/string.c b/usr/src/common/util/string.c index 59a6139324..94153d2db2 100644 --- a/usr/src/common/util/string.c +++ b/usr/src/common/util/string.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,19 +33,25 @@ #include <sys/types.h> #include <sys/varargs.h> -#if defined(_BOOT) || defined(_KMDB) -#include <string.h> -#else + +#if defined(_KERNEL) #include <sys/systm.h> -#endif -#ifdef _KERNEL #include <sys/debug.h> -#endif /* _KERNEL */ +#elif !defined(_BOOT) +#include <string.h> +#endif + +#ifndef NULL +#define NULL 0l +#endif + +#include "memcpy.h" +#include "string.h" /* - * kmdb has its own *printf routines, and thus doesn't need these versions too. + * We don't need these for x86 boot or kmdb. */ -#if !defined(_KMDB) +#if !defined(_KMDB) && (!defined(_BOOT) || defined(__sparc)) #define ADDCHAR(c) if (bufp++ - buf < buflen) bufp[-1] = (c) @@ -322,7 +328,7 @@ snprintf(char *buf, size_t buflen, const char *fmt, ...) return (buflen); } -#if defined(_BOOT) +#if defined(_BOOT) && defined(__sparc) /* * The sprintf() and vsprintf() routines aren't shared with the kernel because * the DDI mandates that they return the buffer rather than its length. @@ -346,9 +352,9 @@ vsprintf(char *buf, const char *fmt, va_list args) (void) vsnprintf(buf, INT_MAX, fmt, args); return (strlen(buf)); } -#endif +#endif /* _BOOT && __sparc */ -#endif /* !_KMDB */ +#endif /* !_KMDB && (!_BOOT || __sparc) */ char * strcat(char *s1, const char *s2) @@ -571,7 +577,8 @@ strlcat(char *dst, const char *src, size_t dstsize) while (left-- != 0 && *df != '\0') df++; - l1 = df - dst; + /*LINTED: possible ptrdiff_t overflow*/ + l1 = (size_t)(df - dst); if (dstsize == l1) return (l1 + l2); @@ -611,7 +618,8 @@ strspn(const char *string, const char *charset) break; } - return (q - string); + /*LINTED: possible ptrdiff_t overflow*/ + return ((size_t)(q - string)); } /* diff --git a/usr/src/common/util/string.h b/usr/src/common/util/string.h new file mode 100644 index 0000000000..c7db1bf967 --- /dev/null +++ b/usr/src/common/util/string.h @@ -0,0 +1,87 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _COMMON_UTIL_STRING_H +#define _COMMON_UTIL_STRING_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(_KMDB) && (!defined(_BOOT) || defined(__sparc)) + +extern size_t vsnprintf(char *, size_t, const char *, va_list); +/*PRINTFLIKE1*/ +extern size_t snprintf(char *, size_t, const char *, ...); + +#if defined(_BOOT) && defined(__sparc) + +/*PRINTFLIKE2*/ +extern int sprintf(char *, const char *, ...); +extern int vsprintf(char *, const char *, va_list); + +#endif /* _BOOT && __sparc */ +#endif /* !_KMDB && (!_BOOT || __sparc) */ + +extern char *strcat(char *, const char *); +extern char *strchr(const char *, int); +extern int strcmp(const char *, const char *); +extern int strncmp(const char *, const char *, size_t); +extern int strcasecmp(const char *, const char *); +extern int strncasecmp(const char *, const char *, size_t); +extern char *strcpy(char *, const char *); +extern char *strncpy(char *, const char *, size_t); +extern char *strrchr(const char *, int c); +extern char *strstr(const char *, const char *); +extern char *strpbrk(const char *, const char *); +extern char *strncat(char *, const char *, size_t); +extern size_t strlcat(char *, const char *, size_t); +extern size_t strlcpy(char *, const char *, size_t); +extern size_t strspn(const char *, const char *); + +#if defined(_BOOT) || defined(_KMDB) + +extern char *strtok(char *, const char *); +extern size_t strlen(const char *); + +#endif /* _BOOT || _KMDB */ + +#ifdef _KERNEL + +extern int strident_valid(const char *); +extern void strident_canon(char *, size_t); + +#endif /* _KERNEL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _COMMON_UTIL_STRING_H */ diff --git a/usr/src/grub/grub-0.95/grub/asmstub.c b/usr/src/grub/grub-0.95/grub/asmstub.c index d71fe5c6f3..b7edddd52f 100644 --- a/usr/src/grub/grub-0.95/grub/asmstub.c +++ b/usr/src/grub/grub-0.95/grub/asmstub.c @@ -1281,3 +1281,30 @@ hercules_setcursor (int on) { return 1; } + +uint32_t amd64_cpuid_supported(void) +{ + /* Nothing to do in the simulator. */ + return (1); +} + +void amd64_cpuid_insn(uint32_t i, void * r) +{ + /* Nothing to do in the simulator. */ +} + +void amd64_rdmsr(uint32_t i, uint64_t * p) +{ + /* Nothing to do in the simulator. */ +} + +void amd64_wrmsr(uint32_t i, const uint64_t * p) +{ + /* Nothing to do in the simulator. */ +} + +int get_target_operating_mode(void) +{ + /* Nothing to do in the simulator. */ + return (1); +} diff --git a/usr/src/grub/grub-0.95/stage2/asm.S b/usr/src/grub/grub-0.95/stage2/asm.S index 1aa6eaed06..1952421725 100644 --- a/usr/src/grub/grub-0.95/stage2/asm.S +++ b/usr/src/grub/grub-0.95/stage2/asm.S @@ -2595,7 +2595,81 @@ ENTRY(currticks) popl %ebp ret -#endif /* STAGE1_5 */ +ENTRY(amd64_rdmsr) + movl 4(%esp), %ecx + rdmsr + movl 8(%esp), %ecx + movl %eax, (%ecx) + movl %edx, 4(%ecx) + ret + +ENTRY(amd64_wrmsr) + movl 8(%esp), %ecx + movl (%ecx), %eax + movl 4(%ecx), %edx + movl 4(%esp), %ecx + wrmsr + ret + +ENTRY(amd64_cpuid_insn) + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %esi + movl 0x8(%ebp), %eax + movl 0xc(%ebp), %esi + cpuid + movl %eax, 0x0(%esi) + movl %ebx, 0x4(%esi) + movl %ecx, 0x8(%esi) + movl %edx, 0xc(%esi) + popl %esi + popl %ebx + popl %ebp + ret + + /* + * Based on code from AMD64 Volume 3 + */ +ENTRY(amd64_cpuid_supported) + pushf + popl %eax + mov %eax, %edx /* save %eax for later */ + xorl %eax, 0x200000 /* toggle bit 21 */ + pushl %eax + popf /* save new %eax to EFLAGS */ + pushf /* save new EFLAGS */ + popl %ecx /* copy EFLAGS to %eax */ + xorl %eax, %eax + cmpl %ecx, %edx /* see if bit 21 has changes */ + jne 1f + incl %eax +1: + ret + +ENTRY(get_target_operating_mode) + pusha + + call EXT_C(prot_to_real) + .code16 + + movw $0xec00, %ax + movw $0x03, %bx + int $0x15 +/* XXX still need to pass back return */ + + movw %ax, %cx + + DATA32 call EXT_C(real_to_prot) + .code32 + + xorl %eax, %eax + movw %cx, %ax + + popa + ret + +#endif /* ! STAGE1_5 */ /* * This is the area for all of the special variables. diff --git a/usr/src/grub/grub-0.95/stage2/builtins.c b/usr/src/grub/grub-0.95/stage2/builtins.c index bdc3fe4e45..b7d0aaa00a 100644 --- a/usr/src/grub/grub-0.95/stage2/builtins.c +++ b/usr/src/grub/grub-0.95/stage2/builtins.c @@ -48,6 +48,8 @@ # include <md5.h> #endif +#include <cpu.h> + /* The type of kernel loaded. */ kernel_t kernel_type; /* The boot device. */ @@ -989,7 +991,7 @@ static int verbose_func(char *arg, int flags) { silent.status = VERBOSE; - /* get back to text console XXX setje -- tty??? */ + /* get back to text console */ if (current_term->shutdown) { (*current_term->shutdown)(); current_term = term_table; /* assumption: console is first */ @@ -2716,6 +2718,280 @@ static struct builtin builtin_kernel = " Linux's mem option automatically." }; + +static int detect_target_operating_mode(); + +int +amd64_config_cpu(void) +{ + struct amd64_cpuid_regs __vcr, *vcr = &__vcr; + uint32_t maxeax; + uint32_t max_maxeax = 0x100; + char vendor[13]; + int isamd64 = 0; + uint32_t stdfeatures = 0, xtdfeatures = 0; + uint64_t efer; + + /* + * This check may seem silly, but if the C preprocesor symbol __amd64 + * is #defined during compilation, something that may outwardly seem + * like a good idea, uts/common/sys/isa_defs.h will #define _LP64, + * which will cause uts/common/sys/int_types.h to typedef uint64_t as + * an unsigned long - which is only 4 bytes in size when using a 32-bit + * compiler. + * + * If that happens, all the page table translation routines will fail + * horribly, so check the size of uint64_t just to insure some degree + * of sanity in future operations. + */ + /*LINTED [sizeof result is invarient]*/ + if (sizeof (uint64_t) != 8) + prom_panic("grub compiled improperly, unable to boot " + "64-bit AMD64 executables"); + + /* + * If the CPU doesn't support the CPUID instruction, it's definitely + * not an AMD64. + */ + if (amd64_cpuid_supported() == 0) + return (0); + + amd64_cpuid_insn(0, vcr); + + maxeax = vcr->r_eax; + { + /*LINTED [vendor string from cpuid data]*/ + uint32_t *iptr = (uint32_t *)vendor; + + *iptr++ = vcr->r_ebx; + *iptr++ = vcr->r_edx; + *iptr++ = vcr->r_ecx; + + vendor[12] = '\0'; + } + + if (maxeax > max_maxeax) { + grub_printf("cpu: warning, maxeax was 0x%x -> 0x%x\n", + maxeax, max_maxeax); + maxeax = max_maxeax; + } + + if (maxeax < 1) + return (0); /* no additional functions, not an AMD64 */ + else { + uint_t family, model, step; + + amd64_cpuid_insn(1, vcr); + + /* + * All AMD64/IA32e processors technically SHOULD report + * themselves as being in family 0xf, but for some reason + * Simics doesn't, and this may change in the future, so + * don't error out if it's not true. + */ + if ((family = BITX(vcr->r_eax, 11, 8)) == 0xf) + family += BITX(vcr->r_eax, 27, 20); + + if ((model = BITX(vcr->r_eax, 7, 4)) == 0xf) + model += BITX(vcr->r_eax, 19, 16) << 4; + step = BITX(vcr->r_eax, 3, 0); + + grub_printf("cpu: '%s' family %d model %d step %d\n", + vendor, family, model, step); + stdfeatures = vcr->r_edx; + } + + amd64_cpuid_insn(0x80000000, vcr); + + if (vcr->r_eax & 0x80000000) { + uint32_t xmaxeax = vcr->r_eax; + const uint32_t max_xmaxeax = 0x80000100; + + if (xmaxeax > max_xmaxeax) { + grub_printf("amd64: warning, xmaxeax was " + "0x%x -> 0x%x\n", xmaxeax, max_xmaxeax); + xmaxeax = max_xmaxeax; + } + + if (xmaxeax >= 0x80000001) { + amd64_cpuid_insn(0x80000001, vcr); + xtdfeatures = vcr->r_edx; + } + } + + if (BITX(xtdfeatures, 29, 29)) /* long mode */ + isamd64++; + else + grub_printf("amd64: CPU does NOT support long mode\n"); + + if (!BITX(stdfeatures, 0, 0)) { + grub_printf("amd64: CPU does NOT support FPU\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 4, 4)) { + grub_printf("amd64: CPU does NOT support TSC\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 5, 5)) { + grub_printf("amd64: CPU does NOT support MSRs\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 6, 6)) { + grub_printf("amd64: CPU does NOT support PAE\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 8, 8)) { + grub_printf("amd64: CPU does NOT support CX8\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 13, 13)) { + grub_printf("amd64: CPU does NOT support PGE\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 17, 17)) { + grub_printf("amd64: CPU does NOT support PSE\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 19, 19)) { + grub_printf("amd64: CPU does NOT support CLFSH\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 23, 23)) { + grub_printf("amd64: CPU does NOT support MMX\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 24, 24)) { + grub_printf("amd64: CPU does NOT support FXSR\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 25, 25)) { + grub_printf("amd64: CPU does NOT support SSE\n"); + isamd64--; + } + + if (!BITX(stdfeatures, 26, 26)) { + grub_printf("amd64: CPU does NOT support SSE2\n"); + isamd64--; + } + + if (isamd64 < 1) { + grub_printf("amd64: CPU does not support amd64 executables.\n"); + return (0); + } + + amd64_rdmsr(MSR_AMD_EFER, &efer); + if (efer & AMD_EFER_SCE) + grub_printf("amd64: EFER_SCE (syscall/sysret) already " + "enabled\n"); + if (efer & AMD_EFER_NXE) + grub_printf("amd64: EFER_NXE (no-exec prot) already enabled\n"); + if (efer & AMD_EFER_LME) + grub_printf("amd64: EFER_LME (long mode) already enabled\n"); + + return (detect_target_operating_mode()); +} + +static int +detect_target_operating_mode() +{ + int ret, ah; + + ah = get_target_operating_mode(); + + ah = ah >> 8; + + /* XXX still need to pass back the return from the call */ + ret = 0; + + if (ah == 0x86 && (ret & CB) != 0) { + grub_printf("[BIOS 'Detect Target Operating Mode' " + "callback unsupported on this platform]\n"); + return (1); /* unsupported, ignore */ + } + + if (ah == 0x0 && (ret & CB) == 0) { + grub_printf("[BIOS accepted mixed-mode target setting!]\n"); + return (1); /* told the bios what we're up to */ + } + + if (ah == 0 && ret & CB) { + grub_printf("fatal: BIOS reports this machine CANNOT run in " + "mixed 32/64-bit mode!\n"); + return (0); + } + + grub_printf("warning: BIOS Detect Target Operating Mode callback " + "confused.\n %%ax >> 8 = 0x%x, carry = %d\n", ah, + ret & CB ? 1 : 0); + + return (1); +} + + +int +isamd64() +{ + static int ret = -1; + + if (ret == -1) + ret = amd64_config_cpu(); + + return (ret); +} + +static int +expand_arch (char *arg, int flags, int func()) +{ + char newarg[MAX_CMDLINE]; /* everything boils down to MAX_CMDLINE */ + char *index; + + newarg[0] = '\0'; + + while ((index = strstr(arg, "$ISADIR")) != NULL) { + + index[0] = '\0'; + strncat(newarg, arg, MAX_CMDLINE); + index[0] = '$'; + + if (isamd64()) + strncat(newarg, "amd64", MAX_CMDLINE); + + arg = index + 7; + } + + strncat(newarg, arg, MAX_CMDLINE); + + grub_printf("loading %s\n", newarg); + + return (func(newarg, flags)); +} + +/* kernel$ */ +static int +kernel_dollar_func (char *arg, int flags) +{ + return (expand_arch(arg, flags, (void *)&kernel_func)); +} + +static struct builtin builtin_kernel_dollar = +{ + "kernel$", + kernel_dollar_func, + BUILTIN_CMDLINE | BUILTIN_HELP_LIST, + "kernel$ [--no-mem-option] [--type=TYPE] FILE [ARG ...]", + " Just like kernel, but with $ISADIR expansion." +}; + /* lock */ static int @@ -2931,6 +3207,22 @@ static struct builtin builtin_module = " the `kernel' command." }; +/* module$ */ +static int +module_dollar_func (char *arg, int flags) +{ + return (expand_arch(arg, flags, (void *)&module_func)); +} + +static struct builtin builtin_module_dollar = +{ + "module$", + module_dollar_func, + BUILTIN_CMDLINE | BUILTIN_HELP_LIST, + "module FILE [ARG ...]", + " Just like module, but with $ISADIR expansion." +}; + /* modulenounzip */ static int @@ -5148,6 +5440,7 @@ struct builtin *builtin_table[] = &builtin_install, &builtin_ioprobe, &builtin_kernel, + &builtin_kernel_dollar, &builtin_lock, &builtin_makeactive, &builtin_map, @@ -5155,6 +5448,7 @@ struct builtin *builtin_table[] = &builtin_md5crypt, #endif /* USE_MD5_PASSWORDS */ &builtin_module, + &builtin_module_dollar, &builtin_modulenounzip, &builtin_pager, &builtin_partnew, diff --git a/usr/src/grub/grub-0.95/stage2/controlregs.h b/usr/src/grub/grub-0.95/stage2/controlregs.h new file mode 100644 index 0000000000..dc675f603f --- /dev/null +++ b/usr/src/grub/grub-0.95/stage2/controlregs.h @@ -0,0 +1,161 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_CONTROLREGS_H +#define _SYS_CONTROLREGS_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This file describes the x86 architecture control registers which + * are part of the privileged architecture. + * + * Many of these definitions are shared between IA-32-style and + * AMD64-style processors. + */ + +/* CR0 Register */ + +#define CR0_PG 0x80000000 /* paging enabled */ +#define CR0_CD 0x40000000 /* cache disable */ +#define CR0_NW 0x20000000 /* not writethrough */ +#define CR0_AM 0x00040000 /* alignment mask */ +#define CR0_WP 0x00010000 /* write protect */ +#define CR0_NE 0x00000020 /* numeric error */ +#define CR0_ET 0x00000010 /* extension type */ +#define CR0_TS 0x00000008 /* task switch */ +#define CR0_EM 0x00000004 /* emulation */ +#define CR0_MP 0x00000002 /* monitor coprocessor */ +#define CR0_PE 0x00000001 /* protection enabled */ + +/* XX64 eliminate these compatibility defines */ + +#define CR0_CE CR0_CD +#define CR0_WT CR0_NW + +#define FMT_CR0 \ + "\20\40pg\37cd\36nw\35am\21wp\6ne\5et\4ts\3em\2mp\1pe" + +/* CR3 Register */ + +#define CR3_PCD 0x00000010 /* cache disable */ +#define CR3_PWT 0x00000008 /* write through */ + +#define FMT_CR3 "\20\5pcd\4pwt" + +/* CR4 Register */ + +#define CR4_VME 0x0001 /* virtual-8086 mode extensions */ +#define CR4_PVI 0x0002 /* protected-mode virtual interrupts */ +#define CR4_TSD 0x0004 /* time stamp disable */ +#define CR4_DE 0x0008 /* debugging extensions */ +#define CR4_PSE 0x0010 /* page size extensions */ +#define CR4_PAE 0x0020 /* physical address extension */ +#define CR4_MCE 0x0040 /* machine check enable */ +#define CR4_PGE 0x0080 /* page global enable */ +#define CR4_PCE 0x0100 /* perf-monitoring counter enable */ +#define CR4_OSFXSR 0x0200 /* OS fxsave/fxrstor support */ +#define CR4_OSXMMEXCPT 0x0400 /* OS unmasked exception support */ + +#define FMT_CR4 \ + "\20\13xmme\12fxsr\11pce\10pge\7mce\6pae\5pse\4de\3tsd\2pvi\1vme" + +/* Intel's SYSENTER configuration registers */ + +#define MSR_INTC_SEP_CS 0x174 /* kernel code selector MSR */ +#define MSR_INTC_SEP_ESP 0x175 /* kernel esp MSR */ +#define MSR_INTC_SEP_EIP 0x176 /* kernel eip MSR */ + +/* AMD's EFER register */ + +#define MSR_AMD_EFER 0xc0000080 /* extended feature enable MSR */ + +#define AMD_EFER_NXE 0x800 /* no-execute enable */ +#define AMD_EFER_LMA 0x400 /* long mode active (read-only) */ +#define AMD_EFER_LME 0x100 /* long mode enable */ +#define AMD_EFER_SCE 0x001 /* system call extensions */ + +#define FMT_AMD_EFER \ + "\20\14nxe\13lma\11lme\1sce" + +/* AMD's SYSCFG register */ + +#define MSR_AMD_SYSCFG 0xc0000010 /* system configuration MSR */ + +#define AMD_SYSCFG_TOM2 0x200000 /* MtrrTom2En */ +#define AMD_SYSCFG_MVDM 0x100000 /* MtrrVarDramEn */ +#define AMD_SYSCFG_MFDM 0x080000 /* MtrrFixDramModEn */ +#define AMD_SYSCFG_MFDE 0x040000 /* MtrrFixDramEn */ + +#define FMT_AMD_SYSCFG \ + "\20\26tom2\25mvdm\24mfdm\23mfde" + +/* AMD's syscall/sysret MSRs */ + +#define MSR_AMD_STAR 0xc0000081 /* %cs:%ss:%cs:%ss:%eip for syscall */ +#define MSR_AMD_LSTAR 0xc0000082 /* target %rip of 64-bit syscall */ +#define MSR_AMD_CSTAR 0xc0000083 /* target %rip of 32-bit syscall */ +#define MSR_AMD_SFMASK 0xc0000084 /* syscall flag mask */ + +/* AMD's FS.base and GS.base MSRs */ + +#define MSR_AMD_FSBASE 0xc0000100 /* 64-bit base address for %fs */ +#define MSR_AMD_GSBASE 0xc0000101 /* 64-bit base address for %gs */ +#define MSR_AMD_KGSBASE 0xc0000102 /* swapgs swaps this with gsbase */ + +/* AMD's configuration MSRs, weakly documented in the revision guide */ + +#define MSR_AMD_DC_CFG 0xc0011022 + +#define AMD_DC_CFG_DIS_CNV_WC_SSO (UINT64_C(1) << 3) +#define AMD_DC_CFG_DIS_SMC_CHK_BUF (UINT64_C(1) << 10) + +/* AMD's HWCR MSR */ + +#define MSR_AMD_HWCR 0xc0010015 + +#define AMD_HWCR_FFDIS 0x00040 /* disable TLB Flush Filter */ +#define AMD_HWCR_MCI_STATUS_WREN 0x40000 /* enable write of MCi_STATUS */ + +/* AMD's NorthBridge Config MSR, SHOULD ONLY BE WRITTEN TO BY BIOS */ + +#define MSR_AMD_NB_CFG 0xc001001f + +#define MSR_BU_CFG 0xc0011023 + +#define AMD_NB_CFG_SRQ_HEARTBEAT (UINT64_C(1) << 20) +#define AMD_NB_CFG_SRQ_SPR (UINT64_C(1) << 32) + +/* AMD */ +#define MSR_AMD_PATCHLEVEL 0x8b + +#ifdef __cplusplus +} +#endif + +#endif /* !_SYS_CONTROLREGS_H */ diff --git a/usr/src/grub/grub-0.95/stage2/cpu.h b/usr/src/grub/grub-0.95/stage2/cpu.h new file mode 100644 index 0000000000..34180727d9 --- /dev/null +++ b/usr/src/grub/grub-0.95/stage2/cpu.h @@ -0,0 +1,73 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _AMD64_CPU +#define _AMD64_CPU + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned int uint_t; +typedef unsigned long ulong_t; + +#define BITX(u, h, l) (((u) >> (l)) & ((1lu << ((h) - (l) + 1lu)) - 1lu)) + +#include <controlregs.h> + +#define CB 0x0001 + +extern void amd64_flush_tlb(void); +extern void amd64_flush_tlbentry(caddr_t); + +extern ulong_t amd64_get_cr2(void); +extern ulong_t amd64_get_cr0(void); +extern ulong_t amd64_get_cr3(void); +extern ulong_t amd64_get_cr4(void); + +extern ulong_t amd64_get_eflags(void); + +struct amd64_cpuid_regs { + uint32_t r_eax; + uint32_t r_ebx; + uint32_t r_ecx; + uint32_t r_edx; +}; + +#define AMD64_Auth 0x68747541 +#define AMD64_enti 0x69746e65 +#define AMD64_cAMD 0x444d4163 + +extern uint32_t amd64_cpuid_supported(void); +extern void amd64_cpuid_insn(uint32_t, struct amd64_cpuid_regs *); +extern void amd64_rdmsr(uint32_t, uint64_t *); +extern void amd64_wrmsr(uint32_t, const uint64_t *); +extern int get_target_operating_mode(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _AMD64_CPU */ diff --git a/usr/src/grub/install_menu b/usr/src/grub/install_menu index f856e75e07..d2f0c52204 100644 --- a/usr/src/grub/install_menu +++ b/usr/src/grub/install_menu @@ -4,14 +4,14 @@ default=0 timeout=60 title Solaris Express, Developer Edition - kernel /boot/multiboot kernel/unix -B install_media=cdrom,soldevx=true + kernel /boot/platform/i86pc/kernel/unix -B install_media=cdrom,soldevx=true module /boot/x86.miniroot title Solaris Express - kernel /boot/multiboot kernel/unix -B install_media=cdrom + kernel /boot/platform/i86pc/kernel/unix -B install_media=cdrom module /boot/x86.miniroot title Solaris Express Serial Console ttya - kernel /boot/multiboot kernel/unix -B install_media=cdrom,console=ttya + kernel /boot/platform/i86pc/kernel/unix -B install_media=cdrom,console=ttya module /boot/x86.miniroot title Solaris Express Serial Console ttyb (for lx50, v60x and v65x) - kernel /boot/multiboot kernel/unix -B install_media=cdrom,console=ttyb + kernel /boot/platform/i86pc/kernel/unix -B install_media=cdrom,console=ttyb module /boot/x86.miniroot diff --git a/usr/src/grub/menu.lst b/usr/src/grub/menu.lst index 41105017e0..8225e83928 100644 --- a/usr/src/grub/menu.lst +++ b/usr/src/grub/menu.lst @@ -31,14 +31,17 @@ timeout 10 # makeactive # # To load a Solaris instance based on grub +# If GRUB determines if the booting system is 64-bit capable, +# the kernel$ and module$ commands expand $ISADIR to "amd64" # # title Solaris <version> # root (hd<disk no>,<partition no>,x) --x = Solaris root slice -# kernel /platform/i86pc/multiboot -# module /platform/i86pc/boot_archive +# kernel$ /platform/i86pc/kernel/$ISADIR/unix +# module$ /platform/i86pc/$ISADIR/boot_archive + # # To override Solaris boot args (see kernel(1M)), console device and # properties set via eeprom(1M) edit the "kernel" line to: # -# kernel /platform/i86pc/multiboot <boot-args> -B prop1=val1,prop2=val2,... +# kernel /platform/i86pc/kernel/unix <boot-args> -B prop1=val1,prop2=val2,... # diff --git a/usr/src/lib/libc/amd64/threads/amd64.il b/usr/src/lib/libc/amd64/threads/amd64.il index fd1e080571..92b55caaad 100644 --- a/usr/src/lib/libc/amd64/threads/amd64.il +++ b/usr/src/lib/libc/amd64/threads/amd64.il @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -30,12 +29,7 @@ .end .inline __curthread, 0 - xorq %rax, %rax - movw %fs, %ax - andq %rax, %rax - je 1f movq %fs:0, %rax -1: .end .inline stkptr, 0 diff --git a/usr/src/lib/libc/amd64/threads/machdep.c b/usr/src/lib/libc/amd64/threads/machdep.c index dd8b7e3e3b..d600fb4cd5 100644 --- a/usr/src/lib/libc/amd64/threads/machdep.c +++ b/usr/src/lib/libc/amd64/threads/machdep.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -46,8 +45,7 @@ setup_context(ucontext_t *ucp, void *(*func)(ulwp_t *), /* setup to store the current thread pointer in %fs */ ucp->uc_mcontext.gregs[REG_FSBASE] = (greg_t)ulwp; - ulwp->ul_gs = LWPFS_SEL; - ucp->uc_mcontext.gregs[REG_FS] = (greg_t)ulwp->ul_gs; + ucp->uc_mcontext.gregs[REG_FS] = 0; /* null selector indicates fsbase */ /* all contexts should have a valid data segment descriptor for %ss */ ucp->uc_mcontext.gregs[REG_SS] = UDS_SEL; diff --git a/usr/src/lib/libc/i386/threads/i386.il b/usr/src/lib/libc/i386/threads/i386.il index f0606c7f79..e37be525e2 100644 --- a/usr/src/lib/libc/i386/threads/i386.il +++ b/usr/src/lib/libc/i386/threads/i386.il @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,12 +30,7 @@ .end .inline __curthread, 0 - xorl %eax, %eax - movw %gs, %ax - andl %eax, %eax - je 1f movl %gs:0, %eax -1: .end .inline stkptr, 0 diff --git a/usr/src/lib/libc/i386/threads/machdep.c b/usr/src/lib/libc/i386/threads/machdep.c index 9062a29d9b..56e7446924 100644 --- a/usr/src/lib/libc/i386/threads/machdep.c +++ b/usr/src/lib/libc/i386/threads/machdep.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -74,8 +73,7 @@ setup_context(ucontext_t *ucp, void *(*func)(ulwp_t *), * on the other side of __lwp_create(). */ ucp->uc_mcontext.gregs[ESP] = (greg_t)ulwp; - ulwp->ul_gs = LWPGS_SEL; - ucp->uc_mcontext.gregs[GS] = (greg_t)ulwp->ul_gs; + ucp->uc_mcontext.gregs[GS] = (greg_t)LWPGS_SEL; /* top-of-stack must be rounded down to STACK_ALIGN */ stack = (uint32_t *)(((uintptr_t)stk + stksize) & ~(STACK_ALIGN-1)); diff --git a/usr/src/lib/libc/inc/thr_inlines.h b/usr/src/lib/libc/inc/thr_inlines.h index e49ac97501..4e2f469488 100644 --- a/usr/src/lib/libc/inc/thr_inlines.h +++ b/usr/src/lib/libc/inc/thr_inlines.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -56,28 +56,14 @@ __curthread(void) ulwp_t *__value; __asm__ __volatile__( #if defined(__amd64) - "xorq %0, %0\n\t" - "mov %%fs, %0\n\t" - "andq %0, %0\n\t" - "je 1f\n\t" "movq %%fs:0, %0\n\t" #elif defined(__i386) - "xorl %0, %0\n\t" - "mov %%gs, %0\n\t" - "andl %0, %0\n\t" - "je 1f\n\t" "movl %%gs:0, %0\n\t" #elif defined(__sparcv9) ".register %%g7, #scratch\n\t" - "tst %%g7\n\t" - "be,a,pn %%xcc, 1f\n\t" - " mov %%g0, %0\n\t" "ldx [%%g7 + 80], %0\n\t" #elif defined(__sparc) ".register %%g7, #scratch\n\t" - "tst %%g7\n\t" - "be,a 1f\n\t" - " mov %%g0, %0\n\t" "ld [%%g7 + 80], %0\n\t" #else #error "port me" diff --git a/usr/src/lib/libc/inc/thr_uberdata.h b/usr/src/lib/libc/inc/thr_uberdata.h index b5ecc7a1be..4e14f05997 100644 --- a/usr/src/lib/libc/inc/thr_uberdata.h +++ b/usr/src/lib/libc/inc/thr_uberdata.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -522,7 +522,7 @@ typedef struct ulwp { uberflags_t *volatile ul_schedctl_called; /* ul_schedctl is set up */ volatile sc_shared_t *volatile ul_schedctl; /* schedctl data */ int ul_bindflags; /* bind_guard() interface to ld.so.1 */ - int ul_gs; /* x86 only: value of %gs/%fs */ + int ul_pad2; tsd_t *ul_stsd; /* slow TLS for keys >= TSD_NFAST */ void *ul_ftsd[TSD_NFAST]; /* fast TLS for keys < TSD_NFAST */ td_evbuf_t ul_td_evbuf; /* event buffer */ @@ -892,7 +892,7 @@ typedef struct ulwp32 { caddr32_t ul_schedctl_called; /* ul_schedctl is set up */ caddr32_t ul_schedctl; /* schedctl data */ int ul_bindflags; /* bind_guard() interface to ld.so.1 */ - int ul_gs; /* x86 only: value of %gs/%fs */ + int ul_pad2; caddr32_t ul_stsd; /* slow TLS for keys >= TSD_NFAST */ caddr32_t ul_ftsd[TSD_NFAST]; /* fast TLS for keys < TSD_NFAST */ td_evbuf32_t ul_td_evbuf; /* event buffer */ diff --git a/usr/src/lib/libc/port/threads/sigaction.c b/usr/src/lib/libc/port/threads/sigaction.c index 5f65435999..529530f2af 100644 --- a/usr/src/lib/libc/port/threads/sigaction.c +++ b/usr/src/lib/libc/port/threads/sigaction.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -531,9 +531,9 @@ _private_setcontext(const ucontext_t *ucp) #if defined(__sparc) uc.uc_mcontext.gregs[REG_G7] = (greg_t)self; #elif defined(__amd64) - uc.uc_mcontext.gregs[REG_FS] = (greg_t)self->ul_gs; + uc.uc_mcontext.gregs[REG_FS] = (greg_t)0; /* null for fsbase */ #elif defined(__i386) - uc.uc_mcontext.gregs[GS] = (greg_t)self->ul_gs; + uc.uc_mcontext.gregs[GS] = (greg_t)LWPGS_SEL; #else #error "none of __sparc, __amd64, __i386 defined" #endif diff --git a/usr/src/lib/libc/port/threads/thr.c b/usr/src/lib/libc/port/threads/thr.c index ac023cf5aa..4df8a78ade 100644 --- a/usr/src/lib/libc/port/threads/thr.c +++ b/usr/src/lib/libc/port/threads/thr.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -838,7 +838,6 @@ _thrp_exit() int ix = self->ul_ix; /* the hash index */ (void) _private_memcpy(replace, self, REPLACEMENT_SIZE); replace->ul_self = replace; - replace->ul_gs = 0; /* clone does not carry %gs */ replace->ul_next = NULL; /* clone not on stack list */ replace->ul_mapsiz = 0; /* allows clone to be freed */ replace->ul_replace = 1; /* requires clone to be freed */ @@ -1417,9 +1416,9 @@ libc_init(void) self->ul_nocancel = 1; #if defined(__amd64) - self->ul_gs = ___lwp_private(_LWP_SETPRIVATE, _LWP_FSBASE, self); + (void) ___lwp_private(_LWP_SETPRIVATE, _LWP_FSBASE, self); #elif defined(__i386) - self->ul_gs = ___lwp_private(_LWP_SETPRIVATE, _LWP_GSBASE, self); + (void) ___lwp_private(_LWP_SETPRIVATE, _LWP_GSBASE, self); #endif /* __i386 || __amd64 */ set_curthread(self); /* redundant on i386 */ /* diff --git a/usr/src/lib/libc/sparc/threads/sparc.il b/usr/src/lib/libc/sparc/threads/sparc.il index ba0ff4a938..c3f81e69b3 100644 --- a/usr/src/lib/libc/sparc/threads/sparc.il +++ b/usr/src/lib/libc/sparc/threads/sparc.il @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,11 +32,7 @@ .inline __curthread, 0 .register %g7, #scratch - tst %g7 - be,a 1f - mov %g0, %o0 ld [%g7 + 80], %o0 ! ul_self -1: .end .inline stkptr, 0 diff --git a/usr/src/lib/libc/sparcv9/threads/sparcv9.il b/usr/src/lib/libc/sparcv9/threads/sparcv9.il index d3fa907f8e..f84623f93c 100644 --- a/usr/src/lib/libc/sparcv9/threads/sparcv9.il +++ b/usr/src/lib/libc/sparcv9/threads/sparcv9.il @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,11 +32,7 @@ .inline __curthread, 0 .register %g7, #scratch - tst %g7 - be,a,pn %xcc, 1f - mov %g0, %o0 ldx [%g7 + 80], %o0 ! ul_self -1: .end .inline stkptr, 0 diff --git a/usr/src/lib/libdtrace/common/dt_module.c b/usr/src/lib/libdtrace/common/dt_module.c index 46ad7c6529..54f6c87e11 100644 --- a/usr/src/lib/libdtrace/common/dt_module.c +++ b/usr/src/lib/libdtrace/common/dt_module.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -927,11 +926,14 @@ dtrace_update(dtrace_hdl_t *dtp) /* * Cache the pointers to the modules representing the base executable - * and the run-time linker in the dtrace client handle. We should - * probably have a more generic way of inquiring as to their names. + * and the run-time linker in the dtrace client handle. Note that on + * x86 krtld is folded into unix, so if we don't find it, use unix + * instead. */ dtp->dt_exec = dt_module_lookup_by_name(dtp, "genunix"); dtp->dt_rtld = dt_module_lookup_by_name(dtp, "krtld"); + if (dtp->dt_rtld == NULL) + dtp->dt_rtld = dt_module_lookup_by_name(dtp, "unix"); /* * If this is the first time we are initializing the module list, diff --git a/usr/src/pkgdefs/Makefile b/usr/src/pkgdefs/Makefile index 6a8a27e0e9..7c229c9b37 100644 --- a/usr/src/pkgdefs/Makefile +++ b/usr/src/pkgdefs/Makefile @@ -121,9 +121,10 @@ i386_SUBDIRS= \ SUNWdrmr \ SUNWgrub \ SUNWgrubS \ - SUNWkvm.i \ + SUNWkvm.i \ SUNWlxr \ SUNWlxu \ + SUNWmv88sx \ SUNWonmtst.i \ SUNWos86r \ SUNWpsdcr \ @@ -134,7 +135,7 @@ i386_SUBDIRS= \ SUNWrtls \ SUNWsi3124 \ SUNWvia823x \ - SUNWmv88sx + SUNWxsvc i386_XMODS= \ SUNWadpu320 \ diff --git a/usr/src/pkgdefs/SUNWagp/prototype_i386 b/usr/src/pkgdefs/SUNWagp/prototype_i386 index 8d6c472610..15be4c0023 100644 --- a/usr/src/pkgdefs/SUNWagp/prototype_i386 +++ b/usr/src/pkgdefs/SUNWagp/prototype_i386 @@ -1,5 +1,5 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -25,15 +25,13 @@ # # SUNWagp # -d none platform 0755 root sys -d none platform/i86pc 0755 root sys -d none platform/i86pc/kernel 0755 root sys -d none platform/i86pc/kernel/drv 0755 root sys -f none platform/i86pc/kernel/drv/agpgart 0755 root sys -f none platform/i86pc/kernel/drv/agpgart.conf 0644 root sys -f none platform/i86pc/kernel/drv/amd64_gart 0755 root sys -f none platform/i86pc/kernel/drv/agptarget 0755 root sys -d none platform/i86pc/kernel/drv/amd64 0755 root sys -f none platform/i86pc/kernel/drv/amd64/agpgart 0755 root sys -f none platform/i86pc/kernel/drv/amd64/amd64_gart 0755 root sys -f none platform/i86pc/kernel/drv/amd64/agptarget 0755 root sys +d none kernel 0755 root sys +d none kernel/drv 0755 root sys +f none kernel/drv/agpgart 0755 root sys +f none kernel/drv/agpgart.conf 0644 root sys +f none kernel/drv/amd64_gart 0755 root sys +f none kernel/drv/agptarget 0755 root sys +d none kernel/drv/amd64 0755 root sys +f none kernel/drv/amd64/agpgart 0755 root sys +f none kernel/drv/amd64/amd64_gart 0755 root sys +f none kernel/drv/amd64/agptarget 0755 root sys diff --git a/usr/src/pkgdefs/SUNWcakr.i/prototype_com b/usr/src/pkgdefs/SUNWcakr.i/prototype_com index 2f83aab47d..4c95f6f92f 100644 --- a/usr/src/pkgdefs/SUNWcakr.i/prototype_com +++ b/usr/src/pkgdefs/SUNWcakr.i/prototype_com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -51,12 +51,17 @@ f none boot/solaris/bin/create_diskmap 0555 root sys f none boot/solaris/bin/create_ramdisk 0555 root sys f none boot/solaris/bin/mbr 0555 root sys s none boot/solaris/bin/root_archive=../../../usr/sbin/root_archive +f none boot/solaris/bin/symdef 0555 root sys +f none boot/solaris/bin/update_grub 0555 root sys f none boot/solaris/filelist.ramdisk 0644 root sys f none boot/solaris/filelist.safe 0644 root sys +d none boot/platform 755 root sys +d none boot/platform/i86pc 755 root sys +d none boot/platform/i86pc/kernel 755 root sys +f none boot/platform/i86pc/kernel/unix 755 root sys d none platform 755 root sys d none platform/i86pc 755 root sys -f none platform/i86pc/biosint 755 root sys -f none platform/i86pc/multiboot 755 root sys +d none platform/i86pc/amd64 755 root sys d none platform/i86pc/kernel 755 root sys d none platform/i86pc/kernel/amd64 755 root sys f none platform/i86pc/kernel/amd64/unix 755 root sys @@ -66,54 +71,34 @@ f none platform/i86pc/kernel/cpu/amd64/cpu.AuthenticAMD.15 755 root sys f none platform/i86pc/kernel/cpu/amd64/cpu.generic 755 root sys f none platform/i86pc/kernel/cpu/cpu.AuthenticAMD.15 755 root sys f none platform/i86pc/kernel/cpu/cpu.generic 755 root sys +d none platform/i86pc/kernel/dacf 755 root sys +f none platform/i86pc/kernel/dacf/consconfig_dacf 755 root sys +d none platform/i86pc/kernel/dacf/amd64 755 root sys +f none platform/i86pc/kernel/dacf/amd64/consconfig_dacf 755 root sys d none platform/i86pc/kernel/drv 755 root sys d none platform/i86pc/kernel/drv/amd64 755 root sys -f none platform/i86pc/kernel/drv/amd64/bmc 755 root sys -f none platform/i86pc/kernel/drv/amd64/bscbus 755 root sys -f none platform/i86pc/kernel/drv/amd64/bscv 755 root sys f none platform/i86pc/kernel/drv/amd64/isa 755 root sys -f none platform/i86pc/kernel/drv/amd64/kb8042 755 root sys f none platform/i86pc/kernel/drv/amd64/mc-amd 755 root sys f none platform/i86pc/kernel/drv/amd64/npe 755 root sys f none platform/i86pc/kernel/drv/amd64/pci 755 root sys -f none platform/i86pc/kernel/drv/amd64/pci_pci 755 root sys -f none platform/i86pc/kernel/drv/amd64/pcie_pci 755 root sys -f none platform/i86pc/kernel/drv/amd64/power 755 root sys f none platform/i86pc/kernel/drv/amd64/rootnex 755 root sys -f none platform/i86pc/kernel/drv/bmc 755 root sys -f none platform/i86pc/kernel/drv/bmc.conf 644 root sys -f none platform/i86pc/kernel/drv/bscbus 755 root sys -f none platform/i86pc/kernel/drv/bscbus.conf 644 root sys -f none platform/i86pc/kernel/drv/bscv 755 root sys -f none platform/i86pc/kernel/drv/bscv.conf 644 root sys f none platform/i86pc/kernel/drv/isa 755 root sys -f none platform/i86pc/kernel/drv/kb8042 755 root sys f none platform/i86pc/kernel/drv/mc-amd 755 root sys f none platform/i86pc/kernel/drv/mc-amd.conf 644 root sys f none platform/i86pc/kernel/drv/npe 755 root sys f none platform/i86pc/kernel/drv/pci 755 root sys -f none platform/i86pc/kernel/drv/pci_pci 755 root sys -f none platform/i86pc/kernel/drv/pcie_pci 755 root sys -f none platform/i86pc/kernel/drv/pcie_pci.conf 644 root sys -f none platform/i86pc/kernel/drv/power 755 root sys -f none platform/i86pc/kernel/drv/power.conf 644 root sys f none platform/i86pc/kernel/drv/rootnex 755 root sys d none platform/i86pc/kernel/mach 755 root sys +f none platform/i86pc/kernel/mach/pcplusmp 755 root sys d none platform/i86pc/kernel/mach/amd64 755 root sys +f none platform/i86pc/kernel/mach/amd64/pcplusmp 755 root sys f none platform/i86pc/kernel/mach/amd64/uppc 755 root sys f none platform/i86pc/kernel/mach/uppc 755 root sys d none platform/i86pc/kernel/misc 755 root sys d none platform/i86pc/kernel/misc/amd64 755 root sys -f none platform/i86pc/kernel/misc/amd64/agpmaster 755 root sys -f none platform/i86pc/kernel/misc/amd64/bootdev 755 root sys f none platform/i86pc/kernel/misc/amd64/gfx_private 755 root sys -f none platform/i86pc/kernel/misc/amd64/pci_autoconfig 755 root sys f none platform/i86pc/kernel/misc/amd64/pcie 755 root sys -f none platform/i86pc/kernel/misc/amd64/pciehpc 755 root sys -f none platform/i86pc/kernel/misc/agpmaster 755 root sys -f none platform/i86pc/kernel/misc/bootdev 755 root sys f none platform/i86pc/kernel/misc/gfx_private 755 root sys -f none platform/i86pc/kernel/misc/pci_autoconfig 755 root sys -f none platform/i86pc/kernel/misc/pciehpc 755 root sys f none platform/i86pc/kernel/misc/pcie 755 root sys f none platform/i86pc/kernel/unix 755 root sys +f none platform/i86pc/multiboot 755 root sys diff --git a/usr/src/pkgdefs/SUNWckr/prototype_i386 b/usr/src/pkgdefs/SUNWckr/prototype_i386 index 5197d98759..fba5fac922 100644 --- a/usr/src/pkgdefs/SUNWckr/prototype_i386 +++ b/usr/src/pkgdefs/SUNWckr/prototype_i386 @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -56,11 +56,16 @@ f none kernel/crypto/rsa 755 root sys f none kernel/crypto/sha1 755 root sys f none kernel/crypto/sha2 755 root sys f none kernel/crypto/swrand 755 root sys -f none kernel/dacf/consconfig_dacf 755 root sys f none kernel/devname/sdev_nsconfig_mod 755 root sys f none kernel/drv/aggr 755 root sys f none kernel/drv/arp 755 root sys f none kernel/drv/bl 755 root sys +f none kernel/drv/bmc 755 root sys +f none kernel/drv/bmc.conf 644 root sys +f none kernel/drv/bscbus 755 root sys +f none kernel/drv/bscbus.conf 644 root sys +f none kernel/drv/bscv 755 root sys +f none kernel/drv/bscv.conf 644 root sys f none kernel/drv/clone 755 root sys f none kernel/drv/cn 755 root sys f none kernel/drv/conskbd 755 root sys @@ -83,6 +88,7 @@ f none kernel/drv/ippctl 755 root sys f none kernel/drv/ipsecah 755 root sys f none kernel/drv/ipsecesp 755 root sys f none kernel/drv/iwscn 755 root sys +f none kernel/drv/kb8042 755 root sys f none kernel/drv/keysock 755 root sys f none kernel/drv/kmdb 755 root sys f none kernel/drv/kssl 755 root sys @@ -95,10 +101,15 @@ f none kernel/drv/mpt.conf 644 root sys f none kernel/drv/mouse8042 755 root sys f none kernel/drv/openeepr 755 root sys f none kernel/drv/options 755 root sys +f none kernel/drv/pci_pci 755 root sys f none kernel/drv/pci_to_i2o 755 root sys f none kernel/drv/pci_to_i2o.conf 644 root sys +f none kernel/drv/pcie_pci 755 root sys +f none kernel/drv/pcie_pci.conf 644 root sys f none kernel/drv/physmem 755 root sys f none kernel/drv/poll 755 root sys +f none kernel/drv/power 755 root sys +f none kernel/drv/power.conf 644 root sys f none kernel/drv/pseudo 755 root sys f none kernel/drv/ptc 755 root sys f none kernel/drv/ptsl 755 root sys @@ -152,6 +163,8 @@ d none boot/acpi/tables 755 root sys f none kernel/mac/mac_ether 755 root sys f none kernel/mac/mac_wifi 755 root sys f none kernel/misc/acpica 755 root sys +f none kernel/misc/agpmaster 755 root sys +f none kernel/misc/bootdev 755 root sys f none kernel/misc/busra 755 root sys f none kernel/misc/cardbus 755 root sys f none kernel/misc/cmlb 755 root sys @@ -168,13 +181,14 @@ f none kernel/misc/ipc 755 root sys f none kernel/misc/kbtrans 755 root sys f none kernel/misc/kcf 755 root sys f none kernel/misc/kmdbmod 755 root sys -f none kernel/misc/krtld 755 root sys f none kernel/misc/mac 755 root sys l none kernel/misc/md5=../../kernel/crypto/md5 f none kernel/misc/net80211 755 root sys f none kernel/misc/neti 755 root sys f none kernel/misc/pcicfg 755 root sys +f none kernel/misc/pciehpc 755 root sys f none kernel/misc/pcihp 755 root sys +f none kernel/misc/pci_autoconfig 755 root sys f none kernel/misc/pcmcia 755 root sys f none kernel/misc/rpcsec 755 root sys f none kernel/misc/sata 755 root sys @@ -184,7 +198,6 @@ l none kernel/misc/sha2=../../kernel/crypto/sha2 f none kernel/misc/strplumb 755 root sys f none kernel/misc/tem 755 root sys f none kernel/misc/tlimod 755 root sys -f none kernel/misc/zmod 755 root sys f none kernel/sched/TS 755 root sys f none kernel/sched/TS_DPTBL 755 root sys f none kernel/strmod/6to4tun 755 root sys @@ -238,14 +251,15 @@ f none kernel/crypto/amd64/rsa 755 root sys f none kernel/crypto/amd64/sha1 755 root sys f none kernel/crypto/amd64/sha2 755 root sys f none kernel/crypto/amd64/swrand 755 root sys -d none kernel/dacf/amd64 755 root sys -f none kernel/dacf/amd64/consconfig_dacf 755 root sys d none kernel/devname/amd64 755 root sys f none kernel/devname/amd64/sdev_nsconfig_mod 755 root sys d none kernel/drv/amd64 755 root sys f none kernel/drv/amd64/aggr 755 root sys f none kernel/drv/amd64/arp 755 root sys f none kernel/drv/amd64/bl 755 root sys +f none kernel/drv/amd64/bmc 755 root sys +f none kernel/drv/amd64/bscbus 755 root sys +f none kernel/drv/amd64/bscv 755 root sys f none kernel/drv/amd64/clone 755 root sys f none kernel/drv/amd64/cn 755 root sys f none kernel/drv/amd64/conskbd 755 root sys @@ -264,6 +278,7 @@ f none kernel/drv/amd64/ippctl 755 root sys f none kernel/drv/amd64/ipsecah 755 root sys f none kernel/drv/amd64/ipsecesp 755 root sys f none kernel/drv/amd64/iwscn 755 root sys +f none kernel/drv/amd64/kb8042 755 root sys f none kernel/drv/amd64/keysock 755 root sys f none kernel/drv/amd64/kmdb 755 root sys f none kernel/drv/amd64/kssl 755 root sys @@ -275,8 +290,11 @@ f none kernel/drv/amd64/mpt 755 root sys f none kernel/drv/amd64/mouse8042 755 root sys f none kernel/drv/amd64/openeepr 755 root sys f none kernel/drv/amd64/options 755 root sys +f none kernel/drv/amd64/pci_pci 755 root sys +f none kernel/drv/amd64/pcie_pci 755 root sys f none kernel/drv/amd64/physmem 755 root sys f none kernel/drv/amd64/poll 755 root sys +f none kernel/drv/amd64/power 755 root sys f none kernel/drv/amd64/pseudo 755 root sys f none kernel/drv/amd64/ptc 755 root sys f none kernel/drv/amd64/ptsl 755 root sys @@ -331,6 +349,8 @@ f none kernel/mac/amd64/mac_ether 755 root sys f none kernel/mac/amd64/mac_wifi 755 root sys d none kernel/misc/amd64 755 root sys f none kernel/misc/amd64/acpica 755 root sys +f none kernel/misc/amd64/agpmaster 755 root sys +f none kernel/misc/amd64/bootdev 755 root sys f none kernel/misc/amd64/busra 755 root sys f none kernel/misc/amd64/cardbus 755 root sys f none kernel/misc/amd64/cmlb 755 root sys @@ -346,13 +366,14 @@ f none kernel/misc/amd64/ipc 755 root sys f none kernel/misc/amd64/kbtrans 755 root sys f none kernel/misc/amd64/kcf 755 root sys f none kernel/misc/amd64/kmdbmod 755 root sys -f none kernel/misc/amd64/krtld 755 root sys f none kernel/misc/amd64/mac 755 root sys l none kernel/misc/amd64/md5=../../../kernel/crypto/amd64/md5 f none kernel/misc/amd64/net80211 755 root sys f none kernel/misc/amd64/neti 755 root sys f none kernel/misc/amd64/pcicfg 755 root sys +f none kernel/misc/amd64/pciehpc 755 root sys f none kernel/misc/amd64/pcihp 755 root sys +f none kernel/misc/amd64/pci_autoconfig 755 root sys f none kernel/misc/amd64/pcmcia 755 root sys f none kernel/misc/amd64/rpcsec 755 root sys f none kernel/misc/amd64/sata 755 root sys @@ -362,7 +383,6 @@ l none kernel/misc/amd64/sha2=../../../kernel/crypto/amd64/sha2 f none kernel/misc/amd64/strplumb 755 root sys f none kernel/misc/amd64/tem 755 root sys f none kernel/misc/amd64/tlimod 755 root sys -f none kernel/misc/amd64/zmod 755 root sys d none kernel/sched/amd64 755 root sys f none kernel/sched/amd64/TS 755 root sys f none kernel/sched/amd64/TS_DPTBL 755 root sys diff --git a/usr/src/pkgdefs/SUNWckr/prototype_sparc b/usr/src/pkgdefs/SUNWckr/prototype_sparc index 9050ad70bb..4d29d7f36e 100644 --- a/usr/src/pkgdefs/SUNWckr/prototype_sparc +++ b/usr/src/pkgdefs/SUNWckr/prototype_sparc @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -191,7 +191,6 @@ f none kernel/misc/sparcv9/strplumb 755 root sys f none kernel/misc/sparcv9/swapgeneric 755 root sys f none kernel/misc/sparcv9/tlimod 755 root sys f none kernel/misc/sparcv9/tem 755 root sys -f none kernel/misc/sparcv9/zmod 755 root sys d none kernel/sched/sparcv9 755 root sys f none kernel/sched/sparcv9/TS 755 root sys f none kernel/sched/sparcv9/TS_DPTBL 755 root sys diff --git a/usr/src/pkgdefs/SUNWcsr/postinstall b/usr/src/pkgdefs/SUNWcsr/postinstall index 88fe03318b..8184b02a5a 100644 --- a/usr/src/pkgdefs/SUNWcsr/postinstall +++ b/usr/src/pkgdefs/SUNWcsr/postinstall @@ -124,6 +124,21 @@ if [ -x /usr/sbin/svcadm -a -x /usr/sbin/svccfg -a \ fi # +# If the eeprom service is present, remove it. We can't use +# /var/svc/profile/upgrade as it runs before manifest-import. +# +/usr/sbin/svccfg -s svc:/platform/i86pc/eeprom:default end >/dev/null 2>&1 +if [ "$?" = 0 ]; then + if [ -r $PKG_INSTALL_ROOT/etc/svc/volatile/repository_door ]; then + svcadm disable -s svc:/platform/i86pc/eeprom:default \ + >/dev/null 2>&1 + fi + svccfg delete svc:/platform/i86pc/eeprom >/dev/null 2>&1 + rm -f $PKG_INSTALL_ROOT/var/svc/profile/platform_i86pc.xml + rm -f $PKG_INSTALL_ROOT/var/svc/profile/platform.xml +fi + +# # svc:/network/rpc/keyserv is expected to be off on systems that don't # set domainname. On systems that do define a default domain, leave the # setting as previously set. diff --git a/usr/src/pkgdefs/SUNWcsr/prototype_i386 b/usr/src/pkgdefs/SUNWcsr/prototype_i386 index 84084dd378..2cb46da075 100644 --- a/usr/src/pkgdefs/SUNWcsr/prototype_i386 +++ b/usr/src/pkgdefs/SUNWcsr/prototype_i386 @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -40,7 +40,7 @@ # !include prototype_com # -# List files which are I386 specific here +# List files which are i386 specific here # # source locations relative to the prototype file # @@ -51,6 +51,4 @@ f none sbin/biosdev 555 root bin f none sbin/installgrub 0555 root sys d none var/ld/amd64 755 root bin s none var/ld/64=amd64 -d none var/svc/manifest/platform/i86pc 755 root sys f none var/svc/manifest/system/boot-archive-update.xml 0444 root sys -f none var/svc/profile/platform_i86pc.xml 444 root sys diff --git a/usr/src/pkgdefs/SUNWcsu/prototype_com b/usr/src/pkgdefs/SUNWcsu/prototype_com index f369ae52cf..d5022de6ba 100644 --- a/usr/src/pkgdefs/SUNWcsu/prototype_com +++ b/usr/src/pkgdefs/SUNWcsu/prototype_com @@ -733,7 +733,7 @@ f none usr/sbin/dminfo 555 root bin l none usr/sbin/drvconfig=./devfsadm f none usr/sbin/dumpadm 555 root bin s none usr/sbin/edquota=../lib/fs/ufs/edquota -l none usr/sbin/eeprom=../../usr/lib/platexec +f none usr/sbin/eeprom 2555 root bin s none usr/sbin/fdisk=../../sbin/fdisk f none usr/sbin/ff 555 root bin f none usr/sbin/fmthard 555 root sys @@ -802,7 +802,6 @@ l none usr/sbin/ports=./devfsadm l none usr/sbin/poweroff=./halt f none usr/sbin/praudit 555 root bin l none usr/sbin/prtconf=../../usr/lib/isaexec -l none usr/sbin/prtdiag=../../usr/lib/platexec f none usr/sbin/prtvtoc 555 root sys f none usr/sbin/psradm 555 root sys f none usr/sbin/psrinfo 555 root sys diff --git a/usr/src/pkgdefs/SUNWcsu/prototype_i386 b/usr/src/pkgdefs/SUNWcsu/prototype_i386 index 7dffa22aad..2b7a59b851 100644 --- a/usr/src/pkgdefs/SUNWcsu/prototype_i386 +++ b/usr/src/pkgdefs/SUNWcsu/prototype_i386 @@ -80,8 +80,10 @@ f none usr/kernel/strmod/cryptmod 755 root sys f none usr/kernel/sys/acctctl 755 root sys f none usr/kernel/sys/exacctsys 755 root sys f none usr/kernel/sys/sysacct 755 root sys +f none usr/lib/devfsadm/linkmod/SUNW_ieee1394_link.so 755 root sys f none usr/lib/devfsadm/linkmod/SUNW_misc_link_i386.so 755 root sys s none usr/sbin/installgrub=../../sbin/installgrub +f none usr/sbin/prtdiag 2755 root sys f none usr/sbin/rtc 555 root bin d none usr/sbin/i86 755 root bin f none usr/sbin/i86/add_drv 555 root sys @@ -138,7 +140,6 @@ d none usr/kernel/sys/amd64 755 root sys f none usr/kernel/sys/amd64/acctctl 755 root sys f none usr/kernel/sys/amd64/exacctsys 755 root sys f none usr/kernel/sys/amd64/sysacct 755 root sys -f none usr/lib/devfsadm/linkmod/SUNW_ieee1394_link.so 755 root sys d none usr/lib/secure/amd64 755 root bin s none usr/lib/secure/64=amd64 d none usr/lib/amd64 755 root bin diff --git a/usr/src/pkgdefs/SUNWcsu/prototype_sparc b/usr/src/pkgdefs/SUNWcsu/prototype_sparc index a53f2c1703..281413f974 100644 --- a/usr/src/pkgdefs/SUNWcsu/prototype_sparc +++ b/usr/src/pkgdefs/SUNWcsu/prototype_sparc @@ -98,6 +98,7 @@ d none usr/lib/secure/sparcv9 755 root bin s none usr/lib/secure/64=sparcv9 d none usr/lib/sparcv9 755 root bin s none usr/lib/sparcv9/ld.so.1=../../../lib/sparcv9/ld.so.1 +l none usr/sbin/prtdiag=../../usr/lib/platexec d none usr/sbin/sparcv9 755 root bin f none usr/sbin/sparcv9/add_drv 555 root sys f none usr/sbin/sparcv9/modinfo 555 root sys diff --git a/usr/src/pkgdefs/SUNWdrmr/prototype_i386 b/usr/src/pkgdefs/SUNWdrmr/prototype_i386 index 972bf8af95..d7cfd7f00c 100755 --- a/usr/src/pkgdefs/SUNWdrmr/prototype_i386 +++ b/usr/src/pkgdefs/SUNWdrmr/prototype_i386 @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -47,14 +47,11 @@ # SUNWdrmr # d none kernel 0755 root sys +d none kernel/drv 0755 root sys +f none kernel/drv/i915 0755 root sys +d none kernel/drv/amd64 0755 root sys +f none kernel/drv/amd64/i915 0755 root sys d none kernel/misc 0755 root sys f none kernel/misc/drm 0755 root sys d none kernel/misc/amd64 0755 root sys f none kernel/misc/amd64/drm 0755 root sys -d none platform 0755 root sys -d none platform/i86pc 0755 root sys -d none platform/i86pc/kernel 0755 root sys -d none platform/i86pc/kernel/drv 0755 root sys -f none platform/i86pc/kernel/drv/i915 0755 root sys -d none platform/i86pc/kernel/drv/amd64 0755 root sys -f none platform/i86pc/kernel/drv/amd64/i915 0755 root sys diff --git a/usr/src/pkgdefs/SUNWhea/prototype_i386 b/usr/src/pkgdefs/SUNWhea/prototype_i386 index 3d7a74517e..4fafdc6e72 100644 --- a/usr/src/pkgdefs/SUNWhea/prototype_i386 +++ b/usr/src/pkgdefs/SUNWhea/prototype_i386 @@ -58,12 +58,13 @@ f none usr/include/asm/htable.h 644 root bin f none usr/include/asm/mmu.h 644 root bin d none usr/include/amd64 755 root bin d none usr/include/amd64/sys 755 root bin +f none usr/include/amd64/sys/kdi_regs.h 644 root bin f none usr/include/amd64/sys/privregs.h 644 root bin d none usr/include/ia32 755 root bin d none usr/include/ia32/sys 755 root bin f none usr/include/ia32/sys/asm_linkage.h 644 root bin +f none usr/include/ia32/sys/kdi_regs.h 644 root bin f none usr/include/ia32/sys/machtypes.h 644 root bin -f none usr/include/ia32/sys/mmu.h 644 root bin f none usr/include/ia32/sys/privregs.h 644 root bin f none usr/include/ia32/sys/psw.h 644 root bin f none usr/include/ia32/sys/pte.h 644 root bin @@ -71,6 +72,7 @@ f none usr/include/ia32/sys/reg.h 644 root bin f none usr/include/ia32/sys/stack.h 644 root bin f none usr/include/ia32/sys/trap.h 644 root bin f none usr/include/ia32/sys/traptrace.h 644 root bin +f none usr/include/sys/kdi_regs.h 644 root bin f none usr/include/stack_unwind.h 644 root bin f none usr/include/sys/bootregs.h 644 root bin f none usr/include/sys/bootsvcs.h 644 root bin @@ -91,19 +93,18 @@ f none usr/include/sys/i2o/i2oadptr.h 644 root bin f none usr/include/sys/i2o/i2obscsi.h 644 root bin f none usr/include/sys/i2o/i2omstr.h 644 root bin f none usr/include/sys/i8272A.h 644 root bin -f none usr/include/sys/immu.h 644 root bin f none usr/include/sys/kd.h 644 root bin f none usr/include/sys/mc.h 644 root bin f none usr/include/sys/mc_amd.h 644 root bin f none usr/include/sys/mca_amd.h 644 root bin f none usr/include/sys/mca_x86.h 644 root bin -f none usr/include/sys/mmu.h 644 root bin f none usr/include/sys/mutex_impl.h 644 root bin f none usr/include/sys/obpdefs.h 644 root bin f none usr/include/sys/pcic_reg.h 644 root bin f none usr/include/sys/pcic_var.h 644 root bin f none usr/include/sys/pic.h 644 root bin f none usr/include/sys/pit.h 644 root bin +f none usr/include/sys/pmem.h 644 root bin f none usr/include/sys/privregs.h 644 root bin f none usr/include/sys/prom_emul.h 644 root bin f none usr/include/sys/prom_isa.h 644 root bin @@ -128,13 +129,15 @@ d none usr/platform/i86pc/include/sys 755 root bin f none usr/platform/i86pc/include/sys/asm_misc.h 644 root bin f none usr/platform/i86pc/include/sys/clock.h 644 root bin f none usr/platform/i86pc/include/sys/cram.h 644 root bin +f none usr/platform/i86pc/include/sys/debug_info.h 644 root bin f none usr/platform/i86pc/include/sys/ddi_subrdefs.h 644 root bin +f none usr/platform/i86pc/include/sys/mach_mmu.h 644 root bin f none usr/platform/i86pc/include/sys/machcpuvar.h 644 root bin f none usr/platform/i86pc/include/sys/machparam.h 644 root bin f none usr/platform/i86pc/include/sys/machsystm.h 644 root bin f none usr/platform/i86pc/include/sys/machthread.h 644 root bin f none usr/platform/i86pc/include/sys/memnode.h 644 root bin -f none usr/platform/i86pc/include/sys/pmem.h 644 root bin +f none usr/platform/i86pc/include/sys/pc_mmu.h 644 root bin f none usr/platform/i86pc/include/sys/psm.h 644 root bin f none usr/platform/i86pc/include/sys/psm_defs.h 644 root bin f none usr/platform/i86pc/include/sys/psm_modctl.h 644 root bin @@ -142,6 +145,7 @@ f none usr/platform/i86pc/include/sys/psm_types.h 644 root bin f none usr/platform/i86pc/include/sys/rm_platter.h 644 root bin f none usr/platform/i86pc/include/sys/smp_impldefs.h 644 root bin f none usr/platform/i86pc/include/sys/vm_machparam.h 644 root bin +f none usr/platform/i86pc/include/sys/xsvc.h 644 root bin f none usr/platform/i86pc/include/sys/x_call.h 644 root bin f none usr/platform/i86pc/include/sys/xc_levels.h 644 root bin d none usr/platform/i86pc/include/vm 755 root bin @@ -149,6 +153,7 @@ f none usr/platform/i86pc/include/vm/hat_i86.h 644 root bin f none usr/platform/i86pc/include/vm/hat_pte.h 644 root bin f none usr/platform/i86pc/include/vm/htable.h 644 root bin f none usr/platform/i86pc/include/vm/hment.h 644 root bin +f none usr/platform/i86pc/include/vm/kboot_mmu.h 644 root bin d none usr/share/src/uts/i86pc 755 root bin s none usr/share/src/uts/i86pc/sys=../../../../platform/i86pc/include/sys s none usr/share/src/uts/i86pc/vm=../../../../platform/i86pc/include/vm diff --git a/usr/src/pkgdefs/SUNWkvm.i/prototype_com b/usr/src/pkgdefs/SUNWkvm.i/prototype_com index c2e8d5e9f7..670d6aaae7 100644 --- a/usr/src/pkgdefs/SUNWkvm.i/prototype_com +++ b/usr/src/pkgdefs/SUNWkvm.i/prototype_com @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -46,11 +45,4 @@ i copyright d none usr 755 root sys d none usr/platform 755 root sys d none usr/platform/i86pc 755 root sys -d none usr/platform/i86pc/sbin 755 root bin -f none usr/platform/i86pc/sbin/eeprom 2555 root sys -f none usr/platform/i86pc/sbin/prtdiag 555 root sys d none usr/platform/i86pc/lib 755 root bin -# -# make the links to other machine types -# -s none usr/platform/ncri86pc=i86pc diff --git a/usr/src/pkgdefs/SUNWkvm.u/prototype_com b/usr/src/pkgdefs/SUNWkvm.u/prototype_com index a2acd42082..04066f8be5 100644 --- a/usr/src/pkgdefs/SUNWkvm.u/prototype_com +++ b/usr/src/pkgdefs/SUNWkvm.u/prototype_com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -97,24 +97,19 @@ s none usr/platform/SUNW,Sun-Blade-1500/sbin=../sun4u/sbin s none usr/platform/SUNW,Sun-Blade-2500/sbin=../sun4u/sbin s none usr/platform/SUNW,A70/sbin=../sun4u/sbin d none usr/platform/SUNW,SPARC-Enterprise/sbin 755 root bin -s none usr/platform/SUNW,SPARC-Enterprise/sbin/eeprom=../../sun4u/sbin/eeprom s none usr/platform/SUNW,SPARC-Enterprise/sbin/prtdiag=../../sun4u/sbin/prtdiag s none usr/platform/SUNW,SPARC-Enterprise/sbin/trapstat=../../sun4u/sbin/trapstat d none usr/platform/SUNW,Sun-Fire-V445/sbin 755 root bin -s none usr/platform/SUNW,Sun-Fire-V445/sbin/eeprom=../../sun4u/sbin/eeprom s none usr/platform/SUNW,Sun-Fire-V445/sbin/prtdiag=../../sun4u/sbin/prtdiag s none usr/platform/SUNW,Sun-Fire-V445/sbin/trapstat=../../sun4u/sbin/trapstat d none usr/platform/SUNW,Sun-Fire-V215/sbin 755 root bin -s none usr/platform/SUNW,Sun-Fire-V215/sbin/eeprom=../../sun4u/sbin/eeprom s none usr/platform/SUNW,Sun-Fire-V215/sbin/prtdiag=../../sun4u/sbin/prtdiag s none usr/platform/SUNW,Sun-Fire-V215/sbin/trapstat=../../sun4u/sbin/trapstat s none usr/platform/SUNW,Sun-Fire/sbin=../sun4u/sbin d none usr/platform/SUNW,Sun-Fire-V240/sbin 755 root bin -s none usr/platform/SUNW,Sun-Fire-V240/sbin/eeprom=../../sun4u/sbin/eeprom s none usr/platform/SUNW,Sun-Fire-V240/sbin/prtdiag=../../sun4u/sbin/prtdiag s none usr/platform/SUNW,Sun-Fire-V240/sbin/trapstat=../../sun4u/sbin/trapstat d none usr/platform/SUNW,Sun-Fire-V250/sbin 755 root bin -s none usr/platform/SUNW,Sun-Fire-V250/sbin/eeprom=../../sun4u/sbin/eeprom s none usr/platform/SUNW,Sun-Fire-V250/sbin/prtdiag=../../sun4u/sbin/prtdiag s none usr/platform/SUNW,Sun-Fire-V250/sbin/trapstat=../../sun4u/sbin/trapstat s none usr/platform/SUNW,Sun-Fire-V440/sbin=../SUNW,Sun-Fire-V240/sbin @@ -131,15 +126,12 @@ s none usr/platform/SUNW,UltraSPARC-IIi-Netract/sbin=../sun4u/sbin s none usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40/sbin=../sun4u/sbin s none usr/platform/SUNW,UltraSPARC-IIe-NetraCT-60/sbin=../sun4u/sbin d none usr/platform/SUNW,Netra-CP2300/sbin 755 root bin -s none usr/platform/SUNW,Netra-CP2300/sbin/eeprom=../../sun4u/sbin/eeprom s none usr/platform/SUNW,Netra-CP2300/sbin/prtdiag=../../sun4u/sbin/prtdiag s none usr/platform/SUNW,Netra-CP2300/sbin/trapstat=../../sun4u/sbin/trapstat d none usr/platform/SUNW,Netra-CP3010/sbin 755 root bin -s none usr/platform/SUNW,Netra-CP3010/sbin/eeprom=../../sun4u/sbin/eeprom s none usr/platform/SUNW,Netra-CP3010/sbin/prtdiag=../../sun4u/sbin/prtdiag s none usr/platform/SUNW,Netra-CP3010/sbin/trapstat=../../sun4u/sbin/trapstat # -f none usr/platform/sun4u/sbin/eeprom 2555 root sys f none usr/platform/sun4u/sbin/trapstat 555 root bin # diff --git a/usr/src/pkgdefs/SUNWkvm.v/prototype_com b/usr/src/pkgdefs/SUNWkvm.v/prototype_com index df2c3d72c7..0d388e4eff 100644 --- a/usr/src/pkgdefs/SUNWkvm.v/prototype_com +++ b/usr/src/pkgdefs/SUNWkvm.v/prototype_com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -51,7 +51,6 @@ d none usr/platform/sun4v 755 root sys d none usr/platform/sun4v/sbin 755 root bin # f none usr/platform/sun4v/sbin/trapstat 555 root bin -f none usr/platform/sun4v/sbin/eeprom 2555 root sys # # create lib directory for sun4v # diff --git a/usr/src/pkgdefs/SUNWos86r/prototype_i386 b/usr/src/pkgdefs/SUNWos86r/prototype_i386 index fb8dc7c93a..fdb964123b 100644 --- a/usr/src/pkgdefs/SUNWos86r/prototype_i386 +++ b/usr/src/pkgdefs/SUNWos86r/prototype_i386 @@ -20,7 +20,7 @@ # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -81,8 +81,6 @@ f none kernel/drv/elxl 755 root sys f none kernel/drv/elxl.conf 644 root sys f none kernel/drv/iprb 755 root sys f none kernel/drv/iprb.conf 644 root sys -f none kernel/drv/ncrs 755 root sys -f none kernel/drv/ncrs.conf 644 root sys f none kernel/drv/pcn 755 root sys f none kernel/drv/pcn.conf 644 root sys # EXPORT DELETE START @@ -93,14 +91,3 @@ d none kernel/drv/amd64 755 root sys f none kernel/drv/amd64/elxl 755 root sys f none kernel/drv/amd64/iprb 755 root sys f none kernel/drv/amd64/pcn 755 root sys -d none kernel/mach 755 root sys -f none kernel/mach/pcplusmp 755 root sys -d none kernel/mach/amd64 755 root sys -f none kernel/mach/amd64/pcplusmp 755 root sys -d none kernel/misc 755 root sys -d none var 755 root sys -d none var/svc 755 root sys -d none var/svc/manifest 755 root sys -d none var/svc/manifest/platform 755 root sys -d none var/svc/manifest/platform/i86pc 755 root sys -f manifest var/svc/manifest/platform/i86pc/eeprom.xml 0444 root sys diff --git a/usr/src/pkgdefs/SUNWpsdcr/prototype_i386 b/usr/src/pkgdefs/SUNWpsdcr/prototype_i386 index d147a9f963..345b187edd 100644 --- a/usr/src/pkgdefs/SUNWpsdcr/prototype_i386 +++ b/usr/src/pkgdefs/SUNWpsdcr/prototype_i386 @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -19,7 +18,7 @@ # # CDDL HEADER END # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -51,52 +50,47 @@ i preremove # d none kernel 755 root sys d none kernel/drv 755 root sys -# Following drv and misc modules are from SUNWcsr f none kernel/drv/asy 755 root sys f none kernel/drv/asy.conf 644 root sys f none kernel/drv/cmdk 755 root sys f none kernel/drv/cmdk.conf 644 root sys f none kernel/drv/ecpp 755 root sys f none kernel/drv/ecpp.conf 644 root sys +f none kernel/drv/fd 755 root sys +f none kernel/drv/fd.conf 644 root sys +f none kernel/drv/fdc.conf 644 root sys +f none kernel/drv/fdc 755 root sys +f none kernel/drv/logi 755 root sys +f none kernel/drv/msm 755 root sys +f none kernel/drv/ncrs 755 root sys +f none kernel/drv/ncrs.conf 644 root sys d none kernel/misc 755 root sys f none kernel/misc/dadk 755 root sys f none kernel/misc/gda 755 root sys f none kernel/misc/strategy 755 root sys +d none kernel/strmod 755 root sys +f none kernel/strmod/vuid2ps2 755 root sys +f none kernel/strmod/vuid3ps2 755 root sys +f none kernel/strmod/vuidm3p 755 root sys +f none kernel/strmod/vuidm4p 755 root sys +f none kernel/strmod/vuidm5p 755 root sys d none kernel/drv/amd64 755 root sys f none kernel/drv/amd64/asy 755 root sys f none kernel/drv/amd64/cmdk 755 root sys f none kernel/drv/amd64/ecpp 755 root sys +f none kernel/drv/amd64/fd 755 root sys +f none kernel/drv/amd64/fdc 755 root sys +f none kernel/drv/amd64/logi 755 root sys d none kernel/misc/amd64 755 root sys f none kernel/misc/amd64/dadk 755 root sys f none kernel/misc/amd64/gda 755 root sys f none kernel/misc/amd64/strategy 755 root sys +d none kernel/strmod/amd64 755 root sys +f none kernel/strmod/amd64/vuid2ps2 755 root sys +f none kernel/strmod/amd64/vuid3ps2 755 root sys +f none kernel/strmod/amd64/vuidm3p 755 root sys +f none kernel/strmod/amd64/vuidm4p 755 root sys +f none kernel/strmod/amd64/vuidm5p 755 root sys e preserve kernel/misc/sysinit 755 root sys e preserve kernel/misc/amd64/sysinit 755 root sys -# Following drivers are from SUNWcar.i -d none platform 755 root sys -d none platform/i86pc 755 root sys -d none platform/i86pc/kernel 755 root sys -d none platform/i86pc/kernel/drv 755 root sys -f none platform/i86pc/kernel/drv/fd 755 root sys -f none platform/i86pc/kernel/drv/fd.conf 644 root sys -f none platform/i86pc/kernel/drv/fdc.conf 644 root sys -f none platform/i86pc/kernel/drv/fdc 755 root sys -f none platform/i86pc/kernel/drv/logi 755 root sys -f none platform/i86pc/kernel/drv/msm 755 root sys -d none platform/i86pc/kernel/drv/amd64 755 root sys -f none platform/i86pc/kernel/drv/amd64/fd 755 root sys -f none platform/i86pc/kernel/drv/amd64/fdc 755 root sys -f none platform/i86pc/kernel/drv/amd64/logi 755 root sys -d none platform/i86pc/kernel/misc 755 root sys -d none platform/i86pc/kernel/strmod 755 root sys -f none platform/i86pc/kernel/strmod/vuid2ps2 755 root sys -f none platform/i86pc/kernel/strmod/vuid3ps2 755 root sys -f none platform/i86pc/kernel/strmod/vuidm3p 755 root sys -f none platform/i86pc/kernel/strmod/vuidm4p 755 root sys -f none platform/i86pc/kernel/strmod/vuidm5p 755 root sys -d none platform/i86pc/kernel/strmod/amd64 755 root sys -f none platform/i86pc/kernel/strmod/amd64/vuid2ps2 755 root sys -f none platform/i86pc/kernel/strmod/amd64/vuid3ps2 755 root sys -f none platform/i86pc/kernel/strmod/amd64/vuidm3p 755 root sys -f none platform/i86pc/kernel/strmod/amd64/vuidm4p 755 root sys -f none platform/i86pc/kernel/strmod/amd64/vuidm5p 755 root sys + diff --git a/usr/src/pkgdefs/SUNWpsdir/prototype_i386 b/usr/src/pkgdefs/SUNWpsdir/prototype_i386 index 35bd862170..0ffb0c26ce 100644 --- a/usr/src/pkgdefs/SUNWpsdir/prototype_i386 +++ b/usr/src/pkgdefs/SUNWpsdir/prototype_i386 @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -51,18 +50,22 @@ i preinstall # SUNWpsdir # # Following drivers are from SUNWcar.i +d none kernel 755 root sys +d none kernel/drv 755 root sys +f none kernel/drv/ata 755 root sys +e ataconf kernel/drv/ata.conf 644 root sys +f none kernel/drv/mscsi 755 root sys +f none kernel/drv/mscsi.conf 644 root sys +f none kernel/drv/sbpro 755 root sys +f none kernel/drv/sbpro.conf 644 root sys +d none kernel/drv/amd64 755 root sys +f none kernel/drv/amd64/ata 755 root sys + d none platform 755 root sys d none platform/i86pc 755 root sys d none platform/i86pc/kernel 755 root sys d none platform/i86pc/kernel/drv 755 root sys -f none platform/i86pc/kernel/drv/ata 755 root sys -e ataconf platform/i86pc/kernel/drv/ata.conf 644 root sys -f none platform/i86pc/kernel/drv/mscsi 755 root sys -f none platform/i86pc/kernel/drv/mscsi.conf 644 root sys f none platform/i86pc/kernel/drv/pci-ide 755 root sys f none platform/i86pc/kernel/drv/pci-ide.conf 644 root sys -f none platform/i86pc/kernel/drv/sbpro 755 root sys -f none platform/i86pc/kernel/drv/sbpro.conf 644 root sys d none platform/i86pc/kernel/drv/amd64 755 root sys -f none platform/i86pc/kernel/drv/amd64/ata 755 root sys f none platform/i86pc/kernel/drv/amd64/pci-ide 755 root sys diff --git a/usr/src/pkgdefs/SUNWxsvc/Makefile b/usr/src/pkgdefs/SUNWxsvc/Makefile new file mode 100644 index 0000000000..0e03136b09 --- /dev/null +++ b/usr/src/pkgdefs/SUNWxsvc/Makefile @@ -0,0 +1,37 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com + +DATAFILES += +CLOBBERFILES += $(MACHDATAFILES) + +.KEEP_STATE: + +all: $(FILES) $(MACHDATAFILES) +install: all pkg + +include ../Makefile.targ diff --git a/usr/src/pkgdefs/SUNWxsvc/depend b/usr/src/pkgdefs/SUNWxsvc/depend new file mode 100644 index 0000000000..9d7e7d4f42 --- /dev/null +++ b/usr/src/pkgdefs/SUNWxsvc/depend @@ -0,0 +1,52 @@ +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# ident "%Z%%M% %I% %E% SMI" +# +# This package information file defines software dependencies associated +# with the pkg. You can define three types of pkg dependencies with this file: +# P indicates a prerequisite for installation +# I indicates an incompatible package +# R indicates a reverse dependency +# <pkg.abbr> see pkginfo(4), PKG parameter +# <name> see pkginfo(4), NAME parameter +# <version> see pkginfo(4), VERSION parameter +# <arch> see pkginfo(4), ARCH parameter +# <type> <pkg.abbr> <name> +# (<arch>)<version> +# (<arch>)<version> +# ... +# <type> <pkg.abbr> <name> +# ... +# + +# Required system dependencies +P SUNWcar Core Architecture, (Root) +P SUNWcakr Core Solaris Kernel Architecture (Root) +P SUNWkvm Core Architecture, (Kvm) +P SUNWcsr Core Solaris, (Root) +P SUNWckr Core Solaris Kernel (Root) +P SUNWcnetr Core Solaris Network Infrastructure (Root) +P SUNWcsu Core Solaris, (Usr) +P SUNWcsd Core Solaris Devices +P SUNWcsl Core Solaris Libraries diff --git a/usr/src/pkgdefs/SUNWxsvc/pkginfo.tmpl b/usr/src/pkgdefs/SUNWxsvc/pkginfo.tmpl new file mode 100644 index 0000000000..70f40d326b --- /dev/null +++ b/usr/src/pkgdefs/SUNWxsvc/pkginfo.tmpl @@ -0,0 +1,50 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +# +# This required package information file describes characteristics of the +# package, such as package abbreviation, full package name, package version, +# and package architecture. +# +PKG="SUNWxsvc" +NAME="Sun Xserver pseudo driver" +ARCH="i386" +CATEGORY="system" +BASEDIR=/ +SUNW_PKGVERS="1.0" +SUNW_PKGTYPE="root" +CLASSES="none" +DESC="Sun Xserver pseudo driver" +SUNW_PRODNAME="SunOS" +SUNW_PRODVERS="RELEASE/VERSION" +VERSION="ONVERS,REV=0.0.0" +VENDOR="Sun Microsystems, Inc." +HOTLINE="Please contact your local service provider" +EMAIL="" +MAXINST="1000" +SUNW_PKG_ALLZONES="true" +SUNW_PKG_HOLLOW="true" +SUNW_PKG_THISZONE="false" diff --git a/usr/src/pkgdefs/SUNWxsvc/postinstall b/usr/src/pkgdefs/SUNWxsvc/postinstall new file mode 100644 index 0000000000..bfd7363653 --- /dev/null +++ b/usr/src/pkgdefs/SUNWxsvc/postinstall @@ -0,0 +1,46 @@ +#!/bin/sh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# + +PATH="/usr/bin:/usr/sbin:${PATH}" +export PATH + +# +# Driver info +# +ADD_DRV="add_drv -b ${BASEDIR}" + +DRV=xsvc +grep "^${DRV} " $BASEDIR/etc/name_to_major > /dev/null 2>&1 +if [ $? -ne 0 ]; then + ${ADD_DRV} ${DRV} + if [ $? -ne 0 ]; then + echo "\nFailed add_drv of ${DRV}!\n" >&2 + exit 1 + fi +fi + +exit 0 diff --git a/usr/src/uts/common/zmod/mapfile b/usr/src/pkgdefs/SUNWxsvc/postremove index 460b10cc10..9e98dbd5b5 100644 --- a/usr/src/uts/common/zmod/mapfile +++ b/usr/src/pkgdefs/SUNWxsvc/postremove @@ -1,10 +1,10 @@ +#!/sbin/sh # # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -19,21 +19,17 @@ # # CDDL HEADER END # - -# -# Copyright 2003 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # - #ident "%Z%%M% %I% %E% SMI" - -{ - global: - z_strerror; - z_uncompress; - _info; - _init; - _fini; - local: - *; -}; +# +BD=${BASEDIR:-/} +if [ "$ACTIVE_PATCH" = "" ] +then + if grep "\<xsvc\>" $BD/etc/name_to_major > /dev/null 2>&1 + then + rem_drv -b ${BD} xsvc + fi +fi +exit 0 diff --git a/usr/src/pkgdefs/SUNWxsvc/prototype_i386 b/usr/src/pkgdefs/SUNWxsvc/prototype_i386 new file mode 100644 index 0000000000..910c7e56db --- /dev/null +++ b/usr/src/pkgdefs/SUNWxsvc/prototype_i386 @@ -0,0 +1,57 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# This required package information file contains a list of package contents. +# The 'pkgmk' command uses this file to identify the contents of a package +# and their location on the development machine when building the package. +# Can be created via a text editor or through use of the 'pkgproto' command. + +# packaging files +i copyright +i depend +i pkginfo +i postinstall +i postremove + +#!search <pathname pathname ...> # where to find pkg objects +#!include <filename> # include another 'prototype' file +#!default <mode> <owner> <group> # default used if not specified on entry +#!<param>=<value> # puts parameter in pkg environment +# +# +# List files which are i386 specific here +# +# source locations relative to the prototype file +# +# SUNWxsvc +# +d none platform 0755 root sys +d none platform/i86pc 0755 root sys +d none platform/i86pc/kernel 0755 root sys +d none platform/i86pc/kernel/drv 0755 root sys +f none platform/i86pc/kernel/drv/xsvc 755 root sys +f none platform/i86pc/kernel/drv/xsvc.conf 644 root sys +d none platform/i86pc/kernel/drv/amd64 0755 root sys +f none platform/i86pc/kernel/drv/amd64/xsvc 755 root sys diff --git a/usr/src/pkgdefs/etc/exception_list_sparc b/usr/src/pkgdefs/etc/exception_list_sparc index ddd59166e4..d8930e923a 100644 --- a/usr/src/pkgdefs/etc/exception_list_sparc +++ b/usr/src/pkgdefs/etc/exception_list_sparc @@ -635,9 +635,6 @@ usr/lib/sparcv9/librestart.so sparc usr/include/librestart.h sparc usr/include/librestart_priv.h sparc usr/include/libcontract_priv.h sparc -var/svc/manifest/platform/i86pc sparc -var/svc/manifest/platform/i86pc/eeprom.xml sparc -var/svc/profile/platform_i86pc.xml sparc # # Private libuutil files # diff --git a/usr/src/pkgdefs/etc/proto_list_ihv_i386 b/usr/src/pkgdefs/etc/proto_list_ihv_i386 index 0bc969214b..c4cba07150 100644 --- a/usr/src/pkgdefs/etc/proto_list_ihv_i386 +++ b/usr/src/pkgdefs/etc/proto_list_ihv_i386 @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -32,13 +32,10 @@ # f kernel/drv/adp - 755 root sys 0 1 - - f kernel/drv/adp.conf - 644 root sys 0 1 - - -f kernel/drv/amd64/xsvc - 755 root sys 0 1 - - f kernel/drv/cadp - 755 root sys 0 1 - - f kernel/drv/cadp.conf - 644 root sys 0 1 - - f kernel/drv/cpqhpc - 755 root sys 0 1 - - f kernel/drv/cpqhpc.conf - 644 root sys 0 1 - - -f kernel/drv/xsvc - 755 root sys 0 1 - - -f kernel/drv/xsvc.conf - 644 root sys 0 1 - - f platform/i86pc/kernel/drv/amd64/cadp160 - 755 root sys 0 1 - - f platform/i86pc/kernel/drv/cadp160 - 755 root sys 0 1 - - f platform/i86pc/kernel/drv/cadp160.conf - 644 root sys 0 1 - - diff --git a/usr/src/psm/stand/boot/Makefile b/usr/src/psm/stand/boot/Makefile index cffc01d339..0964794481 100644 --- a/usr/src/psm/stand/boot/Makefile +++ b/usr/src/psm/stand/boot/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -29,7 +29,6 @@ include ../../../Makefile.master sparcv9_ARCHITECTURES = sparcv9 sparc_ARCHITECTURES = $(sparcv9_ARCHITECTURES) -i386_ARCHITECTURES = i386 SUBDIRS = $($(MACH)_ARCHITECTURES) @@ -56,7 +55,7 @@ UTSDIR = ../../../uts UTSCLOSED = ../../../../closed/uts STANDLIBDIR = ../../../stand/lib STANDSYSDIRS = ../../../stand/sys -PROMDIRS = ../../promif $(UTSDIR)/intel/promif +PROMDIRS = ../../promif NAMESDIRS = ../lib/names XRDIRS += $(STANDLIBDIR) $(STANDSYSDIRS) $(PROMDIRS) $(NAMESDIRS) @@ -64,8 +63,7 @@ XRDIRS += $(STANDLIBDIR) $(STANDSYSDIRS) $(PROMDIRS) $(NAMESDIRS) # Components beginning with B! are in the open and closed trees; those # beginning with O! are just in the open tree. # -XRINCCOMP = B!sun4u O!sfmmu O!sparc/v7 O!sparc/v9 B!sparc B!sun \ - B!common B!intel B!i86pc +XRINCCOMP = B!sun4u O!sfmmu O!sparc/v7 O!sparc/v9 B!sparc B!sun B!common XRINC_TMP = $(XRINCCOMP:B!%=$(UTSDIR)/%) XRINCDIRS = $(XRINC_TMP:O!%=$(UTSDIR)/%) $(CLOSED_BUILD)XRINC_TMP = $(XRINCCOMP:B!%=$(UTSDIR)/% $(UTSCLOSED)/%) diff --git a/usr/src/psm/stand/boot/amd64/alloc.c b/usr/src/psm/stand/boot/amd64/alloc.c deleted file mode 100644 index 4da403f0e1..0000000000 --- a/usr/src/psm/stand/boot/amd64/alloc.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <amd64/boothooks.h> -#include <amd64/alloc.h> -#include <amd64/amd64_page.h> -#include <amd64/cpu.h> -#include <amd64/print.h> - -void * -amd64_alloc_identity(size_t size) -{ - void *addr; - - addr = (void *)idmap_mem((uint32_t)0, size, AMD64_PAGESIZE); - - if (addr == NULL) { - amd64_panic("amd64_alloc_identity: " - "boot failed to identity map 0x%lx bytes\n", size); - /*NOTREACHED*/ - } - return (addr); -} - -void * -amd64_zalloc_identity(size_t size) -{ - void *p; - - if (p = amd64_alloc_identity(size)) - bzero(p, size); - - return (p); -} diff --git a/usr/src/psm/stand/boot/amd64/amd64/amd64.h b/usr/src/psm/stand/boot/amd64/amd64/amd64.h deleted file mode 100644 index c7518b84c8..0000000000 --- a/usr/src/psm/stand/boot/amd64/amd64/amd64.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _AMD64_AMD64_H -#define _AMD64_AMD64_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/types.h> -#include <sys/link.h> - -#include <amd64/types.h> -#include <amd64/boothooks.h> - -struct amd64_machregs; - -extern void amd64_system_reset(void) __NORETURN; - -extern const char *amd64_getmmulist(void); -extern int amd64_config_cpu(void); - -extern struct bootops64 *init_bootops64(struct bootops *); -extern struct boot_syscalls64 *init_boot_syscalls64(struct boot_syscalls *); - -/* - * These routines probably belong in machregs.h - * Or we need to type the arguments as void * .. - */ -struct amd64_machregs; - -extern void amd64_vtrap(struct amd64_machregs *); -extern void amd64_dump_amd64_machregs(struct amd64_machregs *); -extern void amd64_dump_memlist(const char *); - -struct i386_machregs; -extern void amd64_dump_i386_machregs(struct i386_machregs *); - -extern struct amd64_machregs *amd64_makectx64(uint64_t); - -extern void amd64_exitto(struct amd64_machregs *); -extern void amd64_i386_clrtss(struct i386_machregs *); - -#ifdef __cplusplus -} -#endif - -#endif /* _AMD64_AMD64_H */ diff --git a/usr/src/psm/stand/boot/amd64/amd64/amd64_page.h b/usr/src/psm/stand/boot/amd64/amd64/amd64_page.h deleted file mode 100644 index c2e7115205..0000000000 --- a/usr/src/psm/stand/boot/amd64/amd64/amd64_page.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _AMD64_AMD64_PAGE_H -#define _AMD64_AMD64_PAGE_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define AMD64_PAGESIZE 4096 -#define AMD64_PAGESIZE2M (2*1024*1024) -#define AMD64_PAGESIZE4M (4*1024*1024) - -#define AMD64_PAGEOFFSET(pagesize) ((uint64_t)((pagesize) - 1)) -#define AMD64_PAGEMASK(pagesize) (~(AMD64_PAGEOFFSET(pagesize))) - -#define AMD64_PAGEALIGNED(va, pagesize) \ - (!((uint64_t)(va) & AMD64_PAGEOFFSET(pagesize))) - -#define AMD64_PAGESIZE_OFFSET_NBITS 11 - -#define BIT_GLOBAL 8 -#define BIT_PS 7 /* PDE only */ -#define BIT_US 2 -#define BIT_RW 1 -#define BIT_VALID 0 - -#define TBL_GLOBAL (1 << BIT_GLOBAL) -#define TBL_US (1 << BIT_US) -#define TBL_RW (1 << BIT_RW) -#define TBL_VALID (1 << BIT_VALID) - -#define PDE_PS (1 << BIT_PS) - -#define IS_PDE(level, amd64_mmu_mode) \ - ((level) == (mmus[(amd64_mmu_mode)].map_level - 1)) - -#define IS_PTE(level, amd64_mmu_mode) \ - ((level) == mmus[(amd64_mmu_mode)].map_level) - -#define IS_LARGEMAP(entry) ((entry) & PDE_PS) -#define ENTRY_VALID(entry) ((entry) & TBL_VALID) - -#define PA_MODBITS_MASK 0x1eULL -#define PA_MODBITS(entry) (((uint64_t)(entry)) & PA_MODBITS_MASK) - -#define AMD64_MODE_LEGACY 0 -#define AMD64_MODE_LONG64 1 - -typedef struct amd64_mmumode { - uint8_t shift_base; /* shift to start of page tables */ - uint8_t level_shift; /* shift between page table levels */ - uint8_t map_level; /* mapping level for AMD64_PAGESIZE pages */ - uint16_t tbl_entries; /* number of entries per table level */ -} amd64_mmumode_t; - -/* - * This macro is needed because of a difference of opinion between compilers - * that can result in inadvertent sign extension when converting from 32-bit - * to 64-bit values. - * - * For example, given the code: - * - * long *i = (long *)0xf0000000; - * unsigned long long l; - * - * l = (unsigned long long)i; - * - * GCC will currently sign extend "i" before converting it to unsigned long - * long, resulting in the value 0xfffffffff0000000 being stored in l. - * - * On the other hand, Forte compilers will not do the extension, resulting in - * l receiving the value 0xf0000000. - * - * The only way to assure sane results regardless of compiler is to use this - * macro whenever converting any value to an unsigned 64-bit value. - */ -#define UINT64_FROMPTR32(val32) ((uint64_t)(uintptr_t)(val32)) - -#define TBL_ENTRY_DEFAULT(pa) (UINT64_FROMPTR32(pa) | TBL_RW | TBL_VALID) -#define TBL_PTR(table) ((uint64_t *)(&table)) - -#define TBL_INDEX(va, shift, mask) (((va) >> (shift)) & mask) - -#define TBL_ENTRY32(amd64_mmu_mode, tbl_base, va, shift, mask) \ - (((amd64_mmu_mode) == AMD64_MODE_LEGACY) ? \ - (*(((uint32_t *)(tbl_base)) + \ - TBL_INDEX((va), (shift), (mask)))) : \ - ((uint32_t)*(((uint64_t *)(tbl_base)) + \ - TBL_INDEX((va), (shift), (mask))))) - -#define TBL_ENTRY64(amd64_mmu_mode, tbl_base, va, shift, mask) \ - (((amd64_mmu_mode) == AMD64_MODE_LEGACY) ? \ - ((uint64_t)(*(((uint32_t *)(tbl_base)) + \ - TBL_INDEX((va), (shift), (mask))))) : \ - (*(((uint64_t *)(tbl_base)) + TBL_INDEX((va), (shift), (mask))))) - -#define SET_TABLEVAL(amd64_mmu_mode, tbl_base, va, shift, mask, val) \ - (((amd64_mmu_mode) == AMD64_MODE_LEGACY) ? \ - (*(((uint32_t *)(tbl_base)) + \ - TBL_INDEX((va), (shift), (mask))) = (uint32_t)val) : \ - (*(((uint64_t *)(tbl_base)) + TBL_INDEX((va), (shift), \ - (mask))) = val)) - -#define VA64_OFFSET (0xffffffff00000000ULL) - -#define ADDR_TRUNC(a) ((void *)((uintptr_t)(a))) -#define ADDR_XTND(a) (((uintptr_t)(a)) == 0 ? 0ULL : \ - ((UINT64_FROMPTR32(a)) | VA64_OFFSET)) - -extern void amd64_map_mem(uint64_t, uint64_t, uint32_t, uint8_t, uint32_t, - uint16_t); - -extern uint16_t amd64_modbits(uint64_t); - -extern uint64_t amd64_legacy_physaddr(uint32_t); -extern uint64_t amd64_long_physaddr(uint64_t); -extern uint64_t amd64_physaddr(uint64_t, uint8_t); - -extern uint64_t amd64_long_lookup(uint64_t, uint32_t *, uint32_t); -extern uint32_t amd64_legacy_lookup(uint64_t, uint32_t *, uint32_t); -extern uint64_t amd64_legacy_lookup_physaddr(uint64_t, uint32_t); - -extern uint64_t amd64_init_longpt(uint32_t); - -extern void amd64_xlate_legacy_va(uint32_t, uint32_t, uint32_t, uint32_t); -extern void amd64_xlate_long_va(uint64_t, uint32_t, uint32_t, uint32_t); - -extern void amd64_xlate_boot_tables(uint32_t, uint32_t); - -#ifdef __cplusplus -} -#endif - -#endif /* _AMD64_AMD64_PAGE_H */ diff --git a/usr/src/psm/stand/boot/amd64/amd64/boothooks.h b/usr/src/psm/stand/boot/amd64/amd64/boothooks.h deleted file mode 100644 index becc1ef9b9..0000000000 --- a/usr/src/psm/stand/boot/amd64/amd64/boothooks.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _AMD64_BOOTHOOKS_H -#define _AMD64_BOOTHOOKS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/types.h> -#include <sys/bootconf.h> -#include <sys/bootsvcs.h> - -/* - * Grrr... conflicting #defines in sys/bootsvcs.h and sys/saio.h... - */ -#undef printf -#undef getchar -#undef putchar -#undef ischar - -#include <sys/saio.h> -#include <strings.h> - -extern caddr_t idmap_mem(uint32_t, size_t, int); - -#ifdef __cplusplus -} -#endif - -#endif /* _AMD64_BOOTHOOKS_H */ diff --git a/usr/src/psm/stand/boot/amd64/amd64/bootops64.h b/usr/src/psm/stand/boot/amd64/amd64/bootops64.h deleted file mode 100644 index e45872ca47..0000000000 --- a/usr/src/psm/stand/boot/amd64/amd64/bootops64.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _AMD64_BOOTOPS64_H -#define _AMD64_BOOTOPS64_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/types.h> -#include <sys/inttypes.h> - -#include <amd64/types.h> - -struct bsys_mem64 { - caddr64_t physinstalled; /* struct memlist64 pointer */ - caddr64_t physavail; /* struct memlist64 pointer */ - caddr64_t virtavail; /* struct memlist64 pointer */ - caddr64_t pcimem; /* struct memlist64 pointer */ - uint32_t extent; /* unused */ - uint32_t __bsys_pad0; -}; - -/* - * We need bootops-extensions >= 1 to make S10 work. - * bsys_version is BO_VERSION == 5. - */ -struct bootops64 { - uint32_t bsys_version; - uint32_t __bsys_pad0; - caddr64_t boot_mem; /* struct bsys_mem64 pointer */ - fnaddr64_t bsys_alloc; - fnaddr64_t bsys_free; - fnaddr64_t bsys_getproplen; - fnaddr64_t bsys_getprop; - fnaddr64_t bsys_nextprop; - fnaddr64_t bsys_printf; - fnaddr64_t bsys_doint; - fnaddr64_t bsys_ealloc; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* _AMD64_BOOTOPS64_H */ diff --git a/usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h b/usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h deleted file mode 100644 index 4fd533e2df..0000000000 --- a/usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _AMD64_BOOTSVCS64_H -#define _AMD64_BOOTSVCS64_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * We have to do this uglyness because of <bootsvcs.h>, sigh... - */ - -#ifndef _KERNEL -#define _KERNEL 1 -#define __XX64_KERNEL 1 -#endif /* _KERNEL */ - -#undef getchar -#undef putchar -#undef ischar - -#include <amd64/types.h> - -struct boot_syscalls64 { - fnaddr64_t getchar; /* 7 - getchar */ - fnaddr64_t putchar; /* 8 - putchar */ - fnaddr64_t ischar; /* 9 - ischar */ -}; - -#ifdef __XX64_KERNEL -#undef _KERNEL -#undef __XX64_KERNEL -#endif /* __XX64_KERNEL */ - -#ifdef __cplusplus -} -#endif - -#endif /* _AMD64_BOOTSVCS64_H */ diff --git a/usr/src/psm/stand/boot/amd64/amd64/debug.h b/usr/src/psm/stand/boot/amd64/amd64/debug.h deleted file mode 100644 index d62d24c927..0000000000 --- a/usr/src/psm/stand/boot/amd64/amd64/debug.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _AMD64_DEBUG_H -#define _AMD64_DEBUG_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/types.h> -#include <sys/varargs.h> -#include <sys/promif.h> -#include <sys/debug.h> - -extern int amd64_debug; -extern int amd64_pt_debug; -extern uint_t bop_trace; - -#define dprintf if (amd64_debug) printf - -#define AMD64_TRACE_BOP_IO 1 -#define AMD64_TRACE_BOP_VM 2 -#define AMD64_TRACE_BOP_PROP 4 -#define AMD64_TRACE_BOP_1275 8 -#define AMD64_TRACE_BOP_BIOS 16 - -#ifdef __cplusplus -} -#endif - -#endif /* _AMD64_DEBUG_H */ diff --git a/usr/src/psm/stand/boot/amd64/amd64/machregs.h b/usr/src/psm/stand/boot/amd64/amd64/machregs.h deleted file mode 100644 index 6784059966..0000000000 --- a/usr/src/psm/stand/boot/amd64/amd64/machregs.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _AMD64_MACHREGS_H -#define _AMD64_MACHREGS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(_ASM) - -/* - * AMD64 is somewhat unique in that it involves switching the state - * of the machine back and forth between being a complete implementation - * of an i386 processor, and a complete implementation of an amd64 - * processor. As a result, it has to "know" about the state of both - * physical machines. - */ - -#include <sys/types.h> -#include <amd64/tss.h> -#include <amd64/segments.h> - -struct i386_machregs { - - /* - * This is the privileged machine (register) state - */ - - uint32_t r_cr0; - uint32_t r_cr2; - uint32_t r_cr3; - uint32_t r_cr4; - - union { - desctbr_t un_gdt; - uint64_t __pad0; - } r_gdt_un; -#define r_gdt r_gdt_un.un_gdt - - union { - desctbr_t un_idt; - uint64_t __pad0; - } r_idt_un; -#define r_idt r_idt_un.un_idt - - uint32_t r_ldt; - uint32_t r_tr; - - /* - * The rest of this structure is an i386 'struct regs' - */ - - int32_t r_gs; - int32_t r_fs; - int32_t r_es; - int32_t r_ds; - int32_t r_edi; - int32_t r_esi; - int32_t r_ebp; - int32_t r_esp; - int32_t r_ebx; - int32_t r_edx; - int32_t r_ecx; - int32_t r_eax; - int32_t r_trapno; - int32_t r_err; - int32_t r_eip; - int32_t r_cs; - int32_t r_efl; - int32_t r_uesp; - int32_t r_ss; -}; - -/* - * XX64 need assertions to validate structure offsets are really - * what they need to be! - */ - -struct amd64_machregs { - /* - * This is the privileged machine (register) state - * (Does NOT include amd64-specific MSRs, because boot doesn't - * touch them) - * - * XX64 An open question, however, is if the switch between amd64 - * and i386 modes damages any of them -- we may need to save more - * than present below. - */ - - uint64_t r_kgsbase; - uint64_t r_gsbase; - uint64_t r_fsbase; - - uint64_t r_cr0; - uint64_t r_cr2; - uint64_t r_cr3; - uint64_t r_cr4; - uint64_t r_cr8; - - union { - desctbr64_t un_gdt; - upad128_t __pad0; - } r_gdt_un; - - union { - desctbr64_t un_idt; - upad128_t __pad0; - } r_idt_un; - - uint64_t r_ldt; - uint64_t r_tr; - - /* - * The rest of this structure is an amd64 'struct regs' - * - * It is intended to match the 'struct regs' definition - * in amd64/sys/privregs.h - * - * XX64 Need to ensure that it does! - */ - - int64_t r_rdi; - int64_t r_rsi; - int64_t r_rdx; - int64_t r_rcx; - int64_t r_r8; - int64_t r_r9; - int64_t r_rax; - int64_t r_rbx; - int64_t r_rbp; - int64_t r_r10; - int64_t r_r11; - int64_t r_r12; - int64_t r_r13; - int64_t r_r14; - int64_t r_r15; - int64_t r_gs; - int64_t r_fs; - int64_t r_ds; - int64_t r_es; - int64_t r_trapno; - int64_t r_err; - int64_t r_rip; - int64_t r_cs; - int64_t r_rfl; - int64_t r_rsp; - int64_t r_ss; -}; - -/* - * C-calling convention argument order: - * - * %rdi, %rsi, %rdx, %rcx, %r8, %r9 - * - * and how to get them out of an amd64_machregs structure: - */ - -#define _ARG1(rp) ((rp)->r_rdi) -#define _ARG2(rp) ((rp)->r_rsi) -#define _ARG3(rp) ((rp)->r_rdx) -#define _ARG4(rp) ((rp)->r_rcx) -#define _ARG5(rp) ((rp)->r_r8) -#define _ARG6(rp) ((rp)->r_r9) - -#endif /* !_ASM */ - -#ifdef __cplusplus -} -#endif - -#endif /* _AMD64_MACHREGS_H */ diff --git a/usr/src/psm/stand/boot/amd64/amd64/memlist64.h b/usr/src/psm/stand/boot/amd64/amd64/memlist64.h deleted file mode 100644 index ce3978e1e8..0000000000 --- a/usr/src/psm/stand/boot/amd64/amd64/memlist64.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _AMD64_MEMLIST64_H -#define _AMD64_MEMLIST64_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <amd64/types.h> - -struct memlist64 { - uint64_t address; /* starting address of memory segment */ - uint64_t size; /* size of same */ - caddr64_t next; /* struct memlist64 pointer */ - caddr64_t prev; /* struct memlist64 pointer */ -}; - -#ifdef __cplusplus -} -#endif - -#endif /* _AMD64_MEMLIST64_H */ diff --git a/usr/src/psm/stand/boot/amd64/amd64/print.h b/usr/src/psm/stand/boot/amd64/amd64/print.h deleted file mode 100644 index 0db7816902..0000000000 --- a/usr/src/psm/stand/boot/amd64/amd64/print.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _AMD64_PRINT_H -#define _AMD64_PRINT_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/types.h> -#include <sys/varargs.h> - -#undef printf /* unbelievably broken bootsvcs.h */ - -extern int amd64_vsnprintf(char *, size_t, const char *, va_list) - __VPRINTFLIKE(3); -extern int amd64_vsnprintf64(char *, size_t, const char *, va_list) - __VPRINTFLIKE(3); -extern int amd64_snprintf(char *, size_t, const char *, ...) - __PRINTFLIKE(3); -extern int amd64_snprintf64(char *, size_t, const char *, ...) - __PRINTFLIKE(3); -extern void amd64_vpanic(const char *, va_list) - __VPRINTFLIKE(1) __NORETURN; -extern void amd64_panic(const char *, ...) - __PRINTFLIKE(1); -extern void amd64_warning(const char *, ...) - __PRINTFLIKE(1); -extern int amd64_assfail(const char *, const char *, int); - -#ifdef __cplusplus -} -#endif - -#endif /* _AMD64_PRINT_H */ diff --git a/usr/src/psm/stand/boot/amd64/amd64/segments.h b/usr/src/psm/stand/boot/amd64/amd64/segments.h deleted file mode 100644 index 478fc99790..0000000000 --- a/usr/src/psm/stand/boot/amd64/amd64/segments.h +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _AMD64_SEGMENTS_H -#define _AMD64_SEGMENTS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Copyright (c) 1989, 1990 William F. Jolitz - * Copyright (c) 1990 The Regents of the University of California. - * 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: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by 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 - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)segments.h 7.1 (Berkeley) 5/9/91 - * $FreeBSD: src/sys/i386/include/segments.h,v 1.34 2003/09/10 01:07:04 - * jhb Exp $ - * - * 386 Segmentation Data Structures and definitions - * William F. Jolitz (william@ernie.berkeley.edu) 6/20/1989 - */ - -/* - * Selector register format - * CS, DS, ES, FS, GS, SS - * - * 15 3 2 1 0 - * +---------------------+---+----+ - * | SI |TI |RPL | - * +---------------------+---+----+ - * - * SI = selector index - * TI = table indicator (0 = GDT, 1 = LDT) - * RPL = requestor privilege level - */ -#define SELTOIDX(s) ((s) >> 3) /* selector to index */ -#define IDXTOSEL(s) ((s) << 3) /* index to selector */ -#define SEL_KPL 0 /* kernel priority level */ -#define SEL_UPL 3 /* user priority level */ -#define SEL_TI_LDT 4 /* local descriptor table */ -#define SEL_LDT(s) (IDXTOSEL(s) | SEL_TI_LDT | SEL_UPL) /* local sel */ -#define SEL_GDT(s, r) (IDXTOSEL(s) | r) /* global sel */ -#define SELISLDT(s) (((s) & SEL_TI_LDT) == SEL_TI_LDT) -#define CPL_MASK 3 /* RPL mask for selector */ - -#ifndef _ASM - -typedef uint16_t selector_t; /* selector reigster */ - -/* - * Hardware descriptor table register format for GDT and IDT. - */ -#pragma pack(2) -typedef struct descriptor_table_register64 { - uint16_t dtr_limit; /* table limit */ - uint64_t dtr_base; /* table base address */ -} desctbr64_t; -#pragma pack() - -#pragma pack(2) -typedef struct descriptor_table_register { - uint16_t dtr_limit; /* table limit */ - uint32_t dtr_base; /* table base address */ -} desctbr_t; -#pragma pack() - - -/* - * Functions for loading and storing descriptor table - * registers. - */ -extern void rd_idtr(desctbr_t *); -extern void wr_idtr(desctbr_t *); -extern void rd_gdtr(desctbr_t *); -extern void wr_gdtr(desctbr_t *); -extern void wr_ldtr(selector_t); -extern void wr_tsr(selector_t); - -/* - * User segment descirptors (code and data). - * Legacy mode 64-bits wide. - */ -typedef struct user_segment_descriptor { - uint32_t usd_lolimit:16; /* segment limit 15:0 */ - uint32_t usd_lobase:16; /* segment base 15:0 */ - uint32_t usd_midbase:8; /* segment base 23:16 */ - uint32_t usd_type:5; /* segment type, includes S bit */ - uint32_t usd_dpl:2; /* segment descriptor priority level */ - uint32_t usd_p:1; /* segment descriptor present */ - uint32_t usd_hilimit:4; /* segment limit 19:16 */ - uint32_t usd_avl:1; /* available to sw, but not used */ - uint32_t usd_reserved:1; /* unsued, ignored */ - uint32_t usd_def32:1; /* default 32 vs 16 bit operand */ - uint32_t usd_gran:1; /* limit unit (bytes vs pages) */ - uint32_t usd_hibase:8; /* segment base 31:24 */ -} user_desc_t; - -/* - * User segment descriptors. - * Long mode 64-bits wide. - * - * In 32-bit compatibility mode (%cs:usd_long=0) all fields are interpreted - * as in legacy mode for both code and data. - * - * In 64-bit mode (%cs:usd_long=1) code segments only have the conforming - * bit in usd_type, usd_dpl, usd_p, usd_long and usd_def32=0. usd_def32 - * must be zero in 64-bit mode. Setting it to 1 is reserved for future use. - * All other fields are loaded but ignored by hardware. - * - * 64-bit data segments only have usd_p. All other fields are loaded but - * ignored by hardware when in 64-bit mode. - */ -typedef struct user_segment_descriptor64 { - uint32_t usd_lolimit:16; /* segment limit 15:0 */ - uint32_t usd_lobase:16; /* segment base 15:0 */ - uint32_t usd_midbase:8; /* segment base 23:16 */ - uint32_t usd_type:5; /* segment type, includes S bit */ - uint32_t usd_dpl:2; /* segment descriptor priority level */ - uint32_t usd_p:1; /* segment descriptor present */ - uint32_t usd_hilimit:4; /* segment limit 19:16 */ - uint32_t usd_avl:1; /* available to sw, but not used */ - uint32_t usd_long:1; /* long mode (%cs only) */ - uint32_t usd_def32:1; /* default 32 vs 16 bit operand */ - uint32_t usd_gran:1; /* limit gran (byte/page units) */ - uint32_t usd_hibase:8; /* segment base 31:24 */ -} user_desc64_t; - -/* - * System segment descriptors for LDT and TSS segments. - * Legacy mode 64-bits wide. - */ -typedef struct system_segment_descriptor { - uint32_t ssd_lolimit:16; /* segment limit 15:0 */ - uint32_t ssd_lobase:16; /* segment base 15:0 */ - uint32_t ssd_midbase:8; /* segment base 23:16 */ - uint32_t ssd_type:4; /* segment type */ - uint32_t ssd_zero:1; /* must be zero */ - uint32_t ssd_dpl:2; /* segment descriptor priority level */ - uint32_t ssd_p:1; /* segment descriptor present */ - uint32_t ssd_hilimit:4; /* segment limit 19:16 */ - uint32_t ssd_avl:1; /* available to sw, but not used */ - uint32_t ssd_reserved:2; /* unused, ignored */ - uint32_t ssd_gran:1; /* limit unit (bytes vs pages) */ - uint32_t ssd_hibase:8; /* segment base 31:24 */ -} system_desc_t; - -/* - * System segment descriptors for LDT and TSS segments. - * Long mode 128-bits wide. - * - * 32-bit LDT and TSS descriptor types are redefined to 64-bit equivalents. - * All other legacy types are reserved and illegal. - */ -typedef struct system_segment_descriptor64 { - uint32_t ssd_lolimit:16; /* segment limit 15:0 */ - uint32_t ssd_lobase:16; /* segment base 15:0 */ - uint32_t ssd_midbase:8; /* segment base 23:16 */ - uint32_t ssd_type:4; /* segment type */ - uint32_t ssd_zero1:1; /* must be zero */ - uint32_t ssd_dpl:2; /* segment descriptor priority level */ - uint32_t ssd_p:1; /* segment descriptor present */ - uint32_t ssd_hilimit:4; /* segment limit 19:16 */ - uint32_t ssd_avl:1; /* available to sw, but not used */ - uint32_t ssd_resv1:2; /* unused, ignored */ - uint32_t ssd_gran:1; /* limit unit (bytes vs pages) */ - uint32_t ssd_hibase:8; /* segment base 31:24 */ - uint32_t ssd_hi64base:32; /* segment base 63:32 */ - uint32_t ssd_resv2:8; /* unused, ignored */ - uint32_t ssd_zero2:5; /* must be zero */ - uint32_t ssd_resv3:19; /* unused, ignored */ -} system_desc64_t; - -/* - * System gate segment descriptors for interrupt, trap, call and task gates. - * Legacy mode 64-bits wide. - */ -typedef struct gate_segment_descriptor { - uint32_t sgd_looffset:16; /* segment code offset 15:0 */ - uint32_t sgd_selector:16; /* target code or task selector */ - uint32_t sgd_stkcpy:5; /* number of stack wds to cpy */ - uint32_t sgd_resv:3; /* unused, ignored */ - uint32_t sgd_type:5; /* segment type, includes S bit */ - uint32_t sgd_dpl:2; /* segment descriptor priority level */ - uint32_t sgd_p:1; /* segment descriptor present */ - uint32_t sgd_hioffset:16; /* code seg off 31:16 */ -} gate_desc_t; - -/* - * System segment descriptors for interrupt, trap and call gates. - * Long mode 128-bits wide. - * - * 32-bit interrupt, trap and call gate types are redefined to 64-bit - * equivalents. Task gates along with all other legacy types are reserved - * and illegal. - */ -typedef struct gate_segment_descriptor64 { - uint32_t sgd_looffset:16; /* segment code offset 15:0 */ - uint32_t sgd_selector:16; /* target code or task selector */ - uint32_t sgd_ist:3; /* IST table index */ - uint32_t sgd_resv1:5; /* unused, ignored */ - uint32_t sgd_type:5; /* segment type, includes S bit */ - uint32_t sgd_dpl:2; /* segment descriptor priority level */ - uint32_t sgd_p:1; /* segment descriptor present */ - uint32_t sgd_hioffset:16; /* segment code offset 31:16 */ - uint32_t sgd_hi64offset:32; /* segment code offset 63:32 */ - uint32_t sgd_resv2:8; /* unused, ignored */ - uint32_t sgd_zero:5; /* call gate only: must be zero */ - uint32_t sgd_resv3:19; /* unused, ignored */ -} gate_desc64_t; - -#undef BYTES -#define BYTES 0 - -#undef PAGES -#define PAGES 1 - -#undef OP32 -#define OP32 1 - -#undef LONG -#define LONG 1 - -#undef SHORT -#define SHORT 0 - -/* - * functions for initializing and updating segment descriptors. - */ -extern void set_usegd64(user_desc64_t *, uint_t, void *, size_t, uint_t, uint_t, - uint_t, uint_t); -extern void set_gatesegd64(gate_desc64_t *, void (*)(void), selector_t, uint_t, - uint_t, uint_t); -void set_syssegd64(system_desc64_t *, void *, size_t, uint_t, uint_t); - -extern void set_usegd(user_desc_t *, void *, size_t, uint_t, uint_t, - uint_t, uint_t); -extern void set_gatesegd(gate_desc_t *, void (*)(void), selector_t, - uint_t, uint_t, uint_t); -void set_syssegd(system_desc_t *, void *, size_t, uint_t, uint_t); - -#endif /* _ASM */ - -/* - * System segments and gate types. - * - * In long mode i386 32-bit ldt, tss, call, interrupt and trap gate - * types are redefined into 64-bit equivalents. - */ -#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_SYSTSS 9 /* system TSS available */ -#define SDT_SYSNULL3 10 /* system null again */ -#define SDT_SYSTSSBSY 11 /* system TSS busy */ -#define SDT_SYSCGT 12 /* system call gate */ -#define SDT_SYSNULL4 13 /* system null again */ -#define SDT_SYSIGT 14 /* system interrupt gate */ -#define SDT_SYSTGT 15 /* system trap gate */ - -/* - * Memory segment types. - * - * While in long mode expand-down, writable and accessed type field - * attributes are ignored. Only the conforming bit is loaded by hardware - * for long mode code segment descriptors. - */ -#define SDT_MEMRO 16 /* read only */ -#define SDT_MEMROA 17 /* read only accessed */ -#define SDT_MEMRW 18 /* read write */ -#define SDT_MEMRWA 19 /* read write accessed */ -#define SDT_MEMROD 20 /* read only expand dwn limit */ -#define SDT_MEMRODA 21 /* read only expand dwn limit accessed */ -#define SDT_MEMRWD 22 /* read write expand dwn limit */ -#define SDT_MEMRWDA 23 /* read write expand dwn limit accessed */ -#define SDT_MEME 24 /* execute only */ -#define SDT_MEMEA 25 /* execute only accessed */ -#define SDT_MEMER 26 /* execute read */ -#define SDT_MEMERA 27 /* execute read accessed */ -#define SDT_MEMEC 28 /* execute only conforming */ -#define SDT_MEMEAC 29 /* execute only accessed conforming */ -#define SDT_MEMERC 30 /* execute read conforming */ -#define SDT_MEMERAC 31 /* execute read accessed conforming */ - - -/* - * Entries in the Interrupt Descriptor Table (IDT) - */ -#define IDT_DE 0 /* #DE: Divide Error */ -#define IDT_DB 1 /* #DB: Debug */ -#define IDT_NMI 2 /* Nonmaskable External Interrupt */ -#define IDT_BP 3 /* #BP: Breakpoint */ -#define IDT_OF 4 /* #OF: Overflow */ -#define IDT_BR 5 /* #BR: Bound Range Exceeded */ -#define IDT_UD 6 /* #UD: Undefined/Invalid Opcode */ -#define IDT_NM 7 /* #NM: No Math Coprocessor */ -#define IDT_DF 8 /* #DF: Double Fault */ -#define IDT_FPUGP 9 /* Coprocessor Segment Overrun */ -#define IDT_TS 10 /* #TS: Invalid TSS */ -#define IDT_NP 11 /* #NP: Segment Not Present */ -#define IDT_SS 12 /* #SS: Stack Segment Fault */ -#define IDT_GP 13 /* #GP: General Protection Fault */ -#define IDT_PF 14 /* #PF: Page Fault */ -#define IDT_MF 16 /* #MF: FPU Floating-Point Error */ -#define IDT_AC 17 /* #AC: Alignment Check */ -#define IDT_MC 18 /* #MC: Machine Check */ -#define IDT_XF 19 /* #XF: SIMD Floating-Point Exception */ -#define IDT_SYSCALL 0x80 /* System Call Interrupt Vector */ -#define NIDT 256 /* size in entries of IDT */ - -/* - * Entries in the Global Descriptor Table (GDT) for VMX (stretch) - * - * We make sure to space the system descriptors (LDT's, TSS') - * such that they are double gdt slot aligned. This is because - * in long mode system segment decriptors expand to 128 bits. - */ -#define GDT_NULL 0 /* null */ -#define GDT_DATA32 1 /* 32-bit data */ -#define GDT_CODE32 2 /* 32-bit code */ -#define GDT_DATA64 3 /* 64-bit data */ -#define GDT_CODE64 4 /* 64-bit code */ -#define GDT_NULL1 5 /* null */ -#define GDT_TSS64 6 /* 64-bit tss */ -#define GDT_NULL2 7 /* null */ - -#define NGDT 8 - -#ifndef _ASM - -extern void amd64_div0trap(), amd64_dbgtrap(), amd64_nmiint(), amd64_brktrap(); -extern void amd64_ovflotrap(), amd64_boundstrap(), amd64_invoptrap(); -extern void amd64_ndptrap(), amd64_doublefault(); -extern void amd64_invaltrap(), amd64_invtsstrap(), amd64_segnptrap(); -extern void amd64_stktrap(), amd64_gptrap(), amd64_pftrap(), amd64_ndperr(); -extern void amd64_overrun(), amd64_resvtrap(), amd64_achktrap(); -extern void amd64_mcetrap(), amd64_xmtrap(); - -#endif /* _ASM */ - -#ifdef __cplusplus -} -#endif - -#endif /* _AMD64_SEGMENTS_H */ diff --git a/usr/src/psm/stand/boot/amd64/amd64/tss.h b/usr/src/psm/stand/boot/amd64/amd64/tss.h deleted file mode 100644 index 1aff429e8d..0000000000 --- a/usr/src/psm/stand/boot/amd64/amd64/tss.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ -/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ -/* All Rights Reserved */ - -/* - * Copyright (c) 1990 The Regents of the University of California. - * 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: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by 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 - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)tss.h 5.4 (Berkeley) 1/18/91 - * $FreeBSD: src/sys/i386/include/tss.h,v 1.13 2002/09/23 05:04:05 peter Exp $ - */ - -#ifndef _AMD64_TSS_H -#define _AMD64_TSS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ASM -/* - * amd64 long mode TSS definition - */ -#pragma pack(2) -typedef struct amd64tss { - uint32_t tss_rsvd0; /* reserved, ignored */ - uint64_t tss_rsp0; /* stack pointer CPL = 0 */ - uint64_t tss_rsp1; /* stack pointer CPL = 1 */ - uint64_t tss_rsp2; /* stack pointer CPL = 2 */ - uint64_t tss_rsvd1; /* reserved, ignored */ - uint64_t tss_ist1; /* Interrupt stack table 1 */ - uint64_t tss_ist2; /* Interrupt stack table 2 */ - uint64_t tss_ist3; /* Interrupt stack table 3 */ - uint64_t tss_ist4; /* Interrupt stack table 4 */ - uint64_t tss_ist5; /* Interrupt stack table 5 */ - uint64_t tss_ist6; /* Interrupt stack table 6 */ - uint64_t tss_ist7; /* Interrupt stack table 7 */ - uint64_t tss_rsvd2; /* reserved, ignored */ - uint16_t tss_rsvd3; /* reserved, ignored */ - uint16_t tss_iobase; /* io bitmap offset */ -} amd64tss_t; -#pragma pack() - -/* - * Legacy 386 TSS definition - */ -typedef struct i386tss { - uint32_t tss_link; /* 16-bit prior TSS selector */ - uint32_t tss_esp0; - uint32_t tss_ss0; - uint32_t tss_esp1; - uint32_t tss_ss1; - uint32_t tss_esp2; - uint32_t tss_ss2; - uint32_t tss_cr3; - uint32_t tss_eip; - uint32_t tss_eflags; - uint32_t tss_eax; - uint32_t tss_ecx; - uint32_t tss_edx; - uint32_t tss_ebx; - uint32_t tss_esp; - uint32_t tss_ebp; - uint32_t tss_esi; - uint32_t tss_edi; - uint32_t tss_es; - uint32_t tss_cs; - uint32_t tss_ss; - uint32_t tss_ds; - uint32_t tss_fs; - uint32_t tss_gs; - uint32_t tss_ldt; - uint32_t tss_bitmapbase; -} i386tss_t; - -#endif /* !_ASM */ - -#ifdef __cplusplus -} -#endif - -#endif /* _AMD64_TSS_H */ diff --git a/usr/src/psm/stand/boot/amd64/amd64/types.h b/usr/src/psm/stand/boot/amd64/amd64/types.h deleted file mode 100644 index 127effff25..0000000000 --- a/usr/src/psm/stand/boot/amd64/amd64/types.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _AMD64_TYPES_H -#define _AMD64_TYPES_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/types.h> -#include <sys/inttypes.h> - -typedef uint64_t caddr64_t; -typedef uint64_t fnaddr64_t; -typedef uint64_t size64_t; - -#define BITX(u, h, l) (((u) >> (l)) & ((1lu << ((h) - (l) + 1lu)) - 1lu)) - -#ifdef __cplusplus -} -#endif - -#endif /* _AMD64_TYPES_H */ diff --git a/usr/src/psm/stand/boot/amd64/context.c b/usr/src/psm/stand/boot/amd64/context.c deleted file mode 100644 index 7fb2d61c7f..0000000000 --- a/usr/src/psm/stand/boot/amd64/context.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/trap.h> -#include <sys/controlregs.h> -#include <sys/sysmacros.h> -#include <sys/link.h> - -#include <amd64/types.h> -#include <amd64/amd64.h> -#include <amd64/cpu.h> -#include <amd64/machregs.h> -#include <amd64/tss.h> -#include <amd64/segments.h> -#include <amd64/debug.h> -#include <amd64/bootops64.h> -#include <amd64/bootsvcs64.h> -#include <amd64/amd64_page.h> - -/* - * This save area is initialized by amd64_exitto(), and used to - * restore the state of the machine before invoking various - * bootops. - * - * However, it needs to be mapped 1:1 so that we can reference it - * while paging is disabled. This is achieved via mapfile trickery; - * we glom the entire program into one contiguous segment. - */ -struct i386_machregs exitto_i386_machregs; - -/*CSTYLED*/ -#pragma align 16 (amd64_stack) -static uint8_t amd64_stack[1024*16]; - -/*CSTYLED*/ -#pragma align 16 (amd64_dblfault_stack) -static uint8_t amd64_dblfault_stack[1024*16]; - -/*CSTYLED*/ -#pragma align 16 (amd64_exception_stack) -static uint8_t amd64_exception_stack[1024*16]; - -static const selector_t cs64sel = SEL_GDT(GDT_CODE64, SEL_KPL); -static const selector_t ds64sel = SEL_GDT(GDT_DATA64, SEL_KPL); - -static user_desc64_t gdt64[NGDT]; /* long mode gdt */ -static amd64tss_t tss64; /* long mode tss */ - -static void -make_gdt(desctbr64_t *rgdt) -{ - /* - * TSS - */ - bzero(&tss64, sizeof (tss64)); - - /* - * All exceptions but #DF will run on the exception stack. - */ - tss64.tss_ist1 = (uint64_t)(uintptr_t) - &amd64_exception_stack[sizeof (amd64_exception_stack)]; - - /* - * #DF (double fault) gets its own private stack. - */ - tss64.tss_ist2 = (uint64_t)(uintptr_t) - &amd64_dblfault_stack[sizeof (amd64_dblfault_stack)]; - - /* - * GDT - */ - bzero(gdt64, sizeof (gdt64)); - - /* - * 32-bit legacy or compatibility mode for data. - * Maps entire 4G address space. - */ - set_usegd64(&gdt64[GDT_DATA32], SHORT, NULL, 0xfffff, SDT_MEMRW, - SEL_KPL, PAGES, OP32); - - /* - * 32-bit legacy or compatibility mode for code. - * Maps entire 4G address space. - */ - set_usegd64(&gdt64[GDT_CODE32], SHORT, NULL, 0xfffff, SDT_MEMERC, - SEL_KPL, PAGES, OP32); - - /* - * 64-bit long mode for data. XXX don't really need this. - * Maps entire 64-bit address space by definition. - */ - set_usegd64(&gdt64[GDT_DATA64], LONG, NULL, 0, SDT_MEMRW, - SEL_KPL, PAGES, OP32); - - /* - * 64-bit long mode for code. - * Maps entire 64-bit address space by definition. - */ - set_usegd64(&gdt64[GDT_CODE64], LONG, NULL, 0, SDT_MEMERC, - SEL_KPL, PAGES, OP32); - - /* - * 64-bit long mode TSS. - */ - set_syssegd64((system_desc64_t *)&gdt64[GDT_TSS64], &tss64, - sizeof (tss64), SDT_SYSTSS, SEL_KPL); - - rgdt->dtr_limit = sizeof (gdt64) - 1; - rgdt->dtr_base = (uint64_t)(uintptr_t)gdt64; -} - -static gate_desc64_t idt64[NIDT]; /* long mode idt */ - -static void -make_idt(desctbr64_t *ridt) -{ - int i; - - /* - * IDT - * - * First initialize all entries to reserve trap then overwrite - * the important ones with specific handlers. - * - * XXX how big does this idt really need to be ? I suspect - * only large enough to hold kmdb's soft int? - * - * XX64 fbsd only uses interrupt gates for all. Perhaps - * This is good for amd64 since we want to block maskable - * interrupts once we take an exception? - */ - bzero(idt64, sizeof (idt64)); /* FIXME */ - - for (i = 0; i < NIDT; i++) - set_gatesegd64(&idt64[i], &amd64_resvtrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - - set_gatesegd64(&idt64[T_ZERODIV], &amd64_div0trap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - set_gatesegd64(&idt64[T_SGLSTP], &amd64_dbgtrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - set_gatesegd64(&idt64[T_NMIFLT], &amd64_nmiint, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - set_gatesegd64(&idt64[T_BPTFLT], &amd64_brktrap, cs64sel, 1, - SDT_SYSIGT, SEL_UPL); - set_gatesegd64(&idt64[T_OVFLW], &amd64_ovflotrap, cs64sel, 1, - SDT_SYSIGT, SEL_UPL); - set_gatesegd64(&idt64[T_BOUNDFLT], &amd64_boundstrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - set_gatesegd64(&idt64[T_ILLINST], &amd64_invoptrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - set_gatesegd64(&idt64[T_NOEXTFLT], &amd64_ndptrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - - /* - * double fault handler gets its own private stack (tss.ist2). - */ - set_gatesegd64(&idt64[T_DBLFLT], &amd64_doublefault, cs64sel, 2, - SDT_SYSIGT, SEL_KPL); - - /* - * T_EXTOVRFLT coprocessor-segment-overrun not supported. - */ - - set_gatesegd64(&idt64[T_TSSFLT], &amd64_invtsstrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - set_gatesegd64(&idt64[T_SEGFLT], &amd64_segnptrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - set_gatesegd64(&idt64[T_STKFLT], &amd64_stktrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - set_gatesegd64(&idt64[T_GPFLT], &amd64_gptrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - set_gatesegd64(&idt64[T_PGFLT], &amd64_pftrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - - /* - * 15 reserved. - */ - set_gatesegd64(&idt64[15], &amd64_resvtrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - - set_gatesegd64(&idt64[T_EXTERRFLT], &amd64_ndperr, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - set_gatesegd64(&idt64[T_ALIGNMENT], &amd64_achktrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - set_gatesegd64(&idt64[T_MCE], &amd64_mcetrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - set_gatesegd64(&idt64[T_SIMDFPE], &amd64_xmtrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - - /* - * 20-31 reserved - */ - for (i = 20; i < 32; i++) - set_gatesegd64(&idt64[i], &amd64_invaltrap, cs64sel, 1, - SDT_SYSIGT, SEL_KPL); - - /* - * XX64 -- why not resvtrap in initial programming?? - * either way, move this to the top so that the defaults - * are set together. - */ - ridt->dtr_limit = sizeof (idt64) - 1; - ridt->dtr_base = (uint64_t)(uintptr_t)idt64; -} - -/* - * Note that when rsp is being pushed, like the processor, we must - * ensure that the value of the stack pointer at the beginning of the - * instruction is the one that is pushed, NOT the value after. - */ -#define PUSHQ(rsp, value) \ - rsp[-1] = ((uint64_t)(value)); rsp-- - -#define SUBQ(rsp, value) \ - rsp -= ((value) / sizeof (*rsp)) - -struct amd64_machregs * -amd64_makectx64(uint64_t entry) -{ - extern struct bootops *bop; - extern struct boot_syscalls *sysp; - extern Elf64_Boot *elfbootvecELF64; - - struct boot_syscalls64 *sysp64; - struct bootops64 *bop64; - uint64_t *rsp; - - bzero(amd64_stack, sizeof (amd64_stack)); - - rsp = (void *)&amd64_stack[sizeof (amd64_stack)]; - - PUSHQ(rsp, entry); - - /* - * terminate stack walks with a null RBP value. - */ - PUSHQ(rsp, 0); - - /* - * push in amd64_machregs order. - */ - PUSHQ(rsp, ds64sel); /* ss */ - PUSHQ(rsp, (uintptr_t)rsp); /* rsp */ - PUSHQ(rsp, amd64_get_eflags()); /* rfl */ - PUSHQ(rsp, cs64sel); /* cs */ - PUSHQ(rsp, 0); /* %rip - because we didn't go thru a stub */ - PUSHQ(rsp, 0); /* err */ - PUSHQ(rsp, 0); /* trapno */ - PUSHQ(rsp, ds64sel); /* es */ - PUSHQ(rsp, ds64sel); /* ds */ - PUSHQ(rsp, 0); /* fs */ - PUSHQ(rsp, 0); /* gs */ - - SUBQ(rsp, 11 * 8); /* r8 thru r15 are zero */ - - bop64 = init_bootops64(bop); - sysp64 = init_boot_syscalls64(sysp); - - PUSHQ(rsp, (uintptr_t)elfbootvecELF64); /* rcx */ - PUSHQ(rsp, (uintptr_t)bop64); /* rdx */ - PUSHQ(rsp, 0); /* rsi - null dvec */ - PUSHQ(rsp, (uintptr_t)sysp64); /* rdi */ - - PUSHQ(rsp, SEL_GDT(GDT_TSS64, SEL_KPL)); /* tr */ - - SUBQ(rsp, 1 * 8); /* null ldt */ - - PUSHQ(rsp, 0); /* idt */ - PUSHQ(rsp, 0); - make_idt((desctbr64_t *)rsp); - - PUSHQ(rsp, 0); /* gdt */ - PUSHQ(rsp, 0); - make_gdt((desctbr64_t *)rsp); - - PUSHQ(rsp, 0); /* cr8 */ - - /* - * XX64: Note that boot enables CR4_PGE (global pages) - * and Joe has discovered errata that warns against - * mixing this. Need to investigate. - */ - PUSHQ(rsp, CR4_PGE | CR4_PAE | amd64_get_cr4()); /* cr4 */ - PUSHQ(rsp, amd64_init_longpt(amd64_get_cr3())); /* cr3 */ - PUSHQ(rsp, amd64_get_cr2()); /* cr2 */ - - /* - * XX64 - CR0_PG already set? - */ - PUSHQ(rsp, CR0_PG | amd64_get_cr0()); /* cr0 */ - - SUBQ(rsp, 3 * 8); /* kgsbase, gsbase, fsbase */ - - return ((struct amd64_machregs *)rsp); -} diff --git a/usr/src/psm/stand/boot/amd64/cpu.c b/usr/src/psm/stand/boot/amd64/cpu.c deleted file mode 100644 index 668d2f17e6..0000000000 --- a/usr/src/psm/stand/boot/amd64/cpu.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/psw.h> - -#include <amd64/print.h> -#include <amd64/debug.h> -#include <amd64/cpu.h> -#include <amd64/amd64.h> -#include <amd64/msr.h> -#include "../i386/common/biosint.h" - -#ifdef DEBUG -static void -amd64_dump_cpuid(uint32_t eaxmin, uint32_t eaxmax) -{ - uint32_t eax; - struct amd64_cpuid_regs __vcr, *vcr = &__vcr; - - printf("\t%8s | %8s %8s %8s %8s\n", - "eax in", "eax", "ebx", "ecx", "edx"); - for (eax = eaxmin; eax <= eaxmax; eax++) { - amd64_cpuid_insn(eax, vcr); - printf("\t%8x | %8x %8x %8x %8x\n", eax, - vcr->r_eax, vcr->r_ebx, vcr->r_ecx, vcr->r_edx); - } -} - -#define cmprintf printf - -#else /* !DEBUG */ - -#ifdef lint -#define cmprintf printf -#else -#define cmprintf -#endif /* lint */ - -#endif /* DEBUG */ - -static int detect_target_operating_mode(); - -int is_amd64; - -/*ARGSUSED*/ -int -amd64_config_cpu(void) -{ - struct amd64_cpuid_regs __vcr, *vcr = &__vcr; - uint32_t maxeax; - uint32_t max_maxeax = 0x100; - char vendor[13]; - int isamd64 = 0; - uint32_t stdfeatures = 0, xtdfeatures = 0; - uint64_t efer; - - /* - * This check may seem silly, but if the C preprocesor symbol __amd64 - * is #defined during compilation, something that may outwardly seem - * like a good idea, uts/common/sys/isa_defs.h will #define _LP64, - * which will cause uts/common/sys/int_types.h to typedef uint64_t as - * an unsigned long - which is only 4 bytes in size when using a 32-bit - * compiler. - * - * If that happens, all the page table translation routines will fail - * horribly, so check the size of uint64_t just to insure some degree - * of sanity in future operations. - */ - /*LINTED [sizeof result is invarient]*/ - if (sizeof (uint64_t) != 8) - prom_panic("multiboot compiled improperly, unable to boot " - "64-bit AMD64 executables"); - - /* - * If the CPU doesn't support the CPUID instruction, it's definitely - * not an AMD64. - */ - if (amd64_cpuid_supported() == 0) - return (0); - - amd64_cpuid_insn(0, vcr); - - maxeax = vcr->r_eax; - { - /*LINTED [vendor string from cpuid data]*/ - uint32_t *iptr = (uint32_t *)vendor; - - *iptr++ = vcr->r_ebx; - *iptr++ = vcr->r_edx; - *iptr++ = vcr->r_ecx; - - vendor[12] = '\0'; - } - - if (maxeax > max_maxeax) { - cmprintf("cpu: warning, maxeax was 0x%x -> 0x%x\n", - maxeax, max_maxeax); - maxeax = max_maxeax; - } - - if (maxeax < 1) - return (0); /* no additional functions, not an AMD64 */ - else { - uint_t family, model, step; - - amd64_cpuid_insn(1, vcr); - - /* - * All AMD64/IA32e processors technically SHOULD report - * themselves as being in family 0xf, but for some reason - * Simics doesn't, and this may change in the future, so - * don't error out if it's not true. - */ - if ((family = BITX(vcr->r_eax, 11, 8)) == 0xf) - family += BITX(vcr->r_eax, 27, 20); - - if ((model = BITX(vcr->r_eax, 7, 4)) == 0xf) - model += BITX(vcr->r_eax, 19, 16) << 4; - step = BITX(vcr->r_eax, 3, 0); - - cmprintf("cpu: '%s' family %d model %d step %d\n", - vendor, family, model, step); - stdfeatures = vcr->r_edx; - } - -#ifdef DEBUG - if (amd64_debug) { - cmprintf("cpu: standard cpuid data:\n"); - amd64_dump_cpuid(0, maxeax); - } -#endif /* DEBUG */ - - amd64_cpuid_insn(0x80000000, vcr); - - if (vcr->r_eax & 0x80000000) { - uint32_t xmaxeax = vcr->r_eax; - const uint32_t max_xmaxeax = 0x80000100; - - if (xmaxeax > max_xmaxeax) { - cmprintf("amd64: warning, xmaxeax was 0x%x -> 0x%x\n", - xmaxeax, max_xmaxeax); - xmaxeax = max_xmaxeax; - } - -#ifdef DEBUG - if (amd64_debug) { - cmprintf("amd64: extended cpuid data:\n"); - amd64_dump_cpuid(0x80000000, xmaxeax); - } -#endif /* DEBUG */ - - if (xmaxeax >= 0x80000001) { - amd64_cpuid_insn(0x80000001, vcr); - xtdfeatures = vcr->r_edx; - } - } - - if (BITX(xtdfeatures, 29, 29)) /* long mode */ - isamd64++; - else - cmprintf("amd64: CPU does NOT support long mode\n"); - - if (!BITX(stdfeatures, 0, 0)) { - cmprintf("amd64: CPU does NOT support FPU\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 3, 3)) { - cmprintf("amd64: CPU does NOT support PSE\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 4, 4)) { - cmprintf("amd64: CPU does NOT support TSC\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 5, 5)) { - cmprintf("amd64: CPU does NOT support MSRs\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 6, 6)) { - cmprintf("amd64: CPU does NOT support PAE\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 8, 8)) { - cmprintf("amd64: CPU does NOT support CX8\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 13, 13)) { - cmprintf("amd64: CPU does NOT support PGE\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 17, 17)) { - cmprintf("amd64: CPU does NOT support PSE\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 19, 19)) { - cmprintf("amd64: CPU does NOT support CLFSH\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 23, 23)) { - cmprintf("amd64: CPU does NOT support MMX\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 24, 24)) { - cmprintf("amd64: CPU does NOT support FXSR\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 25, 25)) { - cmprintf("amd64: CPU does NOT support SSE\n"); - isamd64--; - } - - if (!BITX(stdfeatures, 26, 26)) { - cmprintf("amd64: CPU does NOT support SSE2\n"); - isamd64--; - } - - if (isamd64 < 1) { - cmprintf("amd64: CPU does not support amd64 executables.\n"); - return (0); - } - - amd64_rdmsr(MSR_AMD_EFER, &efer); - if (efer & AMD_EFER_SCE) - cmprintf("amd64: EFER_SCE (syscall/sysret) already enabled\n"); - if (efer & AMD_EFER_NXE) - cmprintf("amd64: EFER_NXE (no-exec prot) already enabled\n"); - if (efer & AMD_EFER_LME) - cmprintf("amd64: EFER_LME (long mode) already enabled\n"); - - return (detect_target_operating_mode()); -} - -/* - * Issue 'Detect Target Operating Mode' callback to the BIOS - */ -static int -detect_target_operating_mode() -{ - struct int_pb ic = {0}; - int ret, ah; - - ic.ax = 0xec00; /* Detect Target Operating Mode */ - ic.bx = 0x03; /* mixed mode target */ - - ret = bios_doint(0x15, &ic); - - ah = ic.ax >> 8; - if (ah == 0x86 && (ret & PS_C) != 0) { - dprintf("[BIOS 'Detect Target Operating Mode' " - "callback unsupported on this platform]\n"); - return (1); /* unsupported, ignore */ - } - - if (ah == 0x0 && (ret & PS_C) == 0) { - dprintf("[BIOS accepted mixed-mode target setting!]\n"); - return (1); /* told the bios what we're up to */ - } - - if (ah == 0 && ret & PS_C && !amd64_special_hw()) { - printf("fatal: BIOS reports this machine CANNOT run in mixed " - "32/64-bit mode!\n"); - return (0); - } - - dprintf("warning: BIOS Detect Target Operating Mode callback " - "confused.\n %%ax = 0x%x, carry = %d\n", ic.ax, - ret & PS_C ? 1 : 0); - - return (1); -} diff --git a/usr/src/psm/stand/boot/amd64/exception.s b/usr/src/psm/stand/boot/amd64/exception.s deleted file mode 100644 index 0d696a6120..0000000000 --- a/usr/src/psm/stand/boot/amd64/exception.s +++ /dev/null @@ -1,268 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. - * Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T - * All Rights Reserved - */ -#if defined(__lint) - -#include <sys/link.h> - -#include <amd64/amd64.h> - -#endif /* __lint */ - -#include <sys/asm_linkage.h> -#include <sys/controlregs.h> -#include <sys/trap.h> - -#include <amd64/machregs.h> - -#include <assym.h> - -#ifdef lint -void -amd64_div0trap(void) -{} - -void -amd64_dbgtrap(void) -{} - -void -amd64_nmiint(void) -{} - -void -amd64_brktrap(void) -{} - -void -amd64_ovflotrap(void) -{} - -void -amd64_boundstrap(void) -{} - -void -amd64_invoptrap(void) -{} - -void -amd64_ndptrap(void) -{} - -void -amd64_doublefault(void) -{} - -void -amd64_overrun(void) -{} - -void -amd64_invtsstrap(void) -{} - -void -amd64_segnptrap(void) -{} - -void -amd64_stktrap(void) -{} - -void -amd64_gptrap(void) -{} - -void -amd64_pftrap(void) -{} - -void -amd64_resvtrap(void) -{} - -void -amd64_ndperr(void) -{} - -void -amd64_achktrap(void) -{} - -void -amd64_mcetrap(void) -{} - -void -amd64_xmtrap(void) -{} - -void -amd64_invaltrap(void) -{} - -#else - -/* - * never returns. - */ -#define TRAP(trapno) \ - push $trapno; \ - jmp __amd64_exception; - - .text - .code64 - - ENTRY_NP(amd64_div0trap) - push $0 - TRAP(T_ZERODIV) / $0 - hlt - SET_SIZE(amd64_div0trap) - - ENTRY_NP(amd64_dbgtrap) - push $0 - TRAP(T_SGLSTP) / $1 - hlt - SET_SIZE(amd64_dbgtrap) - - ENTRY_NP(amd64_nmiint) - push $0 - TRAP(T_NMIFLT) / $2 - hlt - SET_SIZE(amd64_nmiint) - - ENTRY_NP(amd64_brktrap) - push $0 - TRAP(T_BPTFLT) / $3 - hlt - SET_SIZE(amd64_brktrap) - - ENTRY_NP(amd64_ovflotrap) - push $0 - TRAP(T_OVFLW) / $4 - hlt - SET_SIZE(amd64_ovflotrap) - - ENTRY_NP(amd64_boundstrap) - push $0 - TRAP(T_BOUNDFLT) / $5 - hlt - SET_SIZE(amd64_boundstrap) - - ENTRY_NP(amd64_invoptrap) - push $0 - TRAP(T_ILLINST) / $6 - hlt - SET_SIZE(amd64_invoptrap) - - ENTRY_NP(amd64_ndptrap) - push $0 - TRAP(T_NOEXTFLT) / $7 - hlt - SET_SIZE(amd64_ndptrap) - - ENTRY_NP(amd64_doublefault) - push $0 - TRAP(T_DBLFLT) / $8 - hlt - SET_SIZE(amd64_doublefault) - - ENTRY_NP(amd64_overrun) - push $0 - TRAP(T_EXTOVRFLT) / $9 i386 only - not generated - hlt - SET_SIZE(amd64_overrun) - - ENTRY_NP(amd64_invtsstrap) - TRAP(T_TSSFLT) / $10 already have error code on stack - hlt - SET_SIZE(amd64_invtsstrap) - - ENTRY_NP(amd64_segnptrap) - TRAP(T_SEGFLT) / $11 already have error code on stack - hlt - SET_SIZE(amd64_segnptrap) - - ENTRY_NP(amd64_stktrap) - TRAP(T_STKFLT) / $12 already have error code on stack - hlt - SET_SIZE(amd64_stktrap) - - ENTRY_NP(amd64_gptrap) - TRAP(T_GPFLT) / $13 already have error code on stack - hlt - SET_SIZE(amd64_gptrap) - - ENTRY_NP(amd64_pftrap) - TRAP(T_PGFLT) / $14 already have error code on stack - hlt - SET_SIZE(amd64_pftrap) - - ENTRY_NP(amd64_resvtrap) - TRAP(15) / (reserved) - hlt - SET_SIZE(amd64_resvtrap) - - ENTRY_NP(amd64_ndperr) - push $0 - TRAP(T_EXTERRFLT) / $16 - hlt - SET_SIZE(amd64_ndperr) - - ENTRY_NP(amd64_achktrap) - TRAP(T_ALIGNMENT) / $17 zero already on stack - hlt - SET_SIZE(amd64_achktrap) - - ENTRY_NP(amd64_mcetrap) - push $0 - TRAP(T_MCE) / $18 - hlt - SET_SIZE(amd64_mcetrap) - - ENTRY_NP(amd64_xmtrap) - push $0 - TRAP(T_SIMDFPE) / $19 - hlt - SET_SIZE(amd64_xmtrap) - - /* - * XX64 if amd64 had sprintf we could do better. - */ - ENTRY_NP(amd64_invaltrap) - push $0 - TRAP(-1) / invalid trap - hlt - SET_SIZE(amd64_invaltrap) -#endif /* !__lint */ diff --git a/usr/src/psm/stand/boot/amd64/genassym.c b/usr/src/psm/stand/boot/amd64/genassym.c deleted file mode 100644 index cba7592a16..0000000000 --- a/usr/src/psm/stand/boot/amd64/genassym.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <stdio.h> -#include "amd64/segments.h" - -int -main(void) -{ - (void) printf("#define\tKCS64SEL\t0x%x\n", - SEL_GDT(GDT_CODE64, SEL_KPL)); - (void) printf("#define\tKDS64SEL\t0x%x\n", - SEL_GDT(GDT_DATA64, SEL_KPL)); - (void) printf("#define\tKCS32SEL\t0x%x\n", - SEL_GDT(GDT_CODE32, SEL_KPL)); - (void) printf("#define\tKDS32SEL\t0x%x\n", - SEL_GDT(GDT_DATA32, SEL_KPL)); - (void) printf("#define\tTSS64SEL\t0x%x\n", - SEL_GDT(GDT_TSS64, SEL_KPL)); - return (0); -} diff --git a/usr/src/psm/stand/boot/amd64/handoff.c b/usr/src/psm/stand/boot/amd64/handoff.c deleted file mode 100644 index dafc7ad751..0000000000 --- a/usr/src/psm/stand/boot/amd64/handoff.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <amd64/amd64.h> -#include <amd64/print.h> -#include <amd64/amd64_page.h> -#include <amd64/cpu.h> -#include <amd64/debug.h> -#include <amd64/alloc.h> -#include <amd64/msr.h> -#include <amd64/auxv64.h> - -#ifdef DEBUG -int amd64_debug = 1; -#else -int amd64_debug = 0; -#endif - -/*ARGSUSED*/ -void -amd64_handoff(uint64_t entry) -{ - uint64_t va, pa; - void *rp; - - va = UINT64_FROMPTR32(amd64_handoff); - pa = amd64_legacy_lookup_physaddr(va, amd64_get_cr3()); - - if (va != pa) - amd64_panic("amd64 booter text not identity mapped (va 0x%llx " - "!= pa 0x%llx)\nCannot continue boot.\n", va, pa); - - rp = amd64_makectx64(entry); -#if defined(DEBUG) - amd64_dump_amd64_machregs(rp); -#endif - - /* - * XX64: Any other post-ELF load, pre-exitto() initialization required - * for AMD64 goes here. - */ - - amd64_exitto(rp); - /*NOTREACHED*/ -} - -/* - * The kernel is linked against a module whose - * name includes $MMU, thus krtld requires that - * boot supplies an mmu module list. - * - * For now, there's only one kind of mmu module for - * 64-bit systems - * - * XX64 So do we need this -- could we just link - * the kernel explicitly with mmu64? Are there - * any interesting MMU reworks in the future that - * might make this modularity more useful? - */ - -/*ARGSUSED*/ -const char * -amd64_getmmulist(void) -{ - return ("mmu64"); -} diff --git a/usr/src/psm/stand/boot/amd64/i386_subr.s b/usr/src/psm/stand/boot/amd64/i386_subr.s deleted file mode 100644 index 2f4846e927..0000000000 --- a/usr/src/psm/stand/boot/amd64/i386_subr.s +++ /dev/null @@ -1,244 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/asm_linkage.h> - -#if defined(__lint) -#include <amd64/amd64.h> -#include <amd64/cpu.h> -#else -#include <assym.h> -#endif - -#if defined(__lint) - -void -amd64_system_reset(void) -{} - -void -amd64_flush_tlb(void) -{} - -/*ARGSUSED*/ -void -amd64_flush_tlbentry(char *addr) -{} - -#else - - ENTRY_NP(amd64_system_reset) - movw $0x64, %dx - movb $0xfe, %al - outb (%dx) - hlt - SET_SIZE(amd64_system_reset); - - /* - * Note: does NOT flush global entries if PGE enabled... - */ - ENTRY_NP(amd64_flush_tlb) - movl %cr3, %eax - movl %eax, %cr3 - ret - SET_SIZE(amd64_flush_tlb) - - ENTRY_NP(amd64_flush_tlbentry) - movl 4(%esp), %eax - invlpg (%eax) - ret - SET_SIZE(amd64_flush_tlbentry) -#endif - -#if defined(__lint) - -ulong_t -amd64_get_cr0(void) -{ return (0ul); } - -ulong_t -amd64_get_cr2(void) -{ return (0ul); } - -ulong_t -amd64_get_cr3(void) -{ return (0ul); } - -ulong_t -amd64_get_cr4(void) -{ return (0ul); } - -#else - - ENTRY(amd64_get_cr0) - movl %cr0, %eax - ret - SET_SIZE(amd64_get_cr0) - - ENTRY(amd64_get_cr2) - movl %cr2, %eax - ret - SET_SIZE(amd64_get_cr2) - - ENTRY(amd64_get_cr3) - movl %cr3, %eax - ret - SET_SIZE(amd64_get_cr3) - - ENTRY(amd64_get_cr4) - movl %cr4, %eax - ret - SET_SIZE(amd64_get_cr4) - -#endif - -#if defined(__lint) - -/*ARGSUSED*/ -void -amd64_rdmsr(uint32_t msr, uint64_t *data) -{} - -/*ARGSUSED*/ -void -amd64_wrmsr(uint32_t msr, const uint64_t *data) -{} - -#else - - ENTRY(amd64_rdmsr) - movl 4(%esp), %ecx - rdmsr - movl 8(%esp), %ecx - movl %eax, (%ecx) - movl %edx, 4(%ecx) - ret - SET_SIZE(amd64_rdmsr) - - ENTRY(amd64_wrmsr) - movl 8(%esp), %ecx - movl (%ecx), %eax - movl 4(%ecx), %edx - movl 4(%esp), %ecx - wrmsr - ret - SET_SIZE(amd64_wrmsr) - -#endif /* __lint */ - -#if defined(__lint) - -ulong_t -amd64_get_eflags(void) -{ return (0); } - -#else /* __lint */ - - ENTRY(amd64_get_eflags) - pushfl - pop %eax - ret - SET_SIZE(amd64_get_eflags) - -#endif /* __lint */ - -#if defined(__lint) - -/*ARGSUSED*/ -void -amd64_cpuid_insn(uint32_t eax, struct amd64_cpuid_regs *vcr) -{} - -#else /* __lint */ - - ENTRY(amd64_cpuid_insn) - pushl %ebp - movl %esp, %ebp - pushl %ebx - pushl %esi - movl 0x8(%ebp), %eax - movl 0xc(%ebp), %esi - cpuid - movl %eax, AMD64_CPUID_REG_EAX(%esi) - movl %ebx, AMD64_CPUID_REG_EBX(%esi) - movl %ecx, AMD64_CPUID_REG_ECX(%esi) - movl %edx, AMD64_CPUID_REG_EDX(%esi) - popl %esi - popl %ebx - popl %ebp - ret - SET_SIZE(amd64_cpuid_insn) - -#endif /* __lint */ - -#if defined(__lint) - -unsigned -amd64_cpuid_supported(void) { return (1); } - -#else - /* - * Based on code from AMD64 Volume 3 - */ - ENTRY(amd64_cpuid_supported) - pushf - popl %eax - mov %eax, %edx /* save %eax for later */ - xorl %eax, 0x200000 /* toggle bit 21 */ - pushl %eax - popf /* save new %eax to EFLAGS */ - pushf /* save new EFLAGS */ - popl %ecx /* copy EFLAGS to %eax */ - xorl %eax, %eax - cmpl %ecx, %edx /* see if bit 21 has changes */ - jne 1f - incl %eax -1: - ret - SET_SIZE(amd64_cpuid_supported) -#endif /* __lint */ - -#if defined(__lint) - -unsigned -amd64_special_hw(void) { return (1); } - -#else - ENTRY(amd64_special_hw) - movl $0x564d5868, %eax - movl $0xa, %ecx - movl $0x5658, %edx - inl (%dx) - movl $0x564d5868, %ecx - xorl %eax, %eax - cmpl %ecx, %ebx - jne 1f - incl %eax -1: - ret - SET_SIZE(amd64_special_hw) -#endif /* __lint */ diff --git a/usr/src/psm/stand/boot/amd64/locore.s b/usr/src/psm/stand/boot/amd64/locore.s deleted file mode 100644 index a127e02f05..0000000000 --- a/usr/src/psm/stand/boot/amd64/locore.s +++ /dev/null @@ -1,577 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#if defined(__lint) - -#include <sys/link.h> - -#include <amd64/amd64.h> - -#endif /* __lint */ - -#include <sys/asm_linkage.h> -#include <sys/controlregs.h> - -#include <amd64/machregs.h> - -#include <assym.h> - -#if defined(__lint) - -/*ARGSUSED*/ -void -amd64_exitto(struct amd64_machregs *rp) -{} - -#else /* __lint */ - - .data - .globl need_init_cr8 -need_init_cr8: - .long 1 - - ENTRY_NP(amd64_exitto) - pushl %ebp - movl %esp, %ebp - /* - * stash current i386 state in i386_machregs - */ - lea exitto_i386_machregs, %eax - movw %ss, %dx - movzx %dx, %edx - mov %edx, i386_REG_SS(%eax) - pushfl - pop %edx - mov %edx, i386_REG_EFL(%eax) - movw %cs, %dx - movzx %dx, %edx - mov %edx, i386_REG_CS(%eax) - mov %ebx, i386_REG_EBX(%eax) - mov %esp, i386_REG_ESP(%eax) - mov %ebp, i386_REG_EBP(%eax) - mov %esi, i386_REG_ESI(%eax) - mov %edi, i386_REG_EDI(%eax) - movw %ds, %dx - movzx %dx, %edx - mov %edx, i386_REG_DS(%eax) - movw %es, %dx - movzx %dx, %edx - mov %edx, i386_REG_ES(%eax) - movw %fs, %dx - movzx %dx, %edx - mov %edx, i386_REG_FS(%eax) - movw %gs, %dx - movzx %dx, %edx - mov %edx, i386_REG_GS(%eax) - str i386_REG_TR(%eax) - sldt i386_REG_LDT(%eax) - sidt i386_REG_IDT(%eax) - sgdt i386_REG_GDT(%eax) - mov %cr4, %edx - mov %edx, i386_REG_CR4(%eax) - mov %cr3, %edx - mov %edx, i386_REG_CR3(%eax) - mov %cr2, %edx - mov %edx, i386_REG_CR2(%eax) - mov %cr0, %edx - mov %edx, i386_REG_CR0(%eax) - movl $1, need_init_cr8 /* set flag to cause %cr8 init */ -#ifdef DEBUG - push %eax - call amd64_dump_i386_machregs - addl $4, %esp -#endif /* DEBUG */ - /* - * Fetch the argument, and switch to it as a stack; - * the new stack contains an amd64_machregs on it, - * just sitting there waiting for us to restore it. - */ - mov 8(%ebp), %esp - jmp __return_to_long_mode - /*NOTREACHED*/ - SET_SIZE(amd64_exitto) - -#endif /* __lint */ - -#if defined(__lint) - -#define VTRAP_STUB_BEGIN(opname) \ - uintptr_t opname; - -#define VTRAP_STUB_END(opname) \ - uintptr_t opname; - -#define VTRAP_STUB(symname) \ - uintptr_t symname; - -#else - -#define VTRAP_STUB_BEGIN(symname) \ - .global symname; \ -symname: \ - .code64 - -#define VTRAP_STUB_END(symname) \ - .code32; \ - .global symname; \ -symname: - -/* - * callbacks from the amd64 kernel to the i386 world are handled - * as calls into a virtual amd64 boot program as if they were - * virtual traps i.e. we save the machine state, switch to i386 mode, - * then decode and interpret the request in C code (amd64_vtrap) - */ - -#define VTRAP_STUB(opname) \ - ENTRY_NP(opname); \ - pushq %rbp; \ - movq %rsp, %rbp; \ - call 1f; \ -1: pop %r11; \ - sub $_CONST(1b - opname), %r11; \ - jmp __vtrap_common; \ - SET_SIZE(opname) - - ENTRY_NP(__vtrap_common) - .code64 - /* - * put the state of the amd64 machine onto the stack - */ - movq %rsp, %r10 - addq $0x10, %r10 /* (%rsp immediately before the call) */ - push $0 /* %ss */ - push %r10 /* %rsp */ - pushf /* rflags */ - push $0 /* %cs */ - push %r11 /* %rip (the pc we came in on) */ - push $0 /* err */ - push $-1 /* trapno (virt trap# larger than idt itself) */ - cli - - ALTENTRY(__amd64_exception) /* vectored from amd64_idt */ - push $0 /* %es */ - push $0 /* %ds */ - push %fs - push %gs - push %r15 - push %r14 - push %r13 - push %r12 - push %r11 - push %r10 - push %rbp - push %rbx - push %rax - push %r9 - push %r8 - push %rcx - push %rdx - push %rsi - push %rdi - - /* - * (that was the 'struct regs' part, now for the somewhat trickier - * parts of the machine (with all the implicit state that goes - * along with those registers (?))) - */ - - str %rax - push %rax - sldt %rax - push %rax - - /* XX64 need to do some compile-time assert here to check this! */ - - push $0 - push $0 - sidt (%rsp) - - push $0 - push $0 - sgdt (%rsp) - -#define PUSH_CREG(creg) \ - mov creg, %rax; \ - push %rax - - PUSH_CREG(%cr8) - PUSH_CREG(%cr4) - PUSH_CREG(%cr3) - PUSH_CREG(%cr2) - PUSH_CREG(%cr0) - -#define PUSH_SEG_BASE(msr) \ - mov $msr, %ecx; \ - rdmsr; \ - salq $32, %rdx; \ - mov %eax, %eax; \ - or %rdx, %rax; \ - push %rax - - PUSH_SEG_BASE(MSR_AMD_FSBASE) - PUSH_SEG_BASE(MSR_AMD_GSBASE) - PUSH_SEG_BASE(MSR_AMD_KGSBASE) - - /* - * save the sodding segment registers (because push doesn't work!) - */ - mov %cs, %ax - movzx %ax, %rax - mov %rax, amd64_REG_CS(%rsp) - - mov %ds, %ax - movzx %ax, %rax - mov %rax, amd64_REG_DS(%rsp) - - mov %es, %ax - movzx %ax, %rax - mov %rax, amd64_REG_ES(%rsp) - - mov %ss, %ax - movzx %ax, %rax - mov %rax, amd64_REG_SS(%rsp) - - /* - * Back to i386 mode - */ - - /* - * reload %ds here so we can refer to i386_machregs below - */ - mov $KDS32SEL, %rax - movw %ax, %ds - - /* - * 1. Switch to compatibility mode at CPL=0 - * - * We seem forced to do this -- which is a complicated - * way to do: - * - * ljmp $KCS32SEL, $__amd64_compat_mode - * __amd64_compat_mode: - * - * which unfortunately isn't legal in long mode. - * - * You'd think this would work, but it doesn't. - * - * push $KCS32SEL - * push %rax - * lret - * - * Perhaps there's a better way? - */ - call 9f -9: pop %rax - add $_CONST(__amd64_compat_mode - 9b), %rax - mov %rsp, %rdx - push $KDS32SEL - push %rdx - pushf - push $KCS32SEL - push %rax - iretq - -__amd64_compat_mode: - .code32 - /* - * 2. Deactivate long mode by clearing CR0.PG - */ - mov %cr0, %eax - and $_BITNOT(CR0_PG), %eax - mov %eax, %cr0 - /* - * 2a. Disable PAE - */ - mov %cr4, %eax - and $_BITNOT(CR4_PAE), %eax - mov %eax, %cr4 - /* - * 3. Load CR3 with physical base address of page tables - * - * (Note we loaded %ds above) - */ - lea exitto_i386_machregs, %eax - mov i386_REG_CR3(%eax), %edx - mov %edx, %cr3 - /* - * 4. Disable long mode by clearing EFER.LME to 0 - */ - mov $MSR_AMD_EFER, %ecx - rdmsr - and $_BITNOT(AMD_EFER_LME), %eax - wrmsr - /* - * 5. Enable legacy page-translation - */ - mov %cr0, %eax - or $CR0_PG, %eax - mov %eax, %cr0 - jmp __i386_mode -__i386_mode: - /* - * Reconstruct our life as an i386 processor from the - * exitto save area. - */ - lea exitto_i386_machregs, %eax - mov i386_REG_CR0(%eax), %edx - mov %edx, %cr0 - /* - * %cr2 is the page fault address; we have no need to restore it - */ - mov i386_REG_CR3(%eax), %edx - mov %edx, %cr3 - mov i386_REG_CR4(%eax), %edx - mov %edx, %cr4 - lgdt i386_REG_GDT(%eax) - lidt i386_REG_IDT(%eax) - - /* - * Need to clear busy bit in our tss descriptor - */ -/ clrtss: -/ push %eax -/ call amd64_i386_clrtss -/ pop %eax -/ -/ ltr i386_REG_TR(%eax) - - mov i386_REG_GS(%eax), %edx - movw %dx, %gs - mov i386_REG_FS(%eax), %edx - movw %dx, %fs - mov i386_REG_ES(%eax), %edx - movw %dx, %es - mov i386_REG_DS(%eax), %edx - movw %dx, %ds - mov i386_REG_SS(%eax), %edx - movw %dx, %ss - - pushl i386_REG_EFL(%eax) - popf - - /* - * As long as the transition from long mode to i386 mode - * simply truncated %rsp -> %esp, we now have a struct amd64_machregs - * sitting on the top of the stack. - */ - pushl %esp - call amd64_vtrap - addl $4, %esp - - /* - * let's go long .. - */ -__return_to_long_mode: - mov amd64_REG_CR3(%esp), %edx - - /* - * Disable paging - */ - mov %cr0, %eax - and $_BITNOT(CR0_PG), %eax - mov %eax, %cr0 - /* - * 2a. enable PAE - */ - mov %cr4, %eax - or $CR4_PAE, %eax - mov %eax, %cr4 - /* - * 2b. load CR3 with PML4 base address - */ - mov %edx, %cr3 - /* - * 2c. enable long mode - */ - mov $MSR_AMD_EFER, %ecx - rdmsr - or $AMD_EFER_LME, %eax - wrmsr - /* - * 2d. enable paging - */ - mov %cr0, %eax - or $CR0_PG, %eax - mov %eax, %cr0 - jmp __enable_long_mode -__enable_long_mode: - - /* - * we are now in compatibility mode - * move to the 64 bit descriptor tables so that - * we find ourselves in a sane place when we lret - * and switch to 64 bit mode .. - */ - lgdt amd64_REG_GDT(%esp) - - /* - * switch to 64-bit mode - */ - call 1f -1: pop %eax - add $_CONST(__amd64_64bit_mode - 1b), %eax - mov amd64_REG_CS(%esp), %edx - push %edx - push %eax - lret -__amd64_64bit_mode: - .code64 - - /* - * the following descriptor table loads fetch the full - * 64-bit values expected by the client. - */ - lgdt amd64_REG_GDT(%rsp) - lidt amd64_REG_IDT(%rsp) - lldt amd64_REG_LDT(%rsp) - ltr amd64_REG_TR(%rsp) - - /* - * fix up the selectors for long mode - */ - mov amd64_REG_DS(%rsp), %rax - movw %ax, %ds - mov amd64_REG_ES(%rsp), %rax - movw %ax, %es - mov amd64_REG_FS(%rsp), %rax - movw %ax, %fs - mov amd64_REG_GS(%rsp), %rax - movw %ax, %gs - mov amd64_REG_SS(%rsp), %rax - movw %ax, %ss - -#define RESTORE_SEG_BASE(seg) \ - movq amd64_REG_/**/seg(%rsp), %rax; \ - movq %rax, %rdx; \ - movl %eax, %eax; \ - shrq $32, %rdx; \ - movl $MSR_AMD_/**/seg, %ecx; \ - wrmsr - - RESTORE_SEG_BASE(KGSBASE) - RESTORE_SEG_BASE(GSBASE) - RESTORE_SEG_BASE(FSBASE) - -#define RESTORE_CR(num) \ - movq amd64_REG_CR/**/num(%rsp), %rax; \ - movq %rax, %cr/**/num - - RESTORE_CR(0) - - /* don't restore %cr2 */ - - RESTORE_CR(3) - RESTORE_CR(4) - - /* - * Only restore %cr8 if it's nonzero or if we have not yet initialized - * it (if it's zero, that means it's not safe to restore it -- we're - * either using the local APIC TPR or no TPR at all). We only test the - * non-reserved bits. The %cr8 initialization is done only on the first - * transfer from the booter to the loaded image. - */ - cmpl $0, need_init_cr8(%rip) /* Did we initialize cr8 yet? */ - jnz 1f /* No? Then go and zero it. */ - - testq $0xF, amd64_REG_CR8(%rsp) /* Is the saved cr8 zero? */ - jz 2f /* Yes, -- skip the restore */ -1: - movl $0, need_init_cr8(%rip) /* Mark cr8 as initialized */ - RESTORE_CR(8) -2: - /* - * gdt/idt/ldt/tr have already been restored, as have %gs, %fs, %ds - * and %es. - * - * Meanwhile %rbp, %r11, err and trapno don't get restored at all. - */ - movq amd64_REG_RDI(%rsp), %rdi - movq amd64_REG_RSI(%rsp), %rsi - movq amd64_REG_RAX(%rsp), %rax - movq amd64_REG_RCX(%rsp), %rcx - movq amd64_REG_RDX(%rsp), %rdx - movq amd64_REG_R8(%rsp), %r8 - movq amd64_REG_R9(%rsp), %r9 - movq amd64_REG_RBX(%rsp), %rbx - movq amd64_REG_R10(%rsp), %r10 - movq amd64_REG_R12(%rsp), %r12 - movq amd64_REG_R13(%rsp), %r13 - movq amd64_REG_R14(%rsp), %r14 - movq amd64_REG_R15(%rsp), %r15 - - /* - * The bottom five arguments in the struct amd64_machregs on the - * stack (starting with r_rip) are positioned such that they can be - * used as-is by iretq to return to the caller, switch interrupts - * back on if needed, and restore the proper %rsp. - * - * HOWEVER, we need the %rbp and %rip sitting in the return frame - * on the stack, so grab them from beyond the end of the amd64_machregs - * structure on the stack so that everything will be restored properly - * by the iretq. - * - * The stack after the addq below will be: - * - * 0 amd64_machregs %rip - * +8 amd64_machregs %cs - * +0x10 amd64_machflags rflags - * +0x18 amd64_machflags %rsp - * +0x20 amd64_machflags %ss - * +0x28 return %rbp from bootops 'call' insn - * +0x30 return %rip from bootops 'call' insn - */ - addq $amd64_REG_RIP, %rsp - movq 0x28(%rsp), %rbp /* load the return %rbp to %rbp */ - movq 0x30(%rsp), %r11 /* copy the return %rip to %r11 */ - movq %r11, (%rsp) /* save it as amd64_machregs' r_rip */ - iretq - SET_SIZE(__vtrap_common) - -#endif /* __lint */ - - VTRAP_STUB_BEGIN(bop64_first) - - VTRAP_STUB(bop64_alloc) - VTRAP_STUB(bop64_free) - VTRAP_STUB(bop64_getproplen) - VTRAP_STUB(bop64_getprop) - VTRAP_STUB(bop64_nextprop) - VTRAP_STUB(bop64_printf) - VTRAP_STUB(bop64_doint) - VTRAP_STUB(bop64_ealloc) - - VTRAP_STUB_END(bop64_last) - - VTRAP_STUB_BEGIN(bsys64_first) - - VTRAP_STUB(bsys64_getchar) - VTRAP_STUB(bsys64_putchar) - VTRAP_STUB(bsys64_ischar) - - VTRAP_STUB_END(bsys64_last) diff --git a/usr/src/psm/stand/boot/amd64/memlist.c b/usr/src/psm/stand/boot/amd64/memlist.c deleted file mode 100644 index da62480d1d..0000000000 --- a/usr/src/psm/stand/boot/amd64/memlist.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <amd64/boothooks.h> -#include <amd64/print.h> -#include <amd64/types.h> -#include <amd64/bootops64.h> -#include <amd64/memlist64.h> -#include <amd64/amd64_page.h> - -struct memlist64 * -amd64_convert_memlist(struct memlist *ml, struct memlist64 *ml64) -{ - extern struct memlist64 *amd64_memlistpage; - - ml64->prev = (caddr64_t)0; - - while (ml) { - ml64->address = ml->address; - ml64->size = ml->size; - ml = ml->next; - - if (ml) { - struct memlist64 *next_ml = ml64 + 1; - - ml64->next = (caddr64_t)(uintptr_t)next_ml; - next_ml->prev = (caddr64_t)(uintptr_t)ml64; - ml64++; - - /* - * This may end up being shortsighted, but currently - * boot will panic if the memlists don't all fit on - * one page so we may as well make the same assumption. - */ - if ((uint64_t)(uintptr_t)ml64 > ((uint64_t)(uintptr_t) - amd64_memlistpage + AMD64_PAGESIZE)) - amd64_panic("Memory space for 64-bit memlists " - "exhausted when converting memlist @ 0x%x.", - (uint32_t)ml->prev); - } - } - - ml64->next = (caddr64_t)0; - return (ml64 + 1); -} diff --git a/usr/src/psm/stand/boot/amd64/offsets.in b/usr/src/psm/stand/boot/amd64/offsets.in deleted file mode 100644 index b07ea48e76..0000000000 --- a/usr/src/psm/stand/boot/amd64/offsets.in +++ /dev/null @@ -1,111 +0,0 @@ -\ -\ Copyright 2005 Sun Microsystems, Inc. All rights reserved. -\ Use is subject to license terms. -\ -\ CDDL HEADER START -\ -\ The contents of this file are subject to the terms of the -\ Common Development and Distribution License, Version 1.0 only -\ (the "License"). You may not use this file except in compliance -\ with the License. -\ -\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -\ or http://www.opensolaris.org/os/licensing. -\ See the License for the specific language governing permissions -\ and limitations under the License. -\ -\ When distributing Covered Code, include this CDDL HEADER in each -\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. -\ If applicable, add the following below this CDDL HEADER, with the -\ fields enclosed by brackets "[]" replaced with your own identifying -\ information: Portions Copyright [yyyy] [name of copyright owner] -\ -\ CDDL HEADER END -\ - -#pragma ident "%Z%%M% %I% %E% SMI" - -\ -\ offsets.in: input file to produce assym.h using the ctfstabs program -\ - -#include <sys/types.h> -#include <amd64/cpu.h> -#include <amd64/machregs.h> -#include <amd64/tss.h> -#include <amd64/segments.h> - -amd64_cpuid_regs - r_eax AMD64_CPUID_REG_EAX - r_ebx AMD64_CPUID_REG_EBX - r_ecx AMD64_CPUID_REG_ECX - r_edx AMD64_CPUID_REG_EDX - -amd64_machregs SIZEOF_amd64_machregs - r_kgsbase amd64_REG_KGSBASE - r_gsbase amd64_REG_GSBASE - r_fsbase amd64_REG_FSBASE - r_cr0 amd64_REG_CR0 - r_cr2 amd64_REG_CR2 - r_cr3 amd64_REG_CR3 - r_cr4 amd64_REG_CR4 - r_cr8 amd64_REG_CR8 - r_gdt_un.un_gdt amd64_REG_GDT - r_idt_un.un_idt amd64_REG_IDT - r_ldt amd64_REG_LDT - r_tr amd64_REG_TR - r_rdi amd64_REG_RDI - r_rsi amd64_REG_RSI - r_rdx amd64_REG_RDX - r_rcx amd64_REG_RCX - r_r8 amd64_REG_R8 - r_r9 amd64_REG_R9 - r_rax amd64_REG_RAX - r_rbx amd64_REG_RBX - r_rbp amd64_REG_RBP - r_r10 amd64_REG_R10 - r_r11 amd64_REG_R11 - r_r12 amd64_REG_R12 - r_r13 amd64_REG_R13 - r_r14 amd64_REG_R14 - r_r15 amd64_REG_R15 - r_gs amd64_REG_GS - r_fs amd64_REG_FS - r_ds amd64_REG_DS - r_es amd64_REG_ES - r_trapno amd64_REG_TRAPNO - r_err amd64_REG_ERR - r_rip amd64_REG_RIP - r_cs amd64_REG_CS - r_rfl amd64_REG_FLAGS - r_rsp amd64_REG_RSP - r_ss amd64_REG_SS - -i386_machregs SIZEOF_i386_machregs - r_ss i386_REG_SS - r_uesp i386_REG_UESP - r_efl i386_REG_EFL - r_cs i386_REG_CS - r_eip i386_REG_EIP - r_err i386_REG_ERR - r_trapno i386_REG_TRAPNO - r_eax i386_REG_EAX - r_ecx i386_REG_ECX - r_edx i386_REG_EDX - r_ebx i386_REG_EBX - r_esp i386_REG_ESP - r_ebp i386_REG_EBP - r_esi i386_REG_ESI - r_edi i386_REG_EDI - r_ds i386_REG_DS - r_es i386_REG_ES - r_fs i386_REG_FS - r_gs i386_REG_GS - r_tr i386_REG_TR - r_ldt i386_REG_LDT - r_idt_un.un_idt i386_REG_IDT - r_gdt_un.un_gdt i386_REG_GDT - r_cr4 i386_REG_CR4 - r_cr3 i386_REG_CR3 - r_cr2 i386_REG_CR2 - r_cr0 i386_REG_CR0 diff --git a/usr/src/psm/stand/boot/amd64/print.c b/usr/src/psm/stand/boot/amd64/print.c deleted file mode 100644 index 7f2f7f3aef..0000000000 --- a/usr/src/psm/stand/boot/amd64/print.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/inttypes.h> -#include <sys/varargs.h> -#include <sys/promif.h> - -#include <amd64/print.h> -#include <amd64/amd64.h> - -/* - * Printn prints a number n in base b. - * We don't use recursion to avoid deep stacks. - */ -static void -__amd64_printn(uint64_t n, int b, int width, int pad, - void (*put)(void *, int), void *arg) -{ - char prbuf[65]; - char *cp; - - cp = prbuf; - do { - *cp++ = "0123456789abcdef"[n%b]; - n /= b; - width--; - } while (n); - while (width-- > 0) - *cp++ = (char)pad; - do { - (*put)(arg, *--cp); - } while (cp > prbuf); -} - -/* - * This routine is highly specific to amd64, and is essentially a - * complete kludge which allows amd64 to print using the 64-bit regs - * from an LP64 kernel. - * - * The worst part about it is the assumptions around decoding string - * pointers -- we assume that the top bits of the string pointer can - * be discarded yet still remain as a valid address. - * - * cell size == sizeof (long long) - */ -static void -__amd64_doprnt64( - const char *fmt, - va_list adx, - void (*put)(void *, int), - void *arg) -{ - int b, c, i, pad, width, ells; - char *s; - int64_t l; - uint64_t ul; - -loop: - while ((c = *fmt++) != '%') { - if (c == '\0') - goto out; - (*put)(arg, c); - } - - c = *fmt++; - for (pad = ' '; c == '0'; c = *fmt++) - pad = '0'; - - for (width = 0; c >= '0' && c <= '9'; c = *fmt++) - width = width * 10 + c - '0'; - - for (ells = 0; c == 'l'; c = *fmt++) - ells++; - - switch (c) { - case 'd': - case 'D': - b = 10; - if (ells == 0) - l = (int64_t)(int)va_arg(adx, int64_t); - else if (ells == 1) - l = (int64_t)va_arg(adx, int64_t); - else - l = (int64_t)va_arg(adx, int64_t); - if (l < 0) { - (*put)(arg, '-'); - width--; - ul = -l; - } else - ul = l; - goto number; - - case 'p': - ells = 1; - /*FALLTHROUGH*/ - case 'x': - case 'X': - b = 16; - goto u_number; - - case 'u': - b = 10; - goto u_number; - - case 'o': - case 'O': - b = 8; -u_number: - if (ells == 0) - ul = (uint64_t)(uint_t)va_arg(adx, uint64_t); - else if (ells == 1) - ul = (uint64_t)va_arg(adx, uint64_t); - else - ul = (uint64_t)va_arg(adx, uint64_t); -number: - __amd64_printn(ul, b, width, pad, put, arg); - break; - - case 'c': - b = (int)va_arg(adx, uint64_t); - for (i = 24; i >= 0; i -= 8) - if ((c = ((b >> i) & 0x7f)) != 0) - (*put)(arg, (char)c); - break; - - /* - * Yuck. We're encoding the assumption that a valid 32-bit pointer - * can be obtained by simply truncating the 64-bit pointer. - */ - case 's': - s = (char *)(uintptr_t)va_arg(adx, uint64_t); - for (width -= strlen(s); width > 0; width--) - (*put)(arg, pad); - while ((c = *s++) != 0) - (*put)(arg, c); - break; - - case '%': - (*put)(arg, (char)c); - break; - - default: - break; - } - goto loop; -out: - ; -} - -struct strbuf { - char *sb_base; - char *sb_ptr; - size_t sb_maxsize; -}; - -static void -sput(void *arg, int c) -{ - struct strbuf *sb = arg; - - if (c == '\n') - sput(arg, '\r'); - - if ((sb->sb_ptr - sb->sb_base) >= sb->sb_maxsize) - sb->sb_ptr++; - else - *sb->sb_ptr++ = (char)c; -} - -static int -amd64_vsnprintf_helper(char *s, size_t n, const char *fmt, va_list ap, - void (*doprnt)(const char *, va_list, void (*)(void *, int), void *)) -{ - struct strbuf sbuf, *sb = &sbuf; - int count; - - sb->sb_base = sb->sb_ptr = s; - sb->sb_maxsize = n; - - (*doprnt)(fmt, ap, sput, sb); - - /* - * Ensure there's a trailing NULL to terminate the string - */ - if (sb->sb_maxsize == 0) - return ((int)(sb->sb_ptr - sb->sb_base)); - if ((count = sb->sb_ptr - sb->sb_base) >= sb->sb_maxsize) - sb->sb_ptr = sb->sb_base + sb->sb_maxsize - 1; - if (sb->sb_ptr) - *sb->sb_ptr = '\0'; - return (count); -} - -/* - * Specialized vsnprintf() that is used to print arguments from - * an environment where the native argument size is 64-bit - */ -int -amd64_vsnprintf64(char *s, size_t n, const char *fmt, va_list ap) -{ - return (amd64_vsnprintf_helper(s, n, fmt, ap, __amd64_doprnt64)); -} - -int -amd64_snprintf64(char *s, size_t n, const char *fmt, ...) -{ - int r; - va_list ap; - - va_start(ap, fmt); - r = amd64_vsnprintf64(s, n, fmt, ap); - va_end(ap); - return (r); -} - -struct amd64buf { - char *vb_base; - char *vb_ptr; - size_t vb_maxsize; - struct bootops *vb_bop; -}; - -void -amd64_vpanic(const char *fmt, va_list ap) -{ - printf("amd64_panic: "); - prom_vprintf(fmt, ap); - printf("\n"); - amd64_system_reset(); -} - -void -amd64_panic(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - amd64_vpanic(fmt, ap); - va_end(ap); -} - -void -amd64_warning(const char *fmt, ...) -{ - va_list ap; - - printf("amd64 warning: "); - va_start(ap, fmt); - prom_vprintf(fmt, ap); - va_end(ap); - printf("\n"); -} diff --git a/usr/src/psm/stand/boot/amd64/ptops.c b/usr/src/psm/stand/boot/amd64/ptops.c deleted file mode 100644 index 3b6244efe9..0000000000 --- a/usr/src/psm/stand/boot/amd64/ptops.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> - -#include <amd64/amd64.h> -#include <amd64/print.h> -#include <amd64/debug.h> -#include <amd64/alloc.h> -#include <amd64/cpu.h> -#include <amd64/amd64_page.h> - -static amd64_mmumode_t mmus[] = { - { 22, 10, 2, 1024 }, /* legacy 32-bit mode */ - { 39, 9, 4, 512 } /* long 64-bit mode */ -}; - -uint16_t -amd64_modbits(uint64_t entry) -{ - return ((uint16_t)PA_MODBITS(entry)); -} - -uint64_t -amd64_legacy_physaddr(uint32_t entry) -{ - return (IS_LARGEMAP(entry) ? - ((uint64_t)(entry) & ~0x3fffffULL | - (((uint64_t)(entry) >> 13) & 0xffULL) << 32) - : ((uint64_t)(entry) & ~0xfffULL)); -} - -uint64_t -amd64_long_physaddr(uint64_t entry) -{ - return (IS_LARGEMAP(entry) ? (entry & ~0x1fffffULL) : - (entry & ~0xfffULL)); -} - -uint64_t -amd64_physaddr(uint64_t entry, uint8_t amd64_mmu_mode) -{ - return (amd64_mmu_mode == AMD64_MODE_LONG64) ? - amd64_long_physaddr(entry) : amd64_legacy_physaddr((uint32_t)entry); -} - -static uint64_t -amd64_tbl_lookup(uint8_t amd64_mmu_mode, uint64_t va, uint32_t tbl_base, - uint32_t *addr_inc) -{ - uint8_t level; - uint8_t level_shift = mmus[amd64_mmu_mode].level_shift; - uint8_t pde_level = mmus[amd64_mmu_mode].map_level - 1; - uint8_t shift = mmus[amd64_mmu_mode].shift_base; - uint64_t mask = (1ULL << level_shift) - 1; - uint64_t entry; - - ASSERT(tbl_base); - - for (level = 1; shift > AMD64_PAGESIZE_OFFSET_NBITS; - shift -= level_shift, level++) { - entry = TBL_ENTRY64(amd64_mmu_mode, tbl_base, va, shift, - mask); - - if (!(ENTRY_VALID(entry))) { - /* - * If a page level is empty, set addr_inc to the shift - * value because in a sequential search we know the next - * (1 << level_shift) bytes are unmapped. - */ - while (shift >= 32) - shift -= level_shift; /* XXX */ - - if (addr_inc) - *addr_inc = (1 << shift); - - return (0); - } - - if (((level == pde_level) && (IS_LARGEMAP(entry))) || - IS_PTE(level, amd64_mmu_mode)) { - /* Set addr_inc to pagesize found and return entry. */ - - while (shift >= 32) - shift -= level_shift; /* XXX */ - - if (addr_inc) - *addr_inc = (1 << shift); - - return (entry); - } - - tbl_base = (uint32_t)amd64_physaddr(entry, amd64_mmu_mode); - } - - if (addr_inc) - *addr_inc = (uint32_t)AMD64_PAGESIZE; - - return (0); -} - -uint64_t -amd64_long_lookup(uint64_t va, uint32_t *addr_inc, uint32_t tbl_base) -{ - return (amd64_tbl_lookup(AMD64_MODE_LONG64, va, tbl_base, addr_inc)); -} - -uint32_t -amd64_legacy_lookup(uint64_t va, uint32_t *addr_inc, uint32_t tbl_base) -{ - return ((uint32_t)amd64_tbl_lookup(AMD64_MODE_LEGACY, va, tbl_base, - addr_inc)); -} - -uint64_t -amd64_legacy_lookup_physaddr(uint64_t va, uint32_t tbl_base) -{ - uint32_t entry, pagesize; - uint64_t offset; - - if (!(entry = amd64_legacy_lookup(va, &pagesize, tbl_base))) - amd64_panic("legacy lookup failed for va 0x%llx\n!", va); - - offset = va & AMD64_PAGEOFFSET(pagesize); - return (amd64_legacy_physaddr(entry) + offset); -} - -uint64_t -amd64_long_lookup_physaddr(uint64_t va, uint32_t tbl_base) -{ - uint32_t pagesize; - uint64_t entry, offset; - - if (!(entry = amd64_long_lookup(va, &pagesize, tbl_base))) - amd64_panic("long lookup failed for va 0x%llx\n!", va); - - offset = va & AMD64_PAGEOFFSET(pagesize); - return (amd64_long_physaddr(entry) + offset); -} - -void -amd64_map_mem(uint64_t va, uint64_t pa, uint32_t len, uint8_t amd64_mmu_mode, - uint32_t tbl_base, uint16_t page_modbits) -{ - uint64_t parentlvl_entry; - uint64_t entry; - uint64_t local_pagebits; - - uint32_t pagesize; - uint32_t parent_base; - uint32_t tbl_root = tbl_base; - - uint8_t level_shift = mmus[amd64_mmu_mode].level_shift; - uint64_t idx_mask = (1ULL << level_shift) - 1; - - uint8_t level, map_level; - uint8_t shift; - - ASSERT(tbl_base); - ASSERT(AMD64_PAGEALIGNED(va, AMD64_PAGESIZE)); - ASSERT(AMD64_PAGEALIGNED(pa, AMD64_PAGESIZE)); - ASSERT(AMD64_PAGEALIGNED(len, AMD64_PAGESIZE)); - - if ((amd64_mmu_mode == AMD64_MODE_LONG64) && ((va >> 47) & 1) && - ((va >> 48) != 0xffffULL)) - amd64_panic("amd64_map_mem: map attempted into 64-bit VA " - "hole (va 0x%llx)\n", va); - - while (len != 0) { - map_level = mmus[amd64_mmu_mode].map_level; - - /* - * Check to see if we're mapping a range that could be - * mapped by a large page one page table level up. If so, - * use the larger page for efficiency: - * - * Long 64-bit mode: 2M PAGE = (AMD64_PAGESIZE << LEVEL_SHIFT) - * Legacy 32-bit mode: 4M PAGE = (AMD64_PAGESIZE << LEVEL_SHIFT) - */ - pagesize = AMD64_PAGESIZE << level_shift; - - if (AMD64_PAGEALIGNED(va, pagesize) && AMD64_PAGEALIGNED(pa, - pagesize) && (len >= pagesize)) { - map_level--; - local_pagebits = PDE_PS; - } else { - pagesize = AMD64_PAGESIZE; - local_pagebits = 0; - } - - level = 1; - shift = mmus[amd64_mmu_mode].shift_base; - - while ((level <= map_level) && (len >= pagesize)) { - entry = TBL_ENTRY64(amd64_mmu_mode, tbl_base, va, shift, - idx_mask); - - if (level < map_level) { - if (!(ENTRY_VALID(entry))) { - uint32_t page; - - /* - * Grab an identity-mapped page at this - * level for an array of entries. - */ - page = (uint32_t)amd64_zalloc_identity( - AMD64_PAGESIZE); - - /* - * Setup entry pointing to the new array - */ - entry = TBL_ENTRY_DEFAULT(page); - - /* - * Insert new entry into table - */ - SET_TABLEVAL(amd64_mmu_mode, tbl_base, - va, shift, idx_mask, entry); - - /* - * If we're mapping in 64-bit long mode, - * make sure to identity map the - * allocation above into the 64-bit - * page tables to make sure the kernel - * can walk the 64-bit page tables. - */ - if (amd64_mmu_mode == - AMD64_MODE_LONG64) - amd64_map_mem( - (uint64_t)page, - (uint64_t)page, - AMD64_PAGESIZE, - amd64_mmu_mode, tbl_root, - page_modbits); - } - - /* - * Continue down another level. - */ - if ((level + 1) == map_level) { - parent_base = tbl_base; - parentlvl_entry = entry; - } - - tbl_base = (uint32_t)amd64_physaddr(entry, - amd64_mmu_mode); - shift -= level_shift; - level++; - continue; - } - - do { - /* - * Create mapping entry at this level. - */ - entry = TBL_ENTRY_DEFAULT(pa) | page_modbits | - local_pagebits; - - /* - * Install mapping entry - */ - SET_TABLEVAL(amd64_mmu_mode, tbl_base, va, - shift, idx_mask, entry); - - va += pagesize; - pa += pagesize; - len -= pagesize; - } while ((TBL_ENTRY64(amd64_mmu_mode, parent_base, va, - shift + level_shift, - idx_mask) == parentlvl_entry) && (len >= pagesize)); - - if (len != 0) { - /* - * We went over a parent's table entry mapping - * border, so we need to recalculate where we - * should be adding page tables. - * - * For example, if we are mapping 4K page - * tables in long mode, this means we crossed a - * 2M boundary. (It would be a 4M boundary for - * 32-bit legacy mode.) - */ - level = 1; - tbl_base = tbl_root; - shift = mmus[amd64_mmu_mode].shift_base; - } - } - } -} - -/* - * Save top of boot's 64-bit page tables for future use. - */ -uint64_t amd64_boot_pml4; - -/* - * Initialize long page tables - */ -uint64_t -amd64_init_longpt(uint32_t cr3) -{ - extern int magic_phys; - int i; - uint64_t *pml4, *pdpt, *pdpt_hi, *pdt, *pte_zero; - - pml4 = amd64_zalloc_identity(AMD64_PAGESIZE); - pdpt = amd64_zalloc_identity(AMD64_PAGESIZE); - pdpt_hi = amd64_zalloc_identity(AMD64_PAGESIZE); - pdt = amd64_zalloc_identity(AMD64_PAGESIZE * 4); - pte_zero = amd64_zalloc_identity(AMD64_PAGESIZE); - - /* - * Initialize long mode page tables. - * - * The only initial mappings are those for the identity mapped boot 4M - * (0x01000:0x400000) and those boot has already allocated. - */ - *pml4 = TBL_ENTRY_DEFAULT(pdpt); - - /* - * Preallocate enough level two and three entries to map the lower 4G - * of VA space, which will be reflected to the top 4G of VM space - * directly at the level two page tables. - */ - *(pml4 + 511) = TBL_ENTRY_DEFAULT(pdpt_hi); - - *pdpt = *(pdpt_hi + 508) = TBL_ENTRY_DEFAULT(pdt); - *(pdpt + 1) = *(pdpt_hi + 509) = TBL_ENTRY_DEFAULT(pdt + 512); - *(pdpt + 2) = *(pdpt_hi + 510) = TBL_ENTRY_DEFAULT(pdt + 1024); - *(pdpt + 3) = *(pdpt_hi + 511) = TBL_ENTRY_DEFAULT(pdt + 1536); - - *pdt = TBL_ENTRY_DEFAULT(pte_zero); /* leave page zero unmapped */ - - /* Identity map VA 0x200000:magic_phys at the PDE level via 2M pages */ - for (i = 1; (i + 1) * 0x200000 < magic_phys; i++) - *(pdt + i) = TBL_ENTRY_DEFAULT(i * 0x200000) | PDE_PS; - - /* - * Copy the balance of boot's initial mappings - this will fill in - * mapped entries in the page tables other than the 2M identity mapped - * page mentioned above. - */ - amd64_xlate_boot_tables(cr3, (uint32_t)pml4); - amd64_boot_pml4 = UINT64_FROMPTR32(pml4); - - return (amd64_boot_pml4); -} diff --git a/usr/src/psm/stand/boot/amd64/ptxlate.c b/usr/src/psm/stand/boot/amd64/ptxlate.c deleted file mode 100644 index 80e20f783a..0000000000 --- a/usr/src/psm/stand/boot/amd64/ptxlate.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> - -#include <amd64/amd64.h> -#include <amd64/print.h> -#include <amd64/debug.h> -#include <amd64/amd64_page.h> - -/* - * NOTE: ALL these routines assume that page tables are identity mapped (1:1, - * VA == PA). If they cannot access a given physical address by - * dereferencing the equivalent virtual address, they will fail due to - * the inability of the x86 to easily access any given physical address - * without explicitly mapping a special page specifically to do so. - * - * Since boot already maps the 32-bit page tables this way and we control - * creation of the 64-bit page tables, we can assure that this remains - * the case unless a callback is made from 64-bit mode that references a - * kernel-mapped page; doing THAT will likely cause a crash as the - * routines try to dereference an unmapped or wrong address. - */ - -/* - * Routines to manage legacy 32-bit and long mode 64-bit page mappings - */ - -void -amd64_xlate_legacy_va(uint32_t va, uint32_t len, uint32_t legacy_ptbase, - uint32_t long_ptbase) -{ - uint64_t map_pa, map_va, entry, offset; - uint32_t pagesize, map_pagesize; - - uint64_t maplen = 0; - - /* - * If passed VA is not page aligned, make it so - * and add the offset to the length we need to map, - * so a map of va 0x3100, len 0x1000 becomes a map - * of va 0x3000, len 0x1100. - */ - if (!(AMD64_PAGEALIGNED(va, AMD64_PAGESIZE))) { - len += va & AMD64_PAGEOFFSET(AMD64_PAGESIZE); - va &= AMD64_PAGEMASK(AMD64_PAGESIZE); - } - - while (len) { - uint64_t check_pa, entry_64; - - entry = amd64_legacy_lookup((uint64_t)(va), &map_pagesize, - legacy_ptbase); - - if (entry_64 = amd64_long_lookup((uint64_t)(va), &pagesize, - long_ptbase)) { - /* - * We can skip the next map_pagesize bytes since - * they've already been mapped. - */ - -#ifdef DEBUG - if ((amd64_physaddr(entry_64, AMD64_MODE_LONG64)) != - (amd64_physaddr((uint64_t)entry, - AMD64_MODE_LEGACY))) { - printf("WARNING: 64-bit va 0x%llx already " - "mapped, pa 0x%llx, len 0x%x!\n", - (uint64_t)va, amd64_physaddr(entry_64, - AMD64_MODE_LONG64), - pagesize); - printf(" Will not remap address to pa " - "0x%llx as requested.\n", - amd64_physaddr((uint64_t)entry, - AMD64_MODE_LEGACY)); - } -#endif /* DEBUG */ -#ifdef lint - entry_64 = entry_64; -#endif /* lint */ - map_pagesize = pagesize; - entry = 0; - } - - pagesize = (map_pagesize > len) ? AMD64_PAGESIZE : map_pagesize; - - if (entry) { - /* - * Valid page mapping for va found, so either add - * it to the current page range or map what we have - * and start a new range. - */ - check_pa = amd64_legacy_physaddr(entry); - - if ((map_pagesize == AMD64_PAGESIZE4M) && - (!(AMD64_PAGEALIGNED(va, map_pagesize)))) { - offset = va & AMD64_PAGEMASK(map_pagesize); - check_pa += offset; - pagesize = AMD64_PAGESIZE; - } - - if (!maplen) { - map_va = (uint64_t)(va); - - map_pa = check_pa; - maplen = pagesize; - - if (!(AMD64_PAGEALIGNED(va, pagesize))) { - offset = va & - AMD64_PAGEOFFSET(pagesize); - map_pa += offset; - maplen -= offset; - } - } else { - if (check_pa != (map_pa + maplen)) { - /* - * Range of mapped entries ends, - * so map what we've got and start - * a new range. - */ - amd64_map_mem(map_va, map_pa, - maplen, AMD64_MODE_LONG64, - long_ptbase, - amd64_modbits((uint64_t)entry)); - - /* - * Use current mapping as start of - * new range. - */ - map_va = (uint64_t)(va); - map_pa = check_pa; - maplen = pagesize; - - if (!(AMD64_PAGEALIGNED(va, - pagesize))) { - offset = va & - AMD64_PAGEOFFSET(pagesize); - map_pa += offset; - maplen -= offset; - } - } else { - /* - * Just increment mapping range - * by mapped pagesize. - */ - maplen += pagesize; - } - } - } else if (maplen) { - /* - * Found a bad map entry, so end the mapping range and - * translate the address range we have. - */ - amd64_map_mem(map_va, map_pa, maplen, AMD64_MODE_LONG64, - long_ptbase, amd64_modbits((uint64_t)entry)); - - maplen = 0; - } - - va += pagesize; - len -= (pagesize > len) ? len : pagesize; - } - - /* - * If we ended with an outstanding range left to map, be sure to map it - * now. - */ - if (maplen) - amd64_map_mem(map_va, map_pa, maplen, AMD64_MODE_LONG64, - long_ptbase, amd64_modbits((uint64_t)entry)); -} - -void -amd64_xlate_long_va(uint64_t va, uint32_t len, uint32_t long_ptbase, - uint32_t legacy_ptbase) -{ - uint32_t map_pagesize, pagesize; - uint64_t map_pa, map_va, entry, offset; - uint64_t maplen = 0; - - /* - * If passed VA is not page aligned, make it so - * and add the offset to the length we need to map, - * so a map of va 0x3100, len 0x1000 becomes a map - * of va 0x3000, len 0x1100. - */ - if (!(AMD64_PAGEALIGNED(va, AMD64_PAGESIZE))) { - len += va & AMD64_PAGEOFFSET(AMD64_PAGESIZE); - va &= AMD64_PAGEMASK(AMD64_PAGESIZE); - } - - while (len) { - uint64_t check_pa; - uint32_t entry_32; - - entry = amd64_long_lookup(va, &map_pagesize, long_ptbase); - - if (entry_32 = amd64_legacy_lookup((uint32_t)ADDR_TRUNC(va), - &pagesize, legacy_ptbase)) { - /* - * We can skip the next map_pagesize bytes since - * they've already been mapped. - */ -#ifdef DEBUG - if ((amd64_physaddr((uint64_t)entry_32, - AMD64_MODE_LEGACY)) != (amd64_physaddr(entry, - AMD64_MODE_LONG64))) { - printf("WARNING: 32-bit va 0x%llx already " - "mapped, pa 0x%llx, len 0x%x!\n", - (uint64_t)va, amd64_physaddr(entry_32, - AMD64_MODE_LEGACY), pagesize); - printf(" Will not remap address to " - "pa 0x%llx as requested.\n", - amd64_physaddr(entry, AMD64_MODE_LONG64)); - } - -#endif /* DEBUG */ -#ifdef lint - entry_32 = entry_32; -#endif /* lint */ - map_pagesize = pagesize; - entry = 0; - } - - pagesize = (map_pagesize > len) ? AMD64_PAGESIZE - : map_pagesize; - - if (entry) { - /* - * Valid page mapping for va found, so either add - * it to the current page range or map what we have - * and start a new range. - */ - check_pa = amd64_long_physaddr(entry); - - if ((map_pagesize == AMD64_PAGESIZE2M) && - (!(AMD64_PAGEALIGNED(va, map_pagesize)))) { - offset = va & AMD64_PAGEMASK(map_pagesize); - check_pa += offset; - pagesize = AMD64_PAGESIZE; - } - - if (!maplen) { - map_va = va; - map_pa = check_pa; - maplen = pagesize; - - if (!(AMD64_PAGEALIGNED(va, pagesize))) { - offset = va & - AMD64_PAGEOFFSET(pagesize); - - map_pa += offset; - maplen -= offset; - } - } else { - if (check_pa != (map_pa + maplen)) { - /* - * Range of mapped entries ends, - * so map what we've got and start - * a new range. - */ - amd64_map_mem(map_va, map_pa, maplen, - AMD64_MODE_LEGACY, legacy_ptbase, - amd64_modbits(entry)); - - /* - * Use current mapping as start of - * new range. - */ - map_va = va; - map_pa = check_pa; - maplen = pagesize; - - if (!(AMD64_PAGEALIGNED(va, - pagesize))) { - offset = va & - AMD64_PAGEOFFSET(pagesize); - map_pa += offset; - maplen -= offset; - } - } else { - /* - * Just increment mapping range - * by mapped pagesize. - */ - maplen += pagesize; - } - } - } else if (maplen) { - /* - * Found a bad map entry, so end the mapping range and - * translate the address range we have. - */ - amd64_map_mem(map_va, map_pa, maplen, AMD64_MODE_LEGACY, - legacy_ptbase, amd64_modbits(entry)); - maplen = 0; - } - - va += pagesize; - len -= (pagesize > len) ? len : pagesize; - } - - /* - * If we ended with an outstanding range left to map, be sure to map it - * now. - */ - if (maplen) - amd64_map_mem(map_va, map_pa, maplen, AMD64_MODE_LEGACY, - legacy_ptbase, amd64_modbits(entry)); -} - -void -amd64_xlate_boot_tables(uint32_t boot_ptbase, uint32_t long_ptbase) -{ - extern uint_t magic_phys; - - /* - * The initial 64-bit page tables are setup with 0x200000:0x600000 - * already identity mapped, so we can skip that range. - */ - - /* - * Copy first 2M of boot's pages but SKIP PAGE ZERO. - */ - amd64_xlate_legacy_va(0x1000ULL, 0x1ff000, boot_ptbase, long_ptbase); - - /* - * Now copy balance of boot's pages. - * - * The initial 64-bit page tables are setup with 0x200000:0x400000 - * already identity mapped, so we can skip that range... - */ - amd64_xlate_legacy_va((magic_phys / 0x200000) * 0x200000, - 0xffc00000, boot_ptbase, long_ptbase); -} diff --git a/usr/src/psm/stand/boot/amd64/segments.c b/usr/src/psm/stand/boot/amd64/segments.c deleted file mode 100644 index f384110045..0000000000 --- a/usr/src/psm/stand/boot/amd64/segments.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Copyright (c) 1992 Terrence R. Lambert. - * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. - * 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: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by 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 - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - */ - -#include <sys/types.h> - -#include <amd64/boothooks.h> -#include <amd64/types.h> -#include <amd64/debug.h> -#include <amd64/tss.h> -#include <amd64/segments.h> - -/* - * Routines for loading segment descriptors in a format the hardware - * understands. - */ - -/* - * Install user segment descriptor for code and data. - */ -void -set_usegd(user_desc_t *dp, void *base, size_t size, uint_t type, - uint_t dpl, uint_t gran, uint_t defopsz) -{ - bzero(dp, sizeof (*dp)); - - dp->usd_lolimit = size; - dp->usd_hilimit = (uintptr_t)size >> 16; - - dp->usd_lobase = (uintptr_t)base; - dp->usd_midbase = (uintptr_t)base >> 16; - dp->usd_hibase = (uintptr_t)base >> (16 + 8); - - dp->usd_type = type; - dp->usd_dpl = dpl; - dp->usd_p = 1; - dp->usd_def32 = defopsz; /* 0 = 16, 1 = 32 bit operands */ - dp->usd_gran = gran; /* 0 = bytes, 1 = pages */ -} - -/* - * In long mode we have the new L or long mode attribute bit - * for code segments. Only the conforming bit in type is used along - * with descriptor priority and present bits. Default operand size must - * be zero when in long mode. In 32-bit compatibility mode all fields - * are treated as in legacy mode. For data segments while in long mode - * only the present bit is loaded. - */ -void -set_usegd64(user_desc64_t *dp, uint_t lmode, void *base, size_t size, - uint_t type, uint_t dpl, uint_t gran, uint_t defopsz) -{ - bzero(dp, sizeof (*dp)); - - ASSERT(lmode == 0 || lmode == 1); - - /* - * 64-bit long mode. - */ - if (lmode == LONG) { - dp->usd_type = type; - dp->usd_dpl = dpl; - dp->usd_p = 1; - dp->usd_long = 1; /* 64-bit mode */ - dp->usd_def32 = 0; /* must be zero for 32-bit operands */ - dp->usd_gran = gran; /* 0 = bytes, 1 = pages */ - } else { - - /* - * 32-bit compatibility mode. - */ - dp->usd_lolimit = size; - dp->usd_hilimit = (uintptr_t)size >> 16; - - dp->usd_lobase = (uintptr_t)base; - dp->usd_midbase = (uintptr_t)base >> 16; - dp->usd_hibase = (uintptr_t)base >> (16 + 8); - - dp->usd_type = type; - dp->usd_dpl = dpl; - dp->usd_p = 1; - dp->usd_long = 0; /* 32-bit mode */ - dp->usd_def32 = defopsz; /* 0 = 16, 1 = 32-bit ops */ - dp->usd_gran = gran; /* 0 = bytes, 1 = pages */ - } -} - -/* - * Install system segment descriptor for LDT and TSS segments. - */ -void -set_syssegd(system_desc_t *dp, void *base, size_t size, uint_t type, - uint_t dpl) -{ - bzero(dp, sizeof (*dp)); - - dp->ssd_lolimit = size; - dp->ssd_hilimit = (uintptr_t)size >> 16; - - dp->ssd_lobase = (uintptr_t)base; - dp->ssd_midbase = (uintptr_t)base >> 16; - dp->ssd_hibase = (uintptr_t)base >> (16 + 8); - - dp->ssd_type = type; - dp->ssd_zero = 0; /* must be zero */ - dp->ssd_dpl = dpl; - dp->ssd_p = 1; - - /* - * XXX why would anyone care to use page units for - * ldt or tss sizes? Force it to be bytes. - */ - dp->ssd_gran = 0; -} - -void -set_syssegd64(system_desc64_t *dp, void *base, size_t size, uint_t type, - uint_t dpl) -{ - bzero(dp, sizeof (*dp)); - - dp->ssd_lolimit = size; - dp->ssd_hilimit = (uintptr_t)size >> 16; - - dp->ssd_lobase = (uint32_t)base; - dp->ssd_midbase = (uint64_t)(uint32_t)base >> 16; - dp->ssd_hibase = (uint64_t)(uint32_t)base >> (16 + 8); - dp->ssd_hi64base = (uint64_t)(uint32_t)base >> (16 + 8 + 8); - - dp->ssd_type = type; - dp->ssd_zero1 = 0; /* must be zero */ - dp->ssd_zero2 = 0; - dp->ssd_dpl = dpl; - dp->ssd_p = 1; - dp->ssd_gran = 0; /* force byte units */ -} - -/* - * Install gate segment descriptor for interrupt, trap, call and task gates. - */ -void -set_gatesegd(gate_desc_t *dp, void (*func)(void), selector_t sel, - uint_t wcount, uint_t type, uint_t dpl) -{ - bzero(dp, sizeof (*dp)); - - dp->sgd_looffset = (uintptr_t)func; - dp->sgd_hioffset = (uintptr_t)func >> 16; - - dp->sgd_selector = (uint16_t)sel; - dp->sgd_stkcpy = wcount; - dp->sgd_type = type; - dp->sgd_dpl = dpl; - dp->sgd_p = 1; -} - -/* - * Note stkcpy is replaced with ist. Read the PRM for details on this. - */ -void -set_gatesegd64(gate_desc64_t *dp, void (*func)(void), selector_t sel, - uint_t ist, uint_t type, uint_t dpl) -{ - bzero(dp, sizeof (*dp)); - - dp->sgd_looffset = (uint64_t)(uint32_t)func; - dp->sgd_hioffset = (uint64_t)(uint32_t)func >> 16; - dp->sgd_hi64offset = (uint64_t)(uint32_t)func >> (16 + 16); - - dp->sgd_selector = (uint16_t)sel; - dp->sgd_ist = ist; - dp->sgd_type = type; - dp->sgd_dpl = dpl; - dp->sgd_p = 1; -} diff --git a/usr/src/psm/stand/boot/amd64/vtrap.c b/usr/src/psm/stand/boot/amd64/vtrap.c deleted file mode 100644 index 95c4ee32a4..0000000000 --- a/usr/src/psm/stand/boot/amd64/vtrap.c +++ /dev/null @@ -1,1148 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Contains the set of routines that implement the bootops and bsyscall - * vectors for a 64-bit client program. - */ - -#include <sys/types.h> -#include <sys/controlregs.h> -#include <sys/trap.h> -#include <sys/bootsvcs.h> - -#include <amd64/print.h> -#include <amd64/bootops64.h> -#include <amd64/bootsvcs64.h> -#include <amd64/machregs.h> -#include <amd64/alloc.h> -#include <amd64/amd64_page.h> -#include <amd64/cpu.h> -#include <amd64/debug.h> -#include <amd64/amd64.h> - -uint_t bop64_trace = -#if defined(DEBUG) - /* AMD64_TRACE_BOP_VM | XX64 - also too chatty */ - /* AMD64_TRACE_BOP_PROP | XX64 - also too chatty */ - /* AMD64_TRACE_BOP_BIOS | XX64 - final vestiges of chattyness */ -#endif - 0; - -static struct bsys_mem64 *amd64_update_ml64(struct bootops *); - -/* - * Memory page set aside for translation of boot's memory lists into - * "struct memlist64" format - */ -struct memlist64 *amd64_memlistpage; - -static void -return_int(struct amd64_machregs *rp, int rval) -{ - rp->r_rax = (int64_t)rval; -} - -static void -return_paddr(struct amd64_machregs *rp, void *rval) -{ - rp->r_rax = (caddr64_t)(uint32_t)rval; -} - -static void -return_addr(struct amd64_machregs *rp, void *rval) -{ - rp->r_rax = (caddr64_t)ADDR_XTND(rval); -} - -static const char * -trap_type_name(uint_t type) -{ - switch (type) { - case T_ZERODIV: return ("Divide error (#de)"); - case T_SGLSTP: return ("Debug (#db)"); - case T_NMIFLT: return ("NMI interrupt"); - case T_BPTFLT: return ("Breakpoint (#bp)"); - case T_OVFLW: return ("Overflow (#of)"); - case T_BOUNDFLT: return ("BOUND range exceeded (#br)"); - case T_ILLINST: return ("Invalid opcode (#ud)"); - case T_NOEXTFLT: return ("Device not available (#nm)"); - case T_DBLFLT: return ("Double fault (#df)"); - case T_EXTOVRFLT: return ("(i386 only reserved trap (9))"); - case T_TSSFLT: return ("Invalid TSS (#ts)"); - case T_SEGFLT: return ("Segment not present (#np)"); - case T_STKFLT: return ("Stack segment fault (#ss)"); - case T_GPFLT: return ("General protection (#gp)"); - case T_PGFLT: return ("Page fault (#pf)"); - case 15: return ("Intel reserved trap (15)"); - case T_EXTERRFLT: return ("x87 floating point error (#mf)"); - case T_ALIGNMENT: return ("Alignment check (#ac)"); - case T_MCE: return ("Machine check (#mc)"); - case T_SIMDFPE: return ("SIMD floating point exception (#xf)"); - default: - /* - * see r_trapno for type. Sorry but amd64 - * does not support sprtintf(). - */ - return ("reserved, external or soft int"); - } -} - -/* - * (When we need to get more ambitious with this, we - * can climb the long-mode stack to see how we got here..) - */ -/*PRINTFLIKE2*/ -static void -traceback64(struct amd64_machregs *rp, const char *fmt, ...) -{ - va_list ap; - - printf("%%rip: entry 0x%16" PRIx64 " return 0x%16" PRIx64 "\n", - rp->r_trapno, rp->r_rip); - printf("%%rsp: 0x%16" PRIx64 "\n", rp->r_rsp); - - va_start(ap, fmt); - amd64_vpanic(fmt, ap); - va_end(ap); -} - -/* - * We took a real exception thru amd64's IDT. - * Dump state and reset machine. - */ -static void -idt_exception(struct amd64_machregs *rp) -{ - printf("AMD64_BAD_TRAP: %s error=0x%llx\n\n", - trap_type_name(rp->r_trapno), rp->r_err); - - amd64_dump_amd64_machregs(rp); - printf("resetting ..."); - amd64_system_reset(); - /*NOTREACHED*/ -} - -extern uintptr_t bsys64_first, bsys64_last, bop64_first, bop64_last; -extern struct boot_syscalls *entry_boot_syscalls; - -#ifdef DEBUG -static void -amd64_assert_addr(caddr_t addr, int64_t arg_64, char *caller_name, char *type) -{ - if ((int64_t)ADDR_XTND(addr) != arg_64) - amd64_panic("%s(): unexpected address for %s\n" - " (expected 0x%llx, passed 0x%llx)\n", caller_name, - type, (int64_t)ADDR_XTND(addr), arg_64); -} - -static int -amd64_check_mapped_32(uint64_t addr, char *caller_name, char *type) -{ - if (!(amd64_legacy_lookup((uint64_t)(uintptr_t)addr, (uint32_t *)0, - amd64_get_cr3()))) { - printf("ERROR: %s(): called with unmapped 32-bit %s @ " - "0x%llx\n failing operation...\n", caller_name, type, - addr); - return (0); - } - - return (1); -} - -static int -amd64_check_arg(caddr_t addr, int64_t arg_64, char *caller_name, char *type) -{ - amd64_assert_addr(addr, arg_64, caller_name, type); - return (amd64_check_mapped_32((uint64_t)(uintptr_t)addr, caller_name, - type)); -} -#endif /* DEBUG */ - -static void -amd64_invoke_bootop( - struct amd64_machregs *rp, - struct bootops64 *bop64, - struct bootops *bop) -{ - extern uint64_t amd64_boot_pml4; - - fnaddr64_t this = (fnaddr64_t)rp->r_rip; - enum tracetype { - TRACE_NONE_RETURN, - TRACE_INT_RETURN, - TRACE_ADDR_RETURN, - TRACE_VOID_RETURN - } trace = TRACE_NONE_RETURN; - - if (this == bop64->bsys_alloc) { - - caddr_t vahint = ADDR_TRUNC(_ARG2(rp)); - size_t size = (size_t)_ARG3(rp); - int align = (int)_ARG4(rp); - void *retval; - - if (rp->r_cr3 != amd64_boot_pml4) - amd64_panic("bop64_alloc() called with wrong 64-bit " - "page table start address\n (caller's cr3: " - "0x%llx, should be: 0x%llx)\n", rp->r_cr3, - amd64_boot_pml4); - - if (bop64_trace & AMD64_TRACE_BOP_VM) { - printf("+alloc(vahint 0x%p/0x%" PRIx64 - " size %lu/%" PRIu64 " align %d) ", - (void *)vahint, _ARG2(rp), - size, _ARG3(rp), align); - trace = TRACE_ADDR_RETURN; - } - -#ifdef DEBUG - amd64_assert_addr(vahint, _ARG2(rp), "BOP_ALLOC", "vahint"); -#endif /* DEBUG */ - - retval = BOP_ALLOC(bop, vahint, size, align); - - if (retval != 0) - amd64_xlate_legacy_va((uint32_t)retval, size, - amd64_get_cr3(), amd64_boot_pml4); - - return_addr(rp, retval); - - } else if (this == bop64->bsys_free) { - - caddr_t va = ADDR_TRUNC(_ARG2(rp)); - size_t size = (size_t)_ARG3(rp); - - if (rp->r_cr3 != amd64_boot_pml4) - amd64_panic("bop64_free() called with wrong 64-bit " - "page table start address\n (caller's cr3: " - "0x%llx, should be: 0x%llx)\n", rp->r_cr3, - amd64_boot_pml4); - - if (bop64_trace & AMD64_TRACE_BOP_VM) { - printf("+free(va 0x%p/0x%" PRIx64 - " size %lu/%" PRIu64 ") ", - (void *)va, _ARG2(rp), size, _ARG3(rp)); - trace = TRACE_VOID_RETURN; - } - -#ifdef DEBUG - amd64_assert_addr(va, _ARG2(rp), "BOP_FREE", "va"); -#endif /* DEBUG */ - - BOP_FREE(bop, va, size); - - } else if (this == bop64->bsys_getproplen) { - - /* - * The property routines are mostly pass-through, but - * we take steps to hide our existence, so that the - * 64-bit kernel really does think it's talking to - * a native booter - * - * XX64 The "real" version of 'whoami' handling should be - * done in boot -- if that booter is asked to boot an - * EM_AMD64 file, it should know to put stretch into - * memory, then tell stretch and the kernel to boot - * that program, then we wouldn't need to fib here, - * because boot would be fibbing for us. - */ - - char *name = ADDR_TRUNC(_ARG2(rp)); - - if (bop64_trace & AMD64_TRACE_BOP_PROP) { - printf("+getproplen(name 0x%p/0x%" PRIx64 - " '%s') ", (void *)name, _ARG2(rp), name); - trace = TRACE_INT_RETURN; - } - -#ifdef DEBUG - if (!amd64_check_arg((caddr_t)name, _ARG2(rp), "BOP_GETPROPLEN", - "property name")) { - return_int(rp, 0); - return; - } -#endif /* DEBUG */ - - if (strcmp(name, "mmu-modlist") == 0) { - return_int(rp, strlen(amd64_getmmulist()) + 1); - } else - return_int(rp, BOP_GETPROPLEN(bop, name)); - - } else if (this == bop64->bsys_getprop) { - - char *name = ADDR_TRUNC(_ARG2(rp)); - caddr_t value = ADDR_TRUNC(_ARG3(rp)); - - if (bop64_trace & AMD64_TRACE_BOP_PROP) { - printf("+getprop(name 0x%p/0x%" PRIx64 - " '%s' value 0x%p/0x%" PRIx64 " ", - (void *)name, _ARG2(rp), name, (void *)value, - _ARG3(rp)); - } - -#ifdef DEBUG - if (!amd64_check_arg((caddr_t)name, _ARG2(rp), "BOP_GETPROP", - "property name")) { - return_int(rp, -1); - return; - } - - /* - * amd64_check_arg() can't be used here because krtld - * does a bop_getprop("whoami") with a buffer that is in stack - * space allocated just above AMD64 in memory, typically on the - * page mapped at 0x100f000), so just check to make sure the - * destination buffer is mapped in a way we can access. - */ - if (!amd64_check_mapped_32((uint64_t)(uintptr_t)value, - "BOP_GETPROP", "property value buffer")) { - return_int(rp, -1); - return; - } -#endif /* DEBUG */ - - if (strcmp(name, "memory-update") == 0) { - int retval; - - retval = BOP_GETPROP(bop, name, value); - (void) amd64_update_ml64(bop); - return_int(rp, retval); - } else if (strcmp(name, "mmu-modlist") == 0) { - (void) strcpy(value, amd64_getmmulist()); - return_int(rp, 0); - } else - return_int(rp, BOP_GETPROP(bop, name, value)); - - if (bop64_trace & AMD64_TRACE_BOP_PROP) { - static const char *string_props[] = { - "backfs-fstype", - "backfs-path", - "bootargs", - "bootpath", - "boot-path", - "boot-message", - "default-name", - "extent", - "frontfs-fstype", - "frontfs-path", - "fstype", - "impl-arch-name", - "mfg-name", - "whoami", - 0 - }; - const char * const *sp; - - printf(" = %" PRId64, rp->r_rax); - - /* - * (Sigh. This is a rather tawdry hack so that - * we can print out various "well-known" string - * properties as strings.) - */ - for (sp = string_props; *sp; sp++) - if (strcmp(*sp, name) == 0) { - printf(" [= '%s']", value); - break; - } - - printf("\n"); - } - - } else if (this == bop64->bsys_nextprop) { - - char *prevprop = ADDR_TRUNC(_ARG2(rp)); - - if (bop64_trace & AMD64_TRACE_BOP_PROP) { - printf("+nextprop(prevprop 0x%p/0x%" PRIx64 - "/'%s') ", (void *)prevprop, _ARG2(rp), prevprop); - trace = TRACE_ADDR_RETURN; - } - -#ifdef DEBUG - if (!amd64_check_arg((caddr_t)prevprop, _ARG2(rp), - "BOP_NEXTPROP", "previous property")) { - return_addr(rp, 0); - return; - } -#endif /* DEBUG */ - - return_addr(rp, BOP_NEXTPROP(bop, prevprop)); - - } else if (this == bop64->bsys_printf) { - - char lnbuf[128]; - char *fmt = ADDR_TRUNC(_ARG2(rp)); - int lnlen; - -#if 0 /* correct code */ - ASSERT((uint16_t)rp->r_rax <= 8); /* no SSE regs! */ -#else /* XX64 */ - /* - * Technically an ABI violation, gcc 3.2.3 currently - * only does a "mov $0, al" before calling printf, with - * the result that we tripped over this assert due to garbage - * in the upper 8 bytes of what would be ax. - */ - ASSERT((uint8_t)rp->r_rax <= 8); /* no SSE regs! */ -#endif - -#ifdef DEBUG - if (!amd64_check_mapped_32((uint64_t)(uintptr_t)fmt, - "BOP_PRINTF", "fmt string")) - return; -#endif /* DEBUG */ - - lnlen = amd64_snprintf64(lnbuf, sizeof (lnbuf), fmt, - _ARG3(rp), _ARG4(rp), _ARG5(rp), _ARG6(rp)); - - printf("%s%s", lnbuf, - (lnlen > sizeof (lnbuf)) ? " [truncated]\n" : ""); - - } else if (this == bop64->bsys_doint) { - - int intnum = (int)_ARG2(rp); - struct bop_regs *regs = ADDR_TRUNC(_ARG3(rp)); - - /* - * (Looks like the -kernel- only does this for pci_check() - */ - - if (bop64_trace & AMD64_TRACE_BOP_BIOS) { - printf("+doint(intnum %d " - "regs 0x%p/0x%" PRIx64 ") ", - intnum, (void *)regs, _ARG3(rp)); - trace = TRACE_VOID_RETURN; - } - -#ifdef DEBUG - if (!amd64_check_arg((caddr_t)regs, _ARG3(rp), "BOP_DOINT", - "regs")) - return; -#endif /* DEBUG */ - - BOP_DOINT(bop, intnum, regs); - - } else if (this == bop64->bsys_ealloc) { - - caddr_t vahint = ADDR_TRUNC(_ARG2(rp)); - size_t size = (size_t)_ARG3(rp); - int align = (int)_ARG4(rp); - int flags = (int)_ARG5(rp); - void *retval; - - if (rp->r_cr3 != amd64_boot_pml4) - amd64_panic("bop64_ealloc() called with wrong 64-bit " - "page table start address\n (caller's cr3: " - "0x%llx, should be: 0x%llx)\n", rp->r_cr3, - amd64_boot_pml4); - - if (bop64_trace & AMD64_TRACE_BOP_VM) { - printf("+ealloc(vahint 0x%p/0x%" PRIx64 - " size %lu/%" PRIu64 " align %d flags 0x%x) ", - (void *)vahint, _ARG2(rp), size, _ARG3(rp), align, - flags); - trace = TRACE_ADDR_RETURN; - } - -#ifdef DEBUG - if (vahint) - amd64_assert_addr(vahint, _ARG2(rp), "BOP_EALLOC", - "vahint"); -#endif /* DEBUG */ - - retval = BOP_EALLOC(bop, vahint, size, align, flags); - - /* - * Don't attempt to create 64-bit mappings for purely physical - * memory reservations or for failed allocations, - */ - if (flags & BOPF_X86_ALLOC_PHYS) - return_paddr(rp, retval); - else { - if (retval != 0) - amd64_xlate_legacy_va((uint32_t)retval, size, - amd64_get_cr3(), amd64_boot_pml4); - - return_addr(rp, retval); - } - } else - traceback64(rp, "BOP_xxx (@ 0x%" PRIx64 ") unimp", this); - - switch (trace) { - case TRACE_NONE_RETURN: - break; - case TRACE_INT_RETURN: - printf(" = %" PRId64 "\n", rp->r_rax); - break; - case TRACE_ADDR_RETURN: - printf(" = 0x%p/0x%" PRIx64 "\n", - ADDR_TRUNC(rp->r_rax), rp->r_rax); - break; - case TRACE_VOID_RETURN: - printf(" = (void)\n"); - break; - } -} - -static struct bsys_mem64 * -amd64_update_ml64(struct bootops *bop) -{ - extern struct memlist64 *amd64_convert_memlist(struct memlist *, - struct memlist64 *); - - static struct bsys_mem64 __memlist64, *bop_ml64 = &__memlist64; - - struct memlist64 *ml64 = amd64_memlistpage; - - /* - * amd64_convert_memlist() returns a pointer to the entry one past the - * previous translated list, suitable for the start of the next new - * memlist64, so the assignments below may seem a bit non-intuitive - * at first... - */ - bop_ml64->physinstalled = UINT64_FROMPTR32(ml64); - ml64 = amd64_convert_memlist(bop->boot_mem->physinstalled, ml64); - - bop_ml64->physavail = UINT64_FROMPTR32(ml64); - ml64 = amd64_convert_memlist(bop->boot_mem->physavail, ml64); - - bop_ml64->pcimem = UINT64_FROMPTR32(ml64); - ml64 = amd64_convert_memlist(bop->boot_mem->pcimem, ml64); - return (bop_ml64); -} - -static struct bootops *saved_bootops; - -/* - * This is the 64-bit bootops vector that we hand to the 64-bit standalone - */ -struct bootops64 * -init_bootops64(struct bootops *bop) -{ - static struct bootops64 __bootops64, *bop64 = &__bootops64; - -#define SET_BOP64(bop, opname) \ - { \ - extern uintptr_t bop64_##opname; \ - (bop)->bsys_##opname = \ - (fnaddr64_t)(uintptr_t)&bop64_##opname; \ - } - - /* move to main.c or to startup */ - - ASSERT(bop->bsys_version >= BO_VERSION); - - amd64_memlistpage = (struct memlist64 *) - amd64_zalloc_identity(2 * AMD64_PAGESIZE); - - saved_bootops = bop; - bop64->bsys_version = BO_VERSION; - bop64->boot_mem = (caddr64_t)(uintptr_t)amd64_update_ml64(bop); - - SET_BOP64(bop64, alloc) - SET_BOP64(bop64, free) - SET_BOP64(bop64, getproplen) - SET_BOP64(bop64, getprop) - SET_BOP64(bop64, nextprop) - SET_BOP64(bop64, printf) - SET_BOP64(bop64, doint) - SET_BOP64(bop64, ealloc) - -#undef SET_BOP64 - - return (bop64); -} - -static void -amd64_invoke_boot_syscall( - struct amd64_machregs *rp, - struct boot_syscalls *bsys, - struct boot_syscalls64 *bsys64) -{ - fnaddr64_t this = (fnaddr64_t)rp->r_rip; - - if (this == bsys64->getchar) { - rp->r_rax = BSVC_GETCHAR(bsys); - } else if (this == bsys64->putchar) { - BSVC_PUTCHAR(bsys, (uchar_t)rp->r_rdi); - } else if (this == bsys64->ischar) { - rp->r_rax = BSVC_ISCHAR(bsys); - } else - traceback64(rp, "bsys_xxx (type 0x%" PRIx64 ") unimp", this); -} - -static struct boot_syscalls64 __boot_syscalls64; /* XXX - global scope */ -static struct boot_syscalls *saved_boot_syscallp; - -/* - * Return the 64-bit bsyscall vector that we hand to the 64-bit standalone - */ -struct boot_syscalls64 * -init_boot_syscalls64(struct boot_syscalls *bsys) -{ - struct boot_syscalls64 *bsys64 = &__boot_syscalls64; - - /* - * This variable is awful; the 'bsys' pointer should be - * the first argument to every bsys handler .. but in the - * meantime, this'll do. - */ - saved_boot_syscallp = bsys; - - bzero(bsys64, sizeof (*bsys64)); - -#define SET_BSYS64(bsys, opname) \ - { \ - extern uintptr_t bsys64_##opname; \ - (bsys)->opname = \ - (fnaddr64_t)(uintptr_t)&bsys64_##opname; \ - } - - SET_BSYS64(bsys64, getchar) - SET_BSYS64(bsys64, putchar) - SET_BSYS64(bsys64, ischar) - -#undef SET_BSYS64 - - return (bsys64); -} - -static void dump_desctbr(const char *, desctbr_t *); -static void dump_desctbr64(const char *, desctbr64_t *); - -/* - * After stashing machine state we must convert the tss gdt entry from - * busy to available type. - */ -/*ARGSUSED*/ -void -amd64_i386_clrtss(struct i386_machregs *rp) -{ -#if 0 - system_desc_t *ssd; - - if (rp->r_tr != 0) { - ASSERT(SELTOIDX(rp->r_tr) < SELTOIDX(rp->r_gdt.dtr_limit)); - ASSERT((rp->r_tr & CPL_MASK) == 0); - ssd = (system_desc_t *)(rp->r_gdt.dtr_base + rp->r_tr); - - ASSERT(ssd->ssd_type == SDT_SYSTSSBSY); - ssd->ssd_type = SDT_SYSTSS; - ASSERT(rp->r_gdt.dtr_limit != 0); - } -#endif -} - -static void -amd64_clrtss(struct amd64_machregs *rp) -{ - system_desc64_t *ssd; - - if (rp->r_tr != 0) { - - ASSERT(SELTOIDX(rp->r_tr) < SELTOIDX(rp->r_gdt.dtr_limit)); - ASSERT((rp->r_tr & CPL_MASK) == 0); - ssd = (system_desc64_t *)(uintptr_t) - (rp->r_gdt.dtr_base + rp->r_tr); - - ssd->ssd_type = SDT_SYSTSS; - ASSERT(rp->r_gdt.dtr_limit != 0); - } -} - -void -amd64_vtrap(struct amd64_machregs *rp) -{ - uintptr_t addr = (uintptr_t)rp->r_rip; - - /* - * __vtrap_common always sets r_trapno to -1 - */ - if (rp->r_trapno == -1) { - if ((addr - (uintptr_t)&bsys64_first) <= - ((uintptr_t)&bsys64_last - (uintptr_t)&bsys64_first)) { - amd64_invoke_boot_syscall(rp, - saved_boot_syscallp, &__boot_syscalls64); - } else if ((addr - (uintptr_t)&bop64_first) <= - ((uintptr_t)&bop64_last - (uintptr_t)&bop64_first)) { - struct bootops64 *bop64 = ADDR_TRUNC(_ARG1(rp)); - amd64_invoke_bootop(rp, bop64, saved_bootops); - } - } else { - /* - * we took a real exception. - */ - idt_exception(rp); - } - - amd64_clrtss(rp); -} - -static const char * -desc_type_name(uint_t type) -{ - switch (type) { - case SDT_SYSNULL: - case SDT_SYSNULL2: - case SDT_SYSNULL3: - case SDT_SYSNULL4: return ("illegal"); - case SDT_SYS286TSS: return ("16-bit tss"); - case SDT_SYSLDT: return ("ldt"); - case SDT_SYS286BSY: return ("16-bit tss busy"); - case SDT_SYS286CGT: return ("16-bit call gate"); - case SDT_SYSTASKGT: return ("task gate"); - case SDT_SYS286IGT: return ("16-bit intr gate"); - case SDT_SYS286TGT: return ("16-bit trap gate"); - case SDT_SYSTSS: return ("32-bit tss"); - case SDT_SYSTSSBSY: return ("32-bit tss busy"); - case SDT_SYSCGT: return ("32-bit call gate"); - case SDT_SYSIGT: return ("32-bit intr gate"); - case SDT_SYSTGT: return ("32-bit trap gate"); - - case SDT_MEMRO: return ("r-- --"); - case SDT_MEMROA: return ("r-- -a"); - case SDT_MEMRW: return ("rw- --"); - case SDT_MEMRWA: return ("rw- -a"); - case SDT_MEMROD: return ("r-- d-"); - case SDT_MEMRODA: return ("r-- da"); - case SDT_MEMRWD: return ("rw- d-"); - case SDT_MEMRWDA: return ("rw- da"); - case SDT_MEME: return ("--x --"); - case SDT_MEMEA: return ("--x -a"); - case SDT_MEMER: return ("r-x --"); - case SDT_MEMERA: return ("r-x -a"); - case SDT_MEMEC: return ("--x c-"); - case SDT_MEMEAC: return ("--x ca"); - case SDT_MEMERC: return ("r-x c-"); - case SDT_MEMERAC: return ("r-x ca"); - default: return ("(unknown)"); - } -} - -static size_t -dump_ssd(void *desc) -{ - uint_t type = ((struct user_segment_descriptor *)desc)->usd_type; - - printf("type %2d (%s) ", type, desc_type_name(type)); - - switch (type) { - - case SDT_SYSTASKGT: { - struct gate_segment_descriptor *sgd = desc; - - printf("tss sel 0x%x dpl %d %spresent\n", - sgd->sgd_selector, sgd->sgd_dpl, - sgd->sgd_p ? "" : "NOT "); - return (sizeof (*sgd)); - } - - case SDT_SYSLDT: - case SDT_SYSTSS: - case SDT_SYSTSSBSY: { - struct system_segment_descriptor *ssd = desc; - uint32_t base = ssd->ssd_lobase | - (ssd->ssd_midbase << 16) | (ssd->ssd_hibase << 24); - uint32_t lim = ssd->ssd_lolimit | - (ssd->ssd_hilimit << 16); - - printf("base 0x%x lim 0x%x dpl %d %spresent\n", - base, ssd->ssd_gran ? lim * 4096 : lim, - ssd->ssd_dpl, ssd->ssd_p ? "" : "NOT "); - return (sizeof (*ssd)); - } - - case SDT_SYSCGT: - case SDT_SYSIGT: - case SDT_SYSTGT: { - struct gate_segment_descriptor *sgd = desc; - - printf("target 0x%x:0x%x dpl %d %spresent", - sgd->sgd_selector, sgd->sgd_looffset | - (sgd->sgd_hioffset << 16), - sgd->sgd_dpl, sgd->sgd_p ? "" : "NOT "); - if (type == SDT_SYSCGT) - printf(" %d parms", sgd->sgd_stkcpy); - printf("\n"); - return (sizeof (*sgd)); - } - - case SDT_MEMRO: - case SDT_MEMROA: - case SDT_MEMRW: - case SDT_MEMRWA: - case SDT_MEMROD: - case SDT_MEMRODA: - case SDT_MEMRWD: - case SDT_MEMRWDA: - case SDT_MEME: - case SDT_MEMEA: - case SDT_MEMER: - case SDT_MEMERA: - case SDT_MEMEC: - case SDT_MEMEAC: - case SDT_MEMERC: - case SDT_MEMERAC: { - struct user_segment_descriptor *usd = desc; - uint32_t base = usd->usd_lobase | - (usd->usd_midbase << 16) | (usd->usd_hibase << 24); - uint32_t lim = usd->usd_lolimit | - (usd->usd_hilimit << 16); - - printf("base 0x%x lim 0x%x dpl %d %spresent\n", - base, usd->usd_gran ? lim * 4096 : lim, - usd->usd_dpl, usd->usd_p ? "" : "NOT "); - return (sizeof (*usd)); - } - - default: { - uint16_t *u16 = desc; - struct system_segment_descriptor *ssd = desc; - - printf("0x%x.%x.%x.%x dpl %d %spresent\n", - u16[0], u16[1], u16[2], u16[3], - ssd->ssd_dpl, ssd->ssd_p ? "" : "NOT "); - return (sizeof (*ssd)); - } - - } -} - -static void -dump_desctbr(const char *name, desctbr_t *dtr) -{ - uintptr_t entry, theend; - - printf(" %s [limit %x base %x]\n", - name, dtr->dtr_limit, dtr->dtr_base); - - theend = (uintptr_t)(dtr->dtr_base + dtr->dtr_limit); - - for (entry = dtr->dtr_base; entry < theend; ) { - printf(" %6lu: ", entry - (uintptr_t)dtr->dtr_base); - entry += dump_ssd((void *)entry); - /* - * Hack to print only the hardware entries in the idt - */ - if (entry - (uintptr_t)dtr->dtr_base > 19 && - strcmp(name, "idt") == 0) - return; - } -} - -static void -dump_user_descriptor(desctbr_t *gdt, const char *name, uint16_t sel) -{ - uint_t index; - static const char fmt1[] = " %8s %16x\n "; - - printf(fmt1, name, sel); - - if ((index = SELTOIDX(sel)) == 0) - printf("<null selector>\n"); - else if (index > gdt->dtr_limit) - printf("<selector out of range?>\n"); - else { - uintptr_t entry = - (uintptr_t)gdt->dtr_base + IDXTOSEL(index); - - (void) dump_ssd((void *)entry); - } -} - -void -amd64_dump_i386_machregs(struct i386_machregs *rp) -{ - static const char fmt1[] = " %8s %16x\n"; - static const char fmt2[] = " %8s %16x %8s %16x\n"; - static const char fmtb[] = " %8s %16b\n"; - - printf("struct i386_machregs @0x%p = {\n", (void *)rp); - -#if defined(__GNUC__) - printf(fmt1, "cr0", rp->r_cr0); - printf(fmt1, "cr2", rp->r_cr2); - printf(fmt1, "cr3", rp->r_cr3); - printf(fmt1, "cr4", rp->r_cr4); -#else - printf(fmtb, "cr0", rp->r_cr0, FMT_CR0); - printf(fmt1, "cr2", rp->r_cr2); - printf(fmtb, "cr3", rp->r_cr3, FMT_CR3); - printf(fmtb, "cr4", rp->r_cr4, FMT_CR4); -#endif - dump_desctbr("gdt", &rp->r_gdt); - dump_desctbr("idt", &rp->r_idt); - - dump_user_descriptor(&rp->r_gdt, "ldt", rp->r_ldt); - dump_user_descriptor(&rp->r_gdt, "tr", rp->r_tr); - - printf(fmt2, "edi", rp->r_edi, "esi", rp->r_esi); - printf(fmt2, "ebp", rp->r_ebp, "esp", rp->r_esp); - printf(fmt2, "ebx", rp->r_ebx, "ecx", rp->r_ecx); - - printf(fmt2, "eip", rp->r_eip, "efl", rp->r_efl); - printf(fmt1, "uesp", rp->r_uesp); - - dump_user_descriptor(&rp->r_gdt, "cs", (uint16_t)rp->r_cs); - dump_user_descriptor(&rp->r_gdt, "ds", (uint16_t)rp->r_ds); - dump_user_descriptor(&rp->r_gdt, "es", (uint16_t)rp->r_es); - dump_user_descriptor(&rp->r_gdt, "fs", (uint16_t)rp->r_fs); - dump_user_descriptor(&rp->r_gdt, "gs", (uint16_t)rp->r_gs); - dump_user_descriptor(&rp->r_gdt, "ss", (uint16_t)rp->r_ss); - - printf(fmt2, "trapno", rp->r_trapno, "err", rp->r_err); - - printf("}\n"); -} - -static const char * -desc64_type_name(uint_t type) -{ - switch (type) { - case SDT_SYSNULL: - case SDT_SYS286TSS: - case SDT_SYS286BSY: - case SDT_SYS286CGT: - case SDT_SYSTASKGT: - case SDT_SYS286IGT: - case SDT_SYS286TGT: - case SDT_SYSNULL2: - case SDT_SYSNULL3: - case SDT_SYSNULL4: return ("illegal"); - - case SDT_SYSLDT: return ("64-bit ldt"); - case SDT_SYSTSS: return ("64-bit tss"); - case SDT_SYSTSSBSY: return ("64-bit tss busy"); - case SDT_SYSCGT: return ("64-bit call gate"); - case SDT_SYSIGT: return ("64-bit intr gate"); - case SDT_SYSTGT: return ("64-bit trap gate"); - - case SDT_MEMRO: return ("r-- --"); - case SDT_MEMROA: return ("r-- -a"); - case SDT_MEMRW: return ("rw- --"); - case SDT_MEMRWA: return ("rw- -a"); - case SDT_MEMROD: return ("r-- d-"); - case SDT_MEMRODA: return ("r-- da"); - case SDT_MEMRWD: return ("rw- d-"); - case SDT_MEMRWDA: return ("rw- da"); - case SDT_MEME: return ("--x --"); - case SDT_MEMEA: return ("--x -a"); - case SDT_MEMER: return ("r-x --"); - case SDT_MEMERA: return ("r-x -a"); - case SDT_MEMEC: return ("--x c-"); - case SDT_MEMEAC: return ("--x ca"); - case SDT_MEMERC: return ("r-x c-"); - case SDT_MEMERAC: return ("r-x ca"); - default: return ("(unknown)"); - } -} - -static size_t -dump_ssd64(void *desc) -{ - uint_t type = ((struct user_segment_descriptor64 *)desc)->usd_type; - - printf("type %d (%s) ", type, desc64_type_name(type)); - - switch (type) { - case SDT_SYSLDT: - case SDT_SYSTSS: - case SDT_SYSTSSBSY: { - struct system_segment_descriptor64 *ssd = desc; - uint64_t base = (uint64_t)ssd->ssd_lobase | - ((uint64_t)ssd->ssd_midbase << 16) | - ((uint64_t)ssd->ssd_hibase << 24) | - ((uint64_t)ssd->ssd_hi64base << 32); - uint32_t lim = ssd->ssd_lolimit | - (ssd->ssd_hilimit << 16); - - printf("base 0x%" PRIx64 - " lim 0x%x dpl %d %spresent\n", - base, ssd->ssd_gran ? lim * 4096 : lim, - ssd->ssd_dpl, ssd->ssd_p ? "" : "NOT "); - - if (ssd->ssd_zero1 != 0 || ssd->ssd_zero2) - amd64_warning("zero1 field 0x%x zero2 field " - "0x%x", ssd->ssd_zero1, ssd->ssd_zero2); - return (sizeof (*ssd)); - } - - case SDT_SYSCGT: - case SDT_SYSIGT: - case SDT_SYSTGT: { - struct gate_segment_descriptor64 *sgd = desc; - - printf("target 0x%x:0x%" PRIx64 " dpl %d " - "%spresent\n", sgd->sgd_selector, - (uint64_t)sgd->sgd_looffset | - ((uint64_t)sgd->sgd_hioffset) << 16 | - ((uint64_t)sgd->sgd_hi64offset), - sgd->sgd_dpl, sgd->sgd_p ? "" : "NOT "); - - if (type == SDT_SYSCGT && sgd->sgd_zero != 0) - amd64_warning("zero field 0x%x\n", - sgd->sgd_zero); - return (sizeof (*sgd)); - } - - case SDT_MEMRO: - case SDT_MEMROA: - case SDT_MEMRW: - case SDT_MEMRWA: - case SDT_MEMROD: - case SDT_MEMRODA: - case SDT_MEMRWD: - case SDT_MEMRWDA: { - struct user_segment_descriptor64 *usd = desc; - - printf("%spresent\n", usd->usd_p ? "" : "NOT "); - return (sizeof (*usd)); - } - - case SDT_MEME: - case SDT_MEMEA: - case SDT_MEMER: - case SDT_MEMERA: - case SDT_MEMEC: - case SDT_MEMEAC: - case SDT_MEMERC: - case SDT_MEMERAC: { - struct user_segment_descriptor64 *usd = desc; - - printf("%sconforming, dpl %d, %spresent, " - "long %d, defopsz %d\n", - BITX(usd->usd_type, 2, 2) ? "" : "non-", - usd->usd_dpl, - usd->usd_p ? "" : "NOT ", - usd->usd_long, usd->usd_def32); - if (usd->usd_long && usd->usd_def32) - amd64_warning("both the L and D bit are " - "set!\n"); - return (sizeof (*usd)); - } - - default: - printf("\n"); - return (sizeof (struct user_segment_descriptor64)); - } -} - -static void -dump_desctbr64(const char *name, desctbr64_t *dtr) -{ - uintptr_t entry, theend; - - printf(" %s [limit 0x%x base 0x%" PRIx64 "]\n", - name, dtr->dtr_limit, dtr->dtr_base); - - theend = (uintptr_t)(dtr->dtr_base + dtr->dtr_limit); - - for (entry = (uintptr_t)dtr->dtr_base; entry < theend; ) { - printf(" %6lu: ", entry - (uintptr_t)dtr->dtr_base); - entry += dump_ssd64((void *)entry); - - /* - * Hack to print only the hardware entries in the idt - */ - if (entry - (uintptr_t)dtr->dtr_base > 19 && - strcmp(name, "idt") == 0) - return; - } -} - -static void -dump_user_descriptor64(desctbr64_t *gdt, const char *name, uint16_t sel) -{ - uint_t index; - static const char fmt1[] = " %8s %16x\n "; - - printf(fmt1, name, sel); - - if ((index = SELTOIDX(sel)) == 0) - printf("<null selector>\n"); - else if (index > gdt->dtr_limit) - printf("<selector out of range?>\n"); - else { - uintptr_t entry = - (uintptr_t)gdt->dtr_base + IDXTOSEL(index); - - (void) dump_ssd((void *)entry); - } -} - -void -amd64_dump_amd64_machregs(struct amd64_machregs *rp) -{ - static const char fmt1[] = " %8s %16" PRIx64 "\n"; - static const char fmt2[] = " %8s %16" PRIx64 " %8s %16" PRIx64 "\n"; - static const char fmtb[] = " %8s %16b\n"; - - printf("struct amd64_machregs @0x%p = {\n", (void *)rp); - - printf(fmt1, "kgsbase", rp->r_kgsbase); - printf(fmt2, "gsbase", rp->r_gsbase, "fsbase", rp->r_fsbase); - - printf(fmt2, "cr0", rp->r_cr0, "cr2", rp->r_cr2); - printf(fmt2, "cr3", rp->r_cr3, "cr4", rp->r_cr4); - printf(fmt1, "cr8", rp->r_cr8); - -#if !defined(__GNUC__) - printf(fmtb, "cr0", (uint_t)rp->r_cr0, FMT_CR0); - printf(fmtb, "cr3", (uint_t)rp->r_cr3, FMT_CR3); - printf(fmtb, "cr4", (uint_t)rp->r_cr4, FMT_CR4); -#endif - - dump_desctbr64("gdt", &rp->r_gdt); - dump_desctbr64("idt", &rp->r_idt); - - dump_user_descriptor64(&rp->r_gdt, "ldt", (uint16_t)rp->r_ldt); - dump_user_descriptor64(&rp->r_gdt, "tr", (uint16_t)rp->r_tr); - - printf(fmt2, "rdi", rp->r_rdi, "rsi", rp->r_rsi); - printf(fmt2, "rdx", rp->r_rdx, "rcx", rp->r_rcx); - printf(fmt2, "r8", rp->r_r8, "r9", rp->r_r9); - printf(fmt2, "rax", rp->r_rax, "rbx", rp->r_rbx); - printf(fmt2, "rbp", rp->r_rbp, "r10", rp->r_r10); - printf(fmt2, "r11", rp->r_r11, "r12", rp->r_r12); - printf(fmt2, "r13", rp->r_r13, "r14", rp->r_r14); - printf(fmt2, "r15", rp->r_r15, "rsp", rp->r_rsp); - printf(fmt2, "rip", rp->r_rip, "rfl", rp->r_rfl); - - dump_user_descriptor64(&rp->r_gdt, "cs", (uint16_t)rp->r_cs); - dump_user_descriptor64(&rp->r_gdt, "ds", (uint16_t)rp->r_ds); - dump_user_descriptor64(&rp->r_gdt, "es", (uint16_t)rp->r_es); - dump_user_descriptor64(&rp->r_gdt, "fs", (uint16_t)rp->r_fs); - dump_user_descriptor64(&rp->r_gdt, "gs", (uint16_t)rp->r_gs); - dump_user_descriptor64(&rp->r_gdt, "ss", (uint16_t)rp->r_ss); - - printf(fmt2, "trapno", rp->r_trapno, "err", rp->r_err); - - printf("}\n"); -} diff --git a/usr/src/psm/stand/boot/i386/Makefile b/usr/src/psm/stand/boot/i386/Makefile deleted file mode 100644 index ad7f5d24a0..0000000000 --- a/usr/src/psm/stand/boot/i386/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../../../../Makefile.master - -# firmware libraries, platform-group, and platform-specific -# subdirectories to visit. - -SUBDIRS = i86pc - -all := TARGET = all -install := TARGET = install -clean := TARGET = clean -clobber := TARGET = clobber -lint := TARGET = lint - -all install clean clobber lint: $(SUBDIRS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET) - -# -# Cross-reference customization: include all boot-related source files. -# -XRDIRS += ../amd64 ../common - -cscope.out tags: FRC - $(XREF) -x $@ - -FRC: diff --git a/usr/src/psm/stand/boot/i386/Makefile.com b/usr/src/psm/stand/boot/i386/Makefile.com deleted file mode 100644 index 06e00ac095..0000000000 --- a/usr/src/psm/stand/boot/i386/Makefile.com +++ /dev/null @@ -1,215 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# psm/stand/boot/i386/Makefile.com - -include $(TOPDIR)/psm/stand/boot/Makefile.boot - -BOOTSRCDIR = ../.. - -TOP_CMN_DIR = $(SRC)/common -PROM_DIR = $(SRC)/uts/intel/promif -CMN_DIR = $(BOOTSRCDIR)/common -MACH_DIR = ../common -PLAT_DIR = . -PAMD64_DIR = $(BOOTSRCDIR)/amd64 -BOOT_DIR = $(SRC)/psm/stand/boot - -TOP_CMN_C_SRC = getoptstr.c string.c ufsops.c hsfs.c -TOP_CMN_C_SRC += memcpy.c memmove.c memset.c bcopy.c bzero.c -PROM_C_SRC = prom_printf.c prom_putchar.c prom_env.c -CMN_C_SRC = heap_kmem.c readfile.c - -PAMD64_C_SRC = alloc.c context.c cpu.c handoff.c memlist.c print.c -PAMD64_C_SRC += ptops.c ptxlate.c segments.c vtrap.c -PAMD64_S_SRC = i386_subr.s -PAMD64_SL_SRC = locore.s exception.s - -ASSYM_H = assym.h -GENASSYM = genassym -GENASSYM_FILES = $(ASSYM_H) $(GENASSYM) - -$(PAMD64_SL_SRC:%.s=%.o) := AS = $(amd64_AS) -$(PAMD64_SL_SRC:%.s=%.o) := ASFLAGS = -P $(CPPDEFS) -D_ASM $(CPPINCS) - -MACH_C_SRC = bios.c bootflags.c bootops.c bootprop.c -MACH_C_SRC += boot_plat.c boot_ramdisk.c console.c -MACH_C_SRC += keyboard.c keyboard_table.c memory.c -MACH_C_SRC += multiboot.c standalloc.c vga.c -MACH_C_SRC += bootenv.c vgaprobe.c check_iopath.c - -BIOS_C_SRC = biosutil.c - -C_SRC = $(TOP_CMN_C_SRC) $(CMN_C_SRC) $(MACH_C_SRC) $(ARCH_C_SRC) -C_SRC += $(PAMD64_C_SRC) $(PROM_C_SRC) -S_SRC = $(ARCH_S_SRC) $(PAMD64_S_SRC) $(PAMD64_SL_SRC) - -START_OBJS = $(START_S_SRC:%.s=%.o) -OBJS = $(C_SRC:%.c=%.o) $(S_SRC:%.s=%.o) -L_OBJS = $(OBJS:%.o=%.ln) - -# Note: the BIOS_S_SRC (biosint.s) must come first -BIOS_OBJS = $(BIOS_S_SRC:%.s=%.o) $(BIOS_C_SRC:%.c=%.o) - -ELFCONV = mkbin -BIOSINT = biosint -UNIBOOT = multiboot - -ROOT_PSM_BIOSINT = $(ROOT_PSM_DIR)/$(BIOSINT) -ROOT_PSM_UNIBOOT = $(ROOT_PSM_DIR)/$(UNIBOOT) - -.KEEP_STATE: - -.PARALLEL: $(OBJS) $(START_OBJS) $(L_OBJS) - -all: $(ELFCONV) $(UNIBOOT) $(BIOSINT) - -SYSDIR = $(TOPDIR)/uts - -CPPDEFS = $(ARCHOPTS) -D$(PLATFORM) -D_BOOT -D_KERNEL -D_MACHDEP -CPPINCS += -I$(TOP_CMN_DIR) -CPPINCS += -I. -I$(PAMD64_DIR) -CPPINCS += -I$(PSMSYSHDRDIR) -CPPINCS += -I$(ROOT)/usr/platform/$(PLATFORM)/include -CPPINCS += -I$(TOPDIR)/uts/intel -I$(TOPDIR)/uts/i86pc -CPPINCS += -I$(TOPDIR)/uts/common -CPPINCS += -I$(STANDDIR)/lib/sa -CPPINCS += -I$(STANDDIR) -CPPINCS += -I$(BOOT_DIR)/i386/common - -CPPFLAGS = $(CPPDEFS) $(CPPINCS) -CPPFLAGS += $(CCYFLAG)$(SYSDIR)/common -ASFLAGS = -P $(CPPDEFS) -D__STDC__ -D_BOOT -D_ASM $(CPPINCS) - -CFLAGS = ../common/i86.il $(COPTFLAG) - -# -# Force 16-bit alignment in multiboot -# -CFLAGS += -xcache=0/16/0:0/16/0 -# -# This should be globally enabled! -# -CFLAGS += $(CCVERBOSE) -# -# Inherit the debug format -# -CFLAGS += $(DEBUGFORMAT) - -YFLAGS = -d - -# -# Loader flags used to build biosint -# -BIOS_LOADMAP = bios_loadmap -BIOS_MAPFILE = $(MACH_DIR)/biosint.map -BIOS_LDFLAGS = -dn -m -M $(BIOS_MAPFILE) - -$(ELFCONV): $(MACH_DIR)/$$(@).c - $(NATIVECC) -O -o $@ $(MACH_DIR)/$@.c - -$(BIOSINT): $(ELFCONV) $(BIOS_MAPFILE) $(BIOS_OBJS) - $(LD) $(BIOS_OBJS) $(BIOS_LDFLAGS) -o $@.elf > $(BIOS_LOADMAP) - cp $@.elf $@.strip - $(STRIP) $@.strip - $(RM) $@; ./$(ELFCONV) $@.strip $@ - -# -# Loader flags used to build unified boot -# -UNI_LOADMAP = loadmap -UNI_MAPFILE = $(MACH_DIR)/mapfile -UNI_LDFLAGS = -dn -m -M $(UNI_MAPFILE) - -# -# Object files used to build unified boot -# Note: START_OBJS must come within first 8K to comply with Multiboot Spec -# -UNI_OBJS = $(START_OBJS) $(OBJS) -UNI_L_OBJS = $(UNI_OBJS:%.o=%.ln) - -$(UNIBOOT): $(UNI_MAPFILE) $(UNI_OBJS) - $(LD) $(UNI_LDFLAGS) -o $@ $(UNI_OBJS) > $(UNI_LOADMAP) - $(POST_PROCESS) - -$(UNIBOOT)_lint: $(UNI_L_OBJS) - $(LINT.c) $(UNI_L_OBJS) - -ROOT_BOOT_DIR = $(ROOT)/boot -ROOT_BOOT_SOL_DIR = $(ROOT_BOOT_DIR)/solaris - -$(ROOT_BOOT_DIR): $(ROOT) - -$(INS.dir.root.sys) - -$(ROOT_BOOT_SOL_DIR): $(ROOT_BOOT_DIR) - -$(INS.dir.root.sys) - -$(ROOT_BOOT_SOL_DIR)/%: % $(ROOT_BOOT_SOL_DIR) - $(INS.file) - -# -# AMD64 genassym fun -# -$(PAMD64_S_SRC:%.s=%.o) : $(GENASSYM_FILES) -$(PAMD64_SL_SRC:%.s=%.o) : $(GENASSYM_FILES) - -GENASSYM_SRC = $(PAMD64_DIR)/$(GENASSYM:%=%.c) -$(GENASSYM) := CFLAGS = -D__sun $(ENVCPPFLAGS1) $(ENVCPPFLAGS2) \ - $(ENVCPPFLAGS3) $(ENVCPPFLAGS4) - -$(GENASSYM): $(GENASSYM_SRC) - $(NATIVECC) $(CFLAGS) -o $@ $(GENASSYM_SRC) - -OFFSETS = $(PAMD64_DIR)/offsets.in -$(ASSYM_H) := CC = $(amd64_CC) -$(ASSYM_H) := CFLAGS = -g -xarch=amd64 -xc99=%none \ - -D__sun $(CPPFLAGS) -$(ASSYM_H) := CCYFLAG = -g -YI, - -$(ASSYM_H): $(OFFSETS) $(GENASSYM) - $(GENOFFSETS) -s $(CTFSTABS) -r $(CTFCONVERT) \ - $(CC) $(CFLAGS) $(GOFLAGS) <$(OFFSETS) >$@ - ./$(GENASSYM) >>$@ - -$(START_OBJS): $(ASSYM_H) - -include $(BOOTSRCDIR)/Makefile.rules - -clean: - $(RM) $(OBJS) $(BIOS_OBJS) - $(RM) $(L_OBJS) $(GENASSYM_FILES) - $(RM) $(BIOSINT).elf a.out core - -clobber: clean - $(RM) $(ELFCONV) $(UNIBOOT) $(UNI_LOADMAP) $(BIOSINT) $(BIOS_LOADMAP) - $(RM) $(UFSBOOT) $(NFSBOOT) - -include $(TOPDIR)/Makefile.psm.targ - -install: $(ROOT_PSM_UNIBOOT) $(ROOT_PSM_BIOSINT) - -lint: all $(UNIBOOT)_lint - -FRC: diff --git a/usr/src/psm/stand/boot/i386/common/bios.c b/usr/src/psm/stand/boot/i386/common/bios.c deleted file mode 100644 index e80d0ad55d..0000000000 --- a/usr/src/psm/stand/boot/i386/common/bios.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/controlregs.h> -#include <sys/bootconf.h> -#include <sys/bootvfs.h> -#include <sys/psw.h> -#include "biosint.h" -#include "machine.h" -#include "standalloc.h" -#include "console.h" -#include "util.h" -#include "debug.h" - -#define PCI_FUNCTION_ID 0xB1 -#define PCI_BIOS_PRESENT 0x1 -#define dprintf if (debug & D_BIOS) printf - -int bios_free; /* i.e. no BIOS */ - -extern int openfile(char *, char *); -int (*bios_doint)(int, struct int_pb *); - -static void -pci_check_bios(void) -{ - int ret; - struct int_pb ic = {0}; - - ic.ax = (PCI_FUNCTION_ID << 8) | PCI_BIOS_PRESENT; - ret = bios_doint(0x1a, &ic); - if (ret & PS_C) - printf("bios_doint failed: %d\r\n", ret); - dprintf("bios_doint returned: %d\r\n", ret); - dprintf("ic.ax = 0x%x\r\n", (int)ic.ax); - dprintf("ic.dx = 0x%x\r\n", (int)ic.dx); -} - -/* dummy bios routine when no BIOS is present */ -/*ARGSUSED*/ -static int -bios_doint_none(int a, struct int_pb *p) -{ - dprintf("bios_doint_none: fail 0x%x\n", a); - return (PS_C); -} - -void -init_biosprog() -{ - int fd; - char *buf = (char *)0x2000; - ssize_t count; - - if (bios_free) { - bios_doint = bios_doint_none; - return; - } - - /* read biosint program to pfn 2 */ - fd = openfile("biosint", NULL); - if (fd == -1) { - printf("cannot open biosint\n"); - return; - } - - count = read(fd, buf, PAGESIZE); - if (count <= 0) { - printf("cannot read biosint\n"); - return; - } - - bios_doint = (int (*)(int, struct int_pb *))(buf); - dprintf("biosint loaded at 0x%p: %ld bytes\r\n", (void *)buf, count); - if (debug & D_BIOS) /* run a check if debug */ - pci_check_bios(); - if (verbosemode) - printf("bios service program installed\n"); -} diff --git a/usr/src/psm/stand/boot/i386/common/biosint.h b/usr/src/psm/stand/boot/i386/common/biosint.h deleted file mode 100644 index 0372ed078a..0000000000 --- a/usr/src/psm/stand/boot/i386/common/biosint.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_BIOSINT_H -#define _SYS_BIOSINT_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -struct int_pb { - unsigned short ax, bx, cx, dx, bp, si, di, ds, es; -}; - -extern int (*bios_doint)(int, struct int_pb *); - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_BIOSINT_H */ diff --git a/usr/src/psm/stand/boot/i386/common/biosutil.c b/usr/src/psm/stand/boot/i386/common/biosutil.c deleted file mode 100644 index ad262ae4b4..0000000000 --- a/usr/src/psm/stand/boot/i386/common/biosutil.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * helper functions for switching to realmode and make a bios call. - * The only interesting functions are copyin_args and copyout_args. - * The rest are for debugging via a serial line. - */ - -#include "util.h" -#include "biosint.h" -#include "chario.h" -#include "serial.h" - -/* Forward declarations. */ -static void putchar(int c); -static void itoa(char *buf, int base, int d); - -void -copyin_args(int intnum, struct int_pb *ic) -{ - extern int ic_int; - extern uint16_t ic_ax, ic_bx, ic_cx, ic_dx; - extern uint16_t ic_bp, ic_si, ic_di, ic_ds, ic_es; - - ic_int = intnum; - ic_ax = ic->ax; - ic_bx = ic->bx; - ic_cx = ic->cx; - ic_dx = ic->dx; - ic_bp = ic->bp; - ic_si = ic->si; - ic_di = ic->di; - ic_ds = ic->ds; - ic_es = ic->es; -} - -void -copyout_args(struct int_pb *ic) -{ - extern uint16_t ic_ax, ic_bx, ic_cx, ic_dx; - extern uint16_t ic_bp, ic_si, ic_di, ic_ds, ic_es; - - ic->ax = ic_ax; - ic->bx = ic_bx; - ic->cx = ic_cx; - ic->dx = ic_dx; - ic->bp = ic_bp; - ic->si = ic_si; - ic->di = ic_di; - ic->ds = ic_ds; - ic->es = ic_es; -} - -/* - * Convert the integer D to a string and save the string in BUF. If - * BASE is equal to 'd', interpret that D is decimal, and if BASE is - * equal to 'x', interpret that D is hexadecimal. - */ -static void -itoa(char *buf, int base, int d) -{ - char *p = buf; - char *p1, *p2; - unsigned long ud = d; - int divisor = 10; - - /* If %d is specified and D is minus, put `-' in the head. */ - if (base == 'd' && d < 0) { - *p++ = '-'; - buf++; - ud = -d; - } else if (base == 'x') { - divisor = 16; - } - - /* Divide UD by DIVISOR until UD == 0. */ - do { - int remainder = ud % divisor; - - *p++ = (remainder < 10) ? - remainder + '0' : remainder + 'a' - 10; - } - - while (ud /= divisor) - ; - - /* Terminate BUF. */ - *p = 0; - - /* Reverse BUF. */ - p1 = buf; - p2 = p - 1; - while (p1 < p2) { - char tmp = *p1; - *p1 = *p2; - *p2 = tmp; - p1++; - p2--; - } -} - -/* - * Printn prints a number n in base b. - * We don't use recursion to avoid deep kernel stacks. - */ -/* XXX need to support 64-bit numbers */ -static void -_printn(uint_t n, int b, int width, int pad) -{ - char prbuf[40]; - char *cp; - - cp = prbuf; - do { - *cp++ = "0123456789abcdef"[n%b]; - n /= b; - width--; - } while (n); - while (width-- > 0) - *cp++ = (char)pad; - do { - putchar(*--cp); - } while (cp > prbuf); -} - -/* - * Format a string and print it on the screen, just like the libc - * function printf. - */ -void -vprintf(const char *fmt, va_list adx) -{ - int b, c, i, pad, width, ells; - char *s; - int64_t l; - uint64_t ul; - -loop: - width = 0; - while ((c = *fmt++) != '%') { - if (c == '\0') - return; - putchar(c); - } - - c = *fmt++; - - for (pad = ' '; c == '0'; c = *fmt++) - pad = '0'; - - for (width = 0; c >= '0' && c <= '9'; c = *fmt++) - width = (width * 10) + (c - '0'); - - for (ells = 0; c == 'l'; c = *fmt++) - ells++; - - switch (c) { - - case 'd': - case 'D': - b = 10; - if (ells == 0) - l = (int64_t)va_arg(adx, int); - else if (ells == 1) - l = (int64_t)va_arg(adx, long); - else - l = (int64_t)va_arg(adx, int64_t); - if (l < 0) { - putchar('-'); - width--; - putchar('-'); - width--; - ul = -l; - } else - ul = l; - goto number; - - case 'p': - ells = 1; - /* FALLTHROUGH */ - case 'x': - case 'X': - b = 16; - goto u_number; - - case 'u': - b = 10; - goto u_number; - - case 'o': - case 'O': - b = 8; -u_number: - if (ells == 0) - ul = (uint64_t)va_arg(adx, uint_t); - else if (ells == 1) - ul = (uint64_t)va_arg(adx, ulong_t); - else - ul = (uint64_t)va_arg(adx, uint64_t); -number: - _printn((uint_t)ul, b, width, pad); - break; - - case 'c': - b = va_arg(adx, int); - for (i = 24; i >= 0; i -= 8) - if ((c = ((b >> i) & 0x7f)) != 0) { - putchar(c); - } - break; - case 's': - s = va_arg(adx, char *); - while ((c = *s++) != 0) { - putchar(c); - } - break; - - case '%': - putchar('%'); - break; - } - goto loop; - -} - -/* - * Format a string and print it on the screen, just like the libc - * function printf. - */ -void -printf(const char *fmt, ...) -{ - va_list adx; - - va_start(adx, fmt); - vprintf(fmt, adx); - va_end(adx); -} - -/* serial port stuff */ -static int port = 0x3f8; - -static void -serial_putchar(int c) -{ - int checks = 10000; - - while (((inb(port + LSR) & XHRE) == 0) && checks--) - ; - outb(port + DAT, (char)c); -} - -static void -_doputchar(int c) -{ - serial_putchar(c); -} - -void -putchar(int c) -{ - static int bhcharpos = 0; - - if (c == '\t') { - do { - _doputchar(' '); - } while (++bhcharpos % 8); - return; - } else if (c == '\n') { - bhcharpos = 0; - _doputchar('\r'); - _doputchar(c); - return; - } else if (c == '\b') { - if (bhcharpos) - bhcharpos--; - _doputchar(c); - return; - } - - bhcharpos++; - _doputchar(c); -} - -void -print_long(int reg) -{ - printf("long = 0x%x\n", reg); -} - -void -print_word(ushort_t reg) -{ - printf("word = 0x%x\n", reg); -} - -void -print_regs() -{ - extern int call_esp, ic_int; - extern uint16_t call_cs, call_ss; - - printf("call_cs = %x, call_ss = %x\r\n", call_cs, call_ss); - printf("intnum = %x, esp = %x\r\n", ic_int, call_esp); -} diff --git a/usr/src/psm/stand/boot/i386/common/boot_plat.c b/usr/src/psm/stand/boot/i386/common/boot_plat.c deleted file mode 100644 index 3de61380da..0000000000 --- a/usr/src/psm/stand/boot/i386/common/boot_plat.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/param.h> -#include <sys/bootvfs.h> -#include <sys/varargs.h> -#include "console.h" -#include "util.h" -#include "bootprop.h" -#include "biosint.h" -#include "debug.h" - -char filename[MAXPATHLEN]; -char *impl_arch_name = "i86pc"; -int pagesize = 0x1000; - -extern void *memset(void *, int, size_t); - - -/* - * Open the given filename, expanding to its - * platform-dependent location if necessary. - */ -int -openfile(char *fname, char *kern) -{ - int fd; - - /* - * If the caller -specifies- an absolute pathname, then we just try to - * open it. - */ - if (*fname == '/') { - (void) strcpy(filename, fname); - return (open(fname, 0)); - } - - (void) strcpy(filename, "/platform/i86pc/"); - if (kern) - (void) strcat(filename, kern); - (void) strcat(filename, fname); - if ((fd = open(filename, 0)) != -1) - return (fd); - - /* try / */ - (void) strcpy(filename, "/"); - if (kern) - (void) strcat(filename, kern); - (void) strcat(filename, fname); - return (open(filename, 0)); -} - -/* - * Is path "/platform/"dir"/" ? - */ -static int -platcmp(char *path, char *dir) -{ - static char prefix[] = "/platform/"; - static char suffix[] = "/kernel"; - int len; - - if (strncmp(path, prefix, sizeof (prefix) - 1) != 0) - return (0); - len = strlen(dir); - path += sizeof (prefix) - 1; - if (strncmp(path, dir, len) != 0) - return (0); - path += len; - if (strcmp(path, suffix) != 0) - return (0); - return (1); -} - -void -mod_path_uname_m(char *mod_path, char *ia_name) -{ - /* - * If we found the kernel in the default "i86pc" dir, prepend the - * ia_name directory (e.g. /platform/SUNW,foo/kernel) to the mod_path - * unless ia_name is the same as the default dir. - * - * If we found the kernel in the ia_name dir, append the default - * directory to the modpath. - * - * If neither of the above are true, we were given a specific kernel - * to boot, so we leave things well enough alone. - */ - if (platcmp(mod_path, "i86pc")) { - if (strcmp(ia_name, "i86pc") != 0) { - char tmp[MAXPATHLEN]; - - (void) strcpy(tmp, mod_path); - (void) strcpy(tmp, mod_path); - (void) strcpy(mod_path, "/platform/"); - (void) strcat(mod_path, ia_name); - (void) strcat(mod_path, "/kernel "); - (void) strcat(mod_path, tmp); - } - } else if (platcmp(mod_path, ia_name)) - (void) strcat(mod_path, " /platform/i86pc/kernel"); -} - -void -setup_aux(void) -{ - extern char *mmulist; - static char mmubuf[16]; - int plen; - - if (((plen = bgetproplen(NULL, "mmu-modlist")) > 0) && (plen < 20)) - (void) bgetprop(NULL, "mmu-modlist", mmubuf); - else - (void) strcpy(mmubuf, "mmu32"); /* default to mmu32 */ - mmulist = mmubuf; -} - -/* Print panic string, then blow up! */ -/*PRINTFLIKE1*/ -void -panic(const char *fmt, ...) -{ - extern int efi_boot; - va_list adx; - - /* turn on output */ - verbosemode = 1; - printf("panic: "); - va_start(adx, fmt); - prom_vprintf(fmt, adx); - va_end(adx); - printf("Press any key to reboot\n"); - (void) getchar(); - printf("rebooting...\n"); - if (efi_boot) - efi_reset(); - reset(); -} - -void -prom_panic(char *str) -{ - panic(str); -} - -/* - * stubs for heap_kmem (assuming they're actually even needed there) - */ - -int -splimp() -{ - return (0); -} - -/*ARGSUSED*/ -void -splx(int rs) -{ -} - -int -splnet() -{ - return (0); -} - -static uint_t -gettime(void) -{ - /* - * Read system timer: - * - * Return milliseconds since last time counter was reset. - * The timer ticks 18.2 times per second or approximately - * 55 milliseconds per tick. - * - * The counter will be reset to zero by the bios after 24 hours - * or 1,573,040 ticks. The first read after a counter - * reset will flag this condition in the %al register. - * Unfortunately, it is hard to take advantage of this - * fact because some broken bioses will return bogus - * counter values if the counter is in the process of - * updating. We protect against this race by reading the - * counter until we get consecutive identical readings. - * By doing so, we lose the counter reset bit. To make this - * highly unlikely, we reset the counter to zero on the - * first call and assume 24 hours is enough time to get this - * machine booted. - * - * An attempt is made to provide a unique number on each - * call by adding 1 millisecond if the 55 millisecond counter - * hasn't changed. If this happens more than 54 times, we - * return the same value until the next real tick. - */ - static uint_t lasttime = 0; - static ushort_t fudge = 0; - uint_t ticks, mills, first, tries; - struct int_pb ic; - - if (lasttime == 0) { - /* - * initialize counter to zero so we don't have to - * worry about 24 hour wrap. - */ - (void) memset(&ic, 0, sizeof (ic)); - ic.ax = 0x0100; - (void) bios_doint(0x1a, &ic); - } - tries = 0; - do { - /* - * Loop until we trust the counter value. - */ - (void) memset(&ic, 0, sizeof (ic)); - (void) bios_doint(0x1a, &ic); - first = (ic.cx << 16) + (ic.dx & 0xFFFF); - (void) memset(&ic, 0, sizeof (ic)); - (void) bios_doint(0x1a, &ic); - ticks = (ic.cx << 16) + (ic.dx & 0xFFFF); - } while (first != ticks && ++tries < 10); - if (tries == 10) - printf("gettime: BAD BIOS TIMER\n"); - - mills = ticks*55; - if (mills > lasttime) { - fudge = 0; - } else { - fudge += (fudge < 54) ? 1 : 0; - } - mills += fudge; - lasttime = mills; - return (mills); -} - -void -mdelay(uint_t msec) -{ - uint_t time_now = gettime(); - uint_t time_end = time_now + msec; - - /* spin, we can't do anything else */ - while (gettime() < time_end) - ; -} diff --git a/usr/src/psm/stand/boot/i386/common/boot_ramdisk.c b/usr/src/psm/stand/boot/i386/common/boot_ramdisk.c deleted file mode 100644 index b380e3149c..0000000000 --- a/usr/src/psm/stand/boot/i386/common/boot_ramdisk.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/param.h> -#include <sys/bootconf.h> -#include <sys/bootvfs.h> -#include <sys/filep.h> -#include "util.h" -#include "debug.h" - -extern struct boot_fs_ops bufs_ops, bhsfs_ops; - -extern uint64_t ramdisk_start, ramdisk_end; -struct boot_fs_ops *bfs_ops; -struct boot_fs_ops *bfs_tab[] = {&bufs_ops, &bhsfs_ops, NULL}; - -/* - * This one reads the ramdisk. If fi_memp is set, we copy the - * ramdisk content to the designated buffer. Otherwise, we - * do a "cached" read (set fi_memp to the actual ramdisk buffer). - */ -int -diskread(fileid_t *filep) -{ - uint_t blocknum; - caddr_t diskloc; - - /* add in offset of root slice */ - blocknum = filep->fi_blocknum; - - diskloc = (caddr_t)(uintptr_t)(ramdisk_start + blocknum * DEV_BSIZE); - if (diskloc + filep->fi_count > (caddr_t)(uintptr_t)ramdisk_end) { - printf("diskread: reading beyond end of ramdisk\n"); - printf("\tstart = 0x%p, size = 0x%x\n", - (void *)diskloc, filep->fi_count); - return (-1); - } - - if (filep->fi_memp) { - bcopy(diskloc, filep->fi_memp, filep->fi_count); - } else { - /* "cached" read */ - filep->fi_memp = diskloc; - } - - return (0); -} - -int -mountroot(char *name) -{ - int i; - - if (verbosemode) - printf("mountroot on ramdisk: 0x%llx-%llx\n", - ramdisk_start, ramdisk_end); - /* try ops in bfs_tab and return the first successful one */ - for (i = 0; bfs_tab[i] != NULL; i++) { - bfs_ops = bfs_tab[i]; - if (BRD_MOUNTROOT(bfs_ops, name) == 0) - return (0); - } - return (-1); -} - -int -unmountroot() -{ - return (BRD_UNMOUNTROOT(bfs_ops)); -} - -int -open(const char *filename, int flags) -{ - return (BRD_OPEN(bfs_ops, (char *)filename, flags)); -} - -int -close(int fd) -{ - return (BRD_CLOSE(bfs_ops, fd)); -} - -ssize_t -read(int fd, void *buf, size_t size) -{ - return (BRD_READ(bfs_ops, fd, buf, size)); -} - -off_t -lseek(int fd, off_t addr, int whence) -{ - return (BRD_SEEK(bfs_ops, fd, addr, whence)); -} diff --git a/usr/src/psm/stand/boot/i386/common/bootenv.c b/usr/src/psm/stand/boot/i386/common/bootenv.c deleted file mode 100644 index 30eb186b93..0000000000 --- a/usr/src/psm/stand/boot/i386/common/bootenv.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/bootconf.h> -#include <sys/salib.h> -#include "util.h" -#include "debug.h" -#include "multiboot.h" -#include "bootprop.h" - - -#define BOOTENV_BUFSIZE 4096 -#define BOOTENV_LINESIZE 256 - -/* - * Note this path name must be consistent with that used - * in the ramdisk construction. - */ -static char *f_bootenv = "/boot/solaris/bootenv.rc"; - - -static void -get_bootenv_prop(char *line, int lineno) -{ - char *p; - int inq; - char *name; - char *val; - char **propp; - - /* - * Trim comments, respecting single quotes, then - * skip any blank lines and leading white space. - */ - inq = 0; - for (p = line; *p; p++) { - if (*p == '\'' || *p == '"') { - inq ^= 1; - } else if ((inq == 0 && *p == '#') || - *p == '\r' || *p == '\n') { - *p = 0; - break; - } - } - - while (*line == ' ' || *line == '\t') - line++; - if (strlen(line) == 0) - return; - - /* - * Anything remaining must be in a fixed format - */ - if ((name = strchr(line, ' ')) == NULL) - goto err; - *name++ = 0; - if (strcmp(line, "setprop") != 0) - goto err; - if ((val = strchr(name, ' ')) == NULL) - goto err; - *val++ = 0; - - p = val + strlen(val) - 1; - if (((*val == '\'' && *p == '\'') || - (*val == '"' && *p == '"')) && val != p) { - *p = 0; - val++; - } - - /* - * An empty name indicates a syntax error but - * an empty value should just be ignored. - */ - if (strlen(name) == 0) - goto err; - if (strlen(val) == 0) - return; - - if (debug & D_BPROP) - printf("%s(%d): %s %s\n", f_bootenv, lineno, name, val); - - (void) bsetprop(NULL, name, val, strlen(val) + 1); - - /* - * We respect certain eeprom(1M) properties internally - * if not overridden on the grub kernel cmdline. - * There should never be multiple definitions, but - * should that occur, the last one is the one that sticks. - */ - propp = NULL; - if (strcmp(name, "boot-file") == 0) - propp = &bootfile_prop; - else if (strcmp(name, "console") == 0) - propp = &console_prop; - else if (strcmp(name, "input-device") == 0) - propp = &inputdevice_prop; - else if (strcmp(name, "output-device") == 0) - propp = &outputdevice_prop; - - if (propp) { - if (*propp) - bkmem_free(*propp, strlen(*propp) + 1); - *propp = bkmem_zalloc(strlen(val)+1); - (void) strcpy(*propp, val); - } - - return; - -err: - printf("%s: syntax error on line %d\n", f_bootenv, lineno); -} - -void -get_bootenv_props() -{ - int fd; - char *line; - char *buf; - int n, bufcnt; - int c, linecnt; - char *bp, *lp; - int lineno = 1; - int err; - - fd = openfile(f_bootenv, 0); - if (fd == -1) { - printf("error opening %s\n", f_bootenv); - return; - } - - buf = bkmem_zalloc(BOOTENV_BUFSIZE); - line = bkmem_zalloc(BOOTENV_LINESIZE); - - lp = line; - *lp = 0; - bufcnt = 0; - linecnt = 0; - err = 0; - - for (;;) { - if (bufcnt == 0) { - n = read(fd, buf, BOOTENV_BUFSIZE); - if (n <= 0) - goto exit; - bufcnt = n; - bp = buf; - } - while (bufcnt > 0) { - if ((c = *bp++) == '\n') { - get_bootenv_prop(line, lineno++); - linecnt = 0; - lp = line; - err = 0; - } else if (linecnt < BOOTENV_LINESIZE-1) { - *lp++ = c; - linecnt++; - } else if (err == 0) { - printf("%s: line %d exceeds maximum (%d)\n", - f_bootenv, lineno, BOOTENV_LINESIZE); - err = 1; - } - bufcnt--; - *lp = 0; - } - } - -exit: - - bkmem_free(buf, BOOTENV_BUFSIZE); - bkmem_free(line, BOOTENV_LINESIZE); - - (void) close(fd); -} diff --git a/usr/src/psm/stand/boot/i386/common/bootflags.c b/usr/src/psm/stand/boot/i386/common/bootflags.c deleted file mode 100644 index 26bd0de1b8..0000000000 --- a/usr/src/psm/stand/boot/i386/common/bootflags.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Parse the boot arguments. - */ - -#include <sys/reboot.h> -#include <sys/promif.h> -#include <sys/boot.h> -#include <sys/salib.h> -#include <sys/param.h> -#include <util/getoptstr.h> -#include "bootprop.h" -#include "debug.h" - -int boothowto; -int verbosemode; -char *bootprog; -char *bootfile; -char bootargs[MAXNAMELEN]; -char bootprop[MAXPATHLEN]; -static char bootfile_buf[MAXNAMELEN]; -static char bootprog_buf[MAXNAMELEN]; -static int grub_line_present; - - -/* - * Parse the boot arguments and place results in bootprog, bootfile, - * bootargs, and bootprops. Note that anything unknown is treated as - * [kern-args] and is passed to kernel as is. - * - * The format for the GRUB args is: - * /boot/multiboot [bootfile [-D path]] [-Vadvk] - * [-B prop=value[,prop=value...]] [kern-args] - * - * The format for the eeprom boot-file is: - * [bootfile [-D path]] [-Vadvk] [kern-args] - * - * The grub line takes precedence - */ -static void -get_bootargs(char *args, int grub) -{ - struct gos_params params; - const char *cp, *SPC = " \t"; - char *np; - size_t npres; - int c; - - /* parse grub bootprog (multiboot) and -B */ - if (grub) { - char *dash_B = strstr(args, " -B"); - if (dash_B) { - /* copy -B arg to bootprop */ - cp = strtok(dash_B + 3, SPC); - (void) strncpy(bootprop, cp, MAXPATHLEN - 1); - bootprop[MAXPATHLEN - 1] = 0; - - /* move the end string forward */ - cp = strtok(NULL, ""); - if (cp) { - *dash_B++ = ' '; - while (*dash_B++ = *cp++) - ; - } else { - *dash_B = 0; - } - } - - /* get the multiboot prog (must be present) */ - bootprog = strtok(args, SPC); - (void) strlcpy(bootprog_buf, bootprog, sizeof (bootprog_buf)); - bootprog = bootprog_buf; - bootfile = strtok(NULL, SPC); - grub_line_present = (bootfile != NULL); - } else { - /* don't process bootfile_prop if grub line is present */ - if (grub_line_present) { - if (args && verbosemode) - printf("grub line specified, ignoring " - "boot-file setting %s in bootenv.rc\n", - args); - return; - } - bootfile = strtok(args, SPC); - } - - /* check for leading kmdb/kadb for compatibility */ - if (bootfile == NULL) - return; - - if (*bootfile == '-') { - args = bootfile; - /* XXX undo strtok, if have additional tokens */ - if (strtok(NULL, "")) - args[strlen(bootfile)] = ' '; - bootfile = NULL; - } else { - if (strcmp(bootfile, "kmdb") == 0 || - strcmp(bootfile, "kadb") == 0) { - bootfile = NULL; - boothowto |= RB_KMDB; - } else { - /* copy to buf to avoid being overwritten */ - (void) strlcpy(bootfile_buf, - bootfile, sizeof (bootfile_buf)); - bootfile = bootfile_buf; - } - /* get the remainder of string */ - args = strtok(NULL, ""); - if (args == NULL) - args = ""; - } - - params.gos_opts = "CD:ELVadvk"; - params.gos_strp = args; - getoptstr_init(¶ms); - while ((c = getoptstr(¶ms)) != -1) { - extern int bios_free, efi_boot; - extern void check_iopath(void); - - switch (c) { - case 'E': /* booted from EFI */ - efi_boot = 1; - /*FALLTHRU*/ - case 'L': /* linuxbios -- no bios */ - bios_free = 1; - break; - case 'V': /* Undocumented. */ - verbosemode = 1; - break; - case 'C': /* Undocumented for checking IO path */ - check_iopath(); - /* never returns here */ - break; - case 'D': - if (bootfile || (boothowto & RB_KMDB) == 0) { - printf("boot: -D invalid without kadb/kmdb. " - "Ignoring.\n"); - break; - } - if (params.gos_optarglen >= sizeof (bootfile_buf)) { - printf("boot: -D argument too long. " - "Ignoring.\n"); - break; - } - (void) strncpy(bootfile_buf, params.gos_optargp, - params.gos_optarglen); - bootfile_buf[params.gos_optarglen] = '\0'; - bootfile = bootfile_buf; - break; - - /* Consumed by the kernel */ - case 'a': /* Undocumented. */ - boothowto |= RB_ASKNAME; - break; - case 'd': - boothowto |= RB_DEBUGENTER; - break; - case 'v': - boothowto |= RB_VERBOSE; - break; - case 'k': - boothowto |= RB_KMDB; - break; - - case '?': - /* - * Error. Either an unrecognized option, or an option - * without an argument. Check for the latter. - */ - switch (params.gos_last_opt) { - case 'D': - printf("boot: -%c flag missing required " - "argument. Ignoring.\n", - params.gos_last_opt); - break; - default: - /* Unrecognized flag: stop. */ - goto done; - } - break; - - default: - printf("boot: Ignoring unimplemented option -%c.", c); - } - } -done: - - /* - * Construct the arguments for the standalone. - */ - *bootargs = '\0'; - np = bootargs; - - /* - * Start with '-' if we encountered an unrecognized option or if we - * need to pass flags to the standalone. - */ - if (c == '?' || (boothowto & - /* These flags are to be passed to the kernel. */ - (RB_ASKNAME | RB_DEBUGENTER | RB_VERBOSE | - RB_KMDB))) { - *np++ = '-'; - if (boothowto & RB_ASKNAME) - *np++ = 'a'; - if (boothowto & RB_DEBUGENTER) - *np++ = 'd'; - if (boothowto & RB_VERBOSE) - *np++ = 'v'; - if (boothowto & RB_KMDB) - *np++ = 'k'; - - /* - * If we didn't encounter an unrecognized flag and there's - * more to copy, add a space to separate these flags. - * (Otherwise, unrecognized flags can be appended since we - * started this word with a dash.) - */ - if (c == -1 && params.gos_strp[0] != '\0') - *np++ = ' '; - } - - npres = sizeof (bootargs) - (size_t)(np - bootargs); - - /* - * Unrecognized flag. gos_errp contains the remaining bootargs - */ - - if (c == '?') - cp = params.gos_errp; - else - cp = params.gos_strp; - - while (npres > 0 && (*np++ = *cp++) != '\0') - npres--; - *np = 0; - - if (verbosemode) { - printf("bootprog = %s\n", bootprog); - if (bootfile) - printf("bootfile = %s\n", bootfile); - printf("boot-args = %s\n", bootargs); - printf("bootprop = %s\n", bootprop); - } - - if (!grub) - (void) bsetprop(NULL, "boot-args", bootargs, - strlen(bootargs) + 1); -} - -void -get_grub_bootargs(char *args) -{ - /* grub args is always present */ - get_bootargs(args, 1); -} - -void -get_eeprom_bootargs(char *args) -{ - if (args) /* boot-file prop may not be present */ - get_bootargs(args, 0); -} diff --git a/usr/src/psm/stand/boot/i386/common/bootops.c b/usr/src/psm/stand/boot/i386/common/bootops.c deleted file mode 100644 index b7fe051099..0000000000 --- a/usr/src/psm/stand/boot/i386/common/bootops.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/param.h> -#include <sys/promif.h> -#include <sys/bootconf.h> -#include <sys/bootvfs.h> -#include <sys/varargs.h> -#include "standalloc.h" -#include "bootprop.h" -#include "util.h" -#include "biosint.h" -#include "debug.h" - -#define dprintf if (debug & D_BOP) printf - -extern struct memlist *pinstalledp, *pfreelistp, *vfreelistp, *pbooterp; -extern struct memlist *ppcimemp, *pramdiskp; -extern struct bootops *bop; - -/* Misc memlist stuff */ -extern void update_memlist(char *, char *, struct memlist **); - -/*ARGSUSED*/ -static caddr_t -bkern_alloc(struct bootops *bop, caddr_t virt, size_t size, int align) -{ - if (size < PAGESIZE) - return (bkmem_alloc(size)); - - return (resalloc(((virt == 0) ? RES_BOOTSCRATCH : RES_CHILDVIRT), - size, virt, align)); -} - -/*ARGSUSED*/ -static caddr_t -bkern_ealloc(struct bootops *bop, caddr_t virt, size_t size, int align, - int flags) -{ - uint_t delta; - - /* sanity check */ - if (size == 0) - return ((caddr_t)0); - - if (flags == BOPF_X86_ALLOC_IDMAP || - flags == BOPF_X86_ALLOC_PHYS) { - - /* align to PAGESIZE */ - delta = (uint_t)virt & (PAGESIZE - 1); - size += delta; - size = roundup(size, PAGESIZE); - - switch (flags) { - case BOPF_X86_ALLOC_IDMAP: - return ((caddr_t)idmap_mem( - (uint32_t)virt, size, align)); - /*NOTREACHED*/ - case BOPF_X86_ALLOC_PHYS: - return ((caddr_t)phys_alloc_mem(size, align)); - /*NOTREACHED*/ - } - } - - return (resalloc(((virt == 0) ? RES_BOOTSCRATCH : RES_CHILDVIRT), - size, virt, align)); -} - -/*ARGSUSED*/ -static void -bkern_free(struct bootops *bop, caddr_t virt, size_t size) -{ - resfree(virt, size); -} - -void -install_memlistptrs(void) -{ - /* allocate boot_mem structure */ - bop->boot_mem->physinstalled = pinstalledp; - bop->boot_mem->physavail = pfreelistp; - bop->boot_mem->pcimem = ppcimemp; - - dprintf("physinstalledp = 0x%p\n", - (void *)bop->boot_mem->physinstalled); - dprintf("pfreelistp = 0x%p\n", - (void *)bop->boot_mem->physavail); - dprintf("ppcimemp = 0x%p\n", - (void *)bop->boot_mem->pcimem); -} - -/*ARGSUSED*/ -static void -bkern_printf(struct bootops *bop, char *fmt, ...) -{ - va_list adx; - - va_start(adx, fmt); - prom_vprintf(fmt, adx); - va_end(adx); -} - -/* - * Translate register structure fit what /platform/i86pc/biosint expects. - */ -/*ARGSUSED*/ -static void -bkern_doint(struct bootops *bop, int intnum, struct bop_regs *rp) -{ - struct int_pb ic; - - ic.ax = rp->eax.word.ax; - ic.bx = rp->ebx.word.bx; - ic.cx = rp->ecx.word.cx; - ic.dx = rp->edx.word.dx; - ic.bp = rp->ebp.word.bp; - ic.si = rp->esi.word.si; - ic.di = rp->edi.word.di; - ic.ds = rp->ds; - ic.es = rp->es; - - if (debug & D_BIOS) - printf("bkern_doint: int = 0x%x, ax 0x%x, dx 0x%x\n", - intnum, ic.ax, ic.dx); - rp->eflags = bios_doint(intnum, &ic); - if (debug & D_BIOS) - printf("bios_doint ret = %d, ax 0x%x, dx 0x%x\n", - rp->eflags, ic.ax, ic.dx); - - rp->eax.word.ax = ic.ax; - rp->ebx.word.bx = ic.bx; - rp->ecx.word.cx = ic.cx; - rp->edx.word.dx = ic.dx; - rp->ebp.word.bp = ic.bp; - rp->esi.word.si = ic.si; - rp->edi.word.di = ic.di; - rp->ds = ic.ds; - rp->es = ic.es; -} - -bootops_t bootops = -{ - /* reduced bootops BO_VERSION == 11 ... */ - - BO_VERSION, /* "major" version number */ - 0, /* memlist pointers */ - bkern_alloc, /* G.P. memory allocator */ - bkern_free, /* G.P. memory release */ - bgetproplen, /* proplen */ - bgetprop, /* getprop */ - bnextprop, /* nextprop */ - bkern_printf, /* limited printf for kobj */ - bkern_doint, /* biosint */ - bkern_ealloc -}; - -void -setup_bootops(void) -{ - /* - * Initialize the bootops struct and establish a pointer to it ("bop") - * for use by standalone clients. - */ - bop = &bootops; - bop->boot_mem = bkmem_zalloc(sizeof (struct bsys_mem)); - install_memlistptrs(); - if (verbosemode) - printf("setup bootops\n"); -} diff --git a/usr/src/psm/stand/boot/i386/common/bootprop.c b/usr/src/psm/stand/boot/i386/common/bootprop.c deleted file mode 100644 index 466f27338b..0000000000 --- a/usr/src/psm/stand/boot/i386/common/bootprop.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/bootconf.h> -#include <sys/bootprops.h> -#include <sys/salib.h> -#include "debug.h" -#include "multiboot.h" - -int efi_boot; /* booted from EFI firmware */ -extern int bios_free; /* firmware is not bios */ - -extern void install_memlistptrs(); -#define dprintf if (debug & D_BPROP) printf - -struct pseudoprop { - char *pp_name; - void (*pp_func)(); -} pp_list[] = { - { "memory_update", install_memlistptrs }, - { NULL, NULL} -}; - -struct bootprop { - struct bootprop *bp_next; - char *bp_name; - void *bp_val; - int bp_len; -}; - -static struct bootprop *bp_list; - -static int find_pseudo(char *); -static struct bootprop *find_prop(char *); -static struct bootprop *alloc_prop(char *); -static void set_propval(struct bootprop *, void *, int); -static void setup_rarp_props(struct sol_netinfo *); - -/* - * Return the length of the "name"d property's value. - */ -/*ARGSUSED*/ -int -bgetproplen(struct bootops *bop, char *name) -{ - struct bootprop *bp; - - dprintf("bgetproplen: name = %s\n", name); - bp = find_prop(name); - return (bp ? bp->bp_len : BOOT_FAILURE); -} - -/*ARGSUSED*/ -int -bgetprop(struct bootops *bop, char *name, void *value) -{ - struct bootprop *bp; - - dprintf("bgetprop: name = %s\n", name); - if (find_pseudo(name) == BOOT_SUCCESS) - return (BOOT_SUCCESS); - - bp = find_prop(name); - if (!bp) - return (BOOT_FAILURE); - - /* Found the property in question; return its value */ - (void) bcopy(bp->bp_val, value, bp->bp_len); - return (BOOT_SUCCESS); -} - -/*ARGSUSED*/ -char * -bnextprop(struct bootops *bop, char *prev) -{ - struct bootprop *bp = find_prop(prev); - - if (bp == NULL || bp->bp_next == NULL) - return (NULL); - return (bp->bp_next->bp_name); -} - -/*ARGSUSED*/ -int -bsetprop(struct bootops *bop, char *name, void *value, int len) -{ - struct bootprop *bp; - - dprintf("bsetprop: name = %s, len = %d", name, len); - bp = find_prop(name); - if (bp == NULL) - bp = alloc_prop(name); - - set_propval(bp, value, len); - return (BOOT_SUCCESS); -} - -int -find_pseudo(char *name) -{ - struct pseudoprop *pp = pp_list; - - while (pp->pp_name) { - if (strcmp(name, pp->pp_name) == 0) { - (*pp->pp_func)(); - dprintf("find_pseudo: prop = %s\n", name); - return (BOOT_SUCCESS); - } - pp++; - } - return (BOOT_FAILURE); -} - -struct bootprop * -find_prop(char *name) -{ - struct bootprop *bp = bp_list; - - if (name == NULL || *name == '\0') - return (bp); - - while (bp) { - if (strcmp(name, bp->bp_name) == 0) - break; - bp = bp->bp_next; - } - return (bp); -} - -static struct bootprop * -alloc_prop(char *name) -{ - struct bootprop *bp = bkmem_zalloc(sizeof (*bp)); - - dprintf("alloc_prop: name = %s\n", name); - bp->bp_name = bkmem_alloc(strlen(name) + 1); - (void) strcpy(bp->bp_name, name); - bp->bp_next = bp_list; - bp_list = bp; - - return (bp); -} - -static void -set_propval(struct bootprop *bp, void *value, int len) -{ - dprintf("set_propval: name = %s\n", bp->bp_name); - - if (bp->bp_val) - bkmem_free(bp->bp_val, bp->bp_len); - bp->bp_len = len; - bp->bp_val = bkmem_alloc(len); - bcopy(value, bp->bp_val, len); -} - -void -setup_bootprop(void) -{ - extern char bootprop[], bootargs[]; - extern char *bootprog; - extern uint64_t ramdisk_start, ramdisk_end; - char *name, *val, *cp; - int stdout_val = 0; /* for a dummy property */ - - if (verbosemode) - printf("setup boot properties.\n"); - - dprintf("process command line bootargs: %s\n", bootprop); - cp = bootprop; - while (cp && *cp) { - name = strtok(cp, "="); - val = strtok(NULL, ""); - if (val == NULL) { - val = "true"; - cp = NULL; /* terminate loop */ - } else if (*val != '\'' && *val != '\"') { - if (*val == ',') { - cp = val + 1; - val = ""; - } else { - cp = strtok(val, ","); - cp = strtok(NULL, ""); - } - } else { - /* look for closing single or double quote */ - cp = val + 1; - while (cp && *cp != *val) - ++cp; - if (cp == NULL) { - printf("missing %c in property %s.\n", - *val, name); - } else { - *cp++ = '\0'; - if (*cp == ',') - cp++; - else if (*cp != '\0') { - printf("syntax error in GRUB -B option:" - " ignore %s\n", cp); - cp = NULL; /* terminate */ - } - } - val++; - } - - (void) bsetprop(NULL, name, val, strlen(val) + 1); - } - - (void) bsetprop(NULL, "bootprog", bootprog, strlen(bootprog) + 1); - (void) bsetprop(NULL, "boot-args", bootargs, strlen(bootargs) + 1); - (void) bsetprop(NULL, "ramdisk_start", (char *)&ramdisk_start, - sizeof (ramdisk_start)); - (void) bsetprop(NULL, "ramdisk_end", (char *)&ramdisk_end, - sizeof (ramdisk_end)); - - /* a bunch of fixed properties */ - (void) bsetprop(NULL, "mfg-name", "i86pc", sizeof ("i86pc")); - (void) bsetprop(NULL, "impl-arch-name", "i86pc", sizeof ("i86pc")); - - /* dummy properties needed by Install miniroot */ - (void) bsetprop(NULL, - "stdout", &stdout_val, sizeof (stdout_val)); -} - -void -setup_bootdev_props(void) -{ - extern multiboot_info_t *mbi; - int netboot = 0; - - if (verbosemode) - printf("setup boot device properties.\n"); - - /* If booted from EFI, setup acpi-root-tab and efi-systab */ - if (efi_boot) { - (void) bsetprop(NULL, "acpi-root-tab", - (char *)&mbi->acpi_root_tab, - sizeof (mbi->acpi_root_tab)); - (void) bsetprop(NULL, "efi-systab", (char *)&mbi->efi_systab, - sizeof (mbi->efi_systab)); - } - - if (bios_free) { - (void) bsetprop(NULL, "bios-free", "tree", sizeof ("true")); - return; - } - - /* figure out the boot device */ - if (MB_CHECK_FLAG(mbi->flags, 2)) { - char str[3]; - uint_t boot_device = (mbi->boot_device >> 24) & 0xff; - if (boot_device == MB_NETWORK_DRIVE) - netboot++; - (void) snprintf(str, 3, "%x", boot_device); - (void) bsetprop(NULL, "bios-boot-device", str, 3); - } else { /* assume netboot? */ - netboot++; - } - - /* - * In the netboot case, drives_info is overloaded with - * the dhcp ack. This is not multiboot compliant and - * requires special pxegrub! - */ - if (!netboot) - return; - - if (verbosemode) - printf("booting from network\n"); - - if (mbi->drives_length == 0) { - if (verbosemode) { - printf("no network info, " - "need a GRUB with Solaris enhancements\n"); - } - } else { - struct sol_netinfo *sip = - (struct sol_netinfo *)mbi->drives_addr; - switch (sip->sn_infotype) { - case SN_TYPE_BOOTP: - (void) bsetprop(NULL, BP_BOOTP_RESPONSE, - (void *)mbi->drives_addr, - mbi->drives_length); - break; - case SN_TYPE_RARP: - setup_rarp_props(sip); - break; - default: - printf("invalid network info: type %d\n", - sip->sn_infotype); - break; - }; - } -} - -#define BUFLEN 64 - -static void -setup_rarp_props(struct sol_netinfo *sip) -{ - char *buf = bkmem_alloc(BUFLEN); /* to hold ip/mac addrs */ - uint8_t *val; - - val = (uint8_t *)&sip->sn_ciaddr; - (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d", - val[0], val[1], val[2], val[3]); - (void) bsetprop(NULL, BP_HOST_IP, buf, strlen(buf) + 1); - - val = (uint8_t *)&sip->sn_siaddr; - (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d", - val[0], val[1], val[2], val[3]); - (void) bsetprop(NULL, BP_SERVER_IP, buf, strlen(buf) + 1); - - if (sip->sn_giaddr != 0) { - val = (uint8_t *)&sip->sn_giaddr; - (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d", - val[0], val[1], val[2], val[3]); - (void) bsetprop(NULL, BP_ROUTER_IP, buf, strlen(buf) + 1); - } - - if (sip->sn_netmask != 0) { - val = (uint8_t *)&sip->sn_netmask; - (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d", - val[0], val[1], val[2], val[3]); - (void) bsetprop(NULL, BP_SUBNET_MASK, buf, strlen(buf) + 1); - } - - if (sip->sn_mactype != 4 || sip->sn_maclen != 6) { - printf("unsupported mac type %d, mac len %d\n", - sip->sn_mactype, sip->sn_maclen); - return; - } - - val = sip->sn_macaddr; - (void) snprintf(buf, BUFLEN, "%x:%x:%x:%x:%x:%x", - val[0], val[1], val[2], val[3], val[4], val[5]); - (void) bsetprop(NULL, BP_BOOT_MAC, buf, strlen(buf) + 1); -} diff --git a/usr/src/psm/stand/boot/i386/common/chario.h b/usr/src/psm/stand/boot/i386/common/chario.h deleted file mode 100644 index 7023c17134..0000000000 --- a/usr/src/psm/stand/boot/i386/common/chario.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1995-1998, by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _CHARIO_H -#define _CHARIO_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * This file contains all character i/o related structures - * and defines. - * - * Project: Devconf - * Author : Rick McNeal - * Date : 2-Nov-1994 - */ -struct _char_io_ { - struct _char_io_ *next; /* next i/o member */ - char *name; /* Name for stats */ - int in, out, errs; /* Simple stats */ - int flags; /* control bits */ - int vals; /* state bits */ - int addr; /* physical address */ - char *cookie; /* for driver use */ - char (*getc)(struct _char_io_ *); /* returns character */ - void (*putc)(struct _char_io_ *, char); /* outputs one character */ - int (*avail)(struct _char_io_ *); /* returns 1 if char avail */ - void (*clear)(struct _char_io_ *); /* clear screen */ - void (*set)(struct _char_io_ *, int, int); /* set cursor pos. */ -}; -typedef struct _char_io_ _char_io_t, *_char_io_p; - -int serial_port_enabled(int port); - -#define CHARIO_IGNORE_ALL 0x0001 /* don't output to this dev */ -#define CHARIO_DISABLED 0x0002 /* error occured and ports not used */ -#define CHARIO_OUT_ENABLE 0x0004 /* Device does output */ -#define CHARIO_IN_ENABLE 0x0008 /* Device does input */ -#define CHARIO_IGNORE_CD 0x0010 /* Device shouldn't wait for CD */ -#define CHARIO_RTS_DTR_OFF 0x0020 /* Device shouldn't set rts/dtr */ -#define CHARIO_INIT 0x0040 /* Device should be (re)initialized */ - -/* - * Use this macro when debugging the output side of your driver. This - * will prevent any printf's from your driver causing an infinite loop - */ -#define PRINT(p, x) \ -{ p->flags |= CHARIO_IGNORE_ALL; printf x; p->flags &= ~CHARIO_IGNORE_ALL; } - -/* - * Defines for the serial port - */ - -#define SERIAL_FIFO_FLUSH 16 /* maximum number of chars to flush */ - -/* ---- Bit 11 defines direct serial port ---- */ -#define SDIRECT 0x1000 - -/* ---- Bits 9-10 define flow control ---- */ -#define SSOFT 0x800 -#define SHARD 0x400 - -/* ---- Bits 5-8 define baud rate ---- */ -#define S110 0x00 -#define S150 0x20 -#define S300 0x40 -#define S600 0x60 -#define S1200 0x80 -#define S2400 0xa0 -#define S4800 0xc0 -#define S9600 0xe0 -#define S19200 0x100 -#define S38400 0x120 -#define S57600 0x140 -#define S76800 0x160 -#define S115200 0x180 -#define S153600 0x1a0 -#define S230400 0x1c0 -#define S307200 0x1e0 -#define S460800 0x200 - -/* ---- Bits 3 & 4 are parity ---- */ -#define PARITY_NONE 0x10 -#define PARITY_ODD 0x08 -#define PARITY_EVEN 0x18 - -/* ---- Bit 2 is stop bit ---- */ -#define STOP_1 0x00 -#define STOP_2 0x04 - -/* ---- Bits 0 & 1 are data bits ---- */ -#define DATA_8 0x03 -#define DATA_7 0x02 -#define DATA_6 0x01 -#define DATA_5 0x00 - -/* ---- Line Status ---- */ -#define SERIAL_TIMEOUT 0x80 -#define SERIAL_XMITSHFT 0x40 -#define SERIAL_XMITHOLD 0x20 -#define SERIAL_BREAK 0x10 -#define SERIAL_FRAME 0x08 -#define SERIAL_PARITY 0x04 -#define SERIAL_OVERRUN 0x02 -#define SERIAL_DATA 0x01 - -/* - * Bit style flag operations for 32bit ints only - */ -#define BCLR(x) x &= ~(1 << y) -#define BSET(x, y) x |= (1 << y) -#define BISSET(x, y) x & (1 << y) - -#ifdef __cplusplus -} -#endif - -#endif /* _CHARIO_H */ diff --git a/usr/src/psm/stand/boot/i386/common/check_iopath.c b/usr/src/psm/stand/boot/i386/common/check_iopath.c deleted file mode 100644 index fb842546f0..0000000000 --- a/usr/src/psm/stand/boot/i386/common/check_iopath.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/promif.h> -#include "multiboot.h" -#include "util.h" -#include "debug.h" - -extern multiboot_info_t *mbi; - -/* return the number of bits set to 1 */ -static uint_t -count_bits(int val) -{ - int nbits = 0; - - while (val = (val ^ (val - 1))) - nbits++; - - return (nbits); -} - -/* - * GRUB has loaded two identical modules, we compare the content - * to check for potential problems in the BIOS I/O code path. - * Andromeda appears to have problems with USB DVD drive, but IDE - * drive works fine. This is a simple way to check it. - */ -void -check_iopath(void) -{ - mb_module_t *mod; - char errbits = 0; - uchar_t *cp1, *cp2; - uint_t i, size1, size2; - - /* check # modules */ - if (mbi->mods_count != 2) { - printf("The number of modules is not 2.\n"); - panic("reboot with modified GRUB menu"); - } - - /* check module sizes */ - mod = (mb_module_t *)mbi->mods_addr; - cp1 = (uchar_t *)mod[0].mod_start; - cp2 = (uchar_t *)mod[1].mod_start; - size1 = mod[0].mod_end - mod[0].mod_start; - size2 = mod[1].mod_end - mod[1].mod_start; - printf("module 1: start = 0x%p, size = 0x%x (%s)\n", - (void *)cp1, size1, (char *)mod[0].string); - printf("module 2: start = 0x%p, size = 0x%x (%s)\n", - (void *)cp2, size2, (char *)mod[1].string); - - if (size1 != size2) { - printf("Module sizes are different!\n"); - panic("Check FAILED"); - } - - for (i = 0; i < size1; i++) { - if (cp1[i] != cp2[i]) { - printf("byte 0x%x differ: %2x, %2x\n", - i, cp1[i], cp2[i]); - errbits += count_bits(cp1[i] ^ cp2[i]); - } - } - if (errbits) - panic("Check FAILED: err bit rate %d in %d bytes\n", - errbits, size1); - else - panic("Check PASSED: no bit error\n"); -} diff --git a/usr/src/psm/stand/boot/i386/common/console.c b/usr/src/psm/stand/boot/i386/common/console.c deleted file mode 100644 index d6c40a83df..0000000000 --- a/usr/src/psm/stand/boot/i386/common/console.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/bootsvcs.h> -#include <sys/varargs.h> -#include <sys/promif.h> -#include <sys/salib.h> -#include <sys/psw.h> - -#include "util.h" -#include "serial.h" -#include "chario.h" -#include "vga.h" -#include "console.h" -#include "debug.h" -#include "bootprop.h" - -#include "biosint.h" - -#define dprintf if (debug & D_ALLOC) printf - -static int cons_color = CONS_COLOR; -int console = CONS_SCREEN_TEXT; -/* or CONS_SCREEN_GRAPHICS, CONS_TTYA, CONS_TTYB */ -static int serial_ischar(void); -static int serial_getchar(void); -static void serial_putchar(int); -static void serial_adjust_prop(void); -static int console_state = 0; - -/* Clear the screen and initialize VIDEO, XPOS and YPOS. */ -static void -clear_screen(void) -{ - /* - * XXX should set vga mode so we don't depend on the - * state left by the boot loader - */ - vga_clear(cons_color); - vga_setpos(0, 0); -} - -/* Put the character C on the screen. */ -static void -screen_putchar(int c) -{ - int row, col; - - vga_getpos(&row, &col); - switch (c) { - case '\r': - vga_setpos(row, 0); - break; - - case '\b': - if (col > 0) - vga_setpos(row, col - 1); - break; - - case '\n': - if (row < VGA_TEXT_ROWS - 1) - vga_setpos(row + 1, col); - else - vga_scroll(cons_color); - break; - - default: - vga_drawc(c, cons_color); - if (col < VGA_TEXT_COLS -1) - vga_setpos(row, col + 1); - else if (row < VGA_TEXT_ROWS - 1) - vga_setpos(row + 1, 0); - else { - vga_setpos(row, 0); - vga_scroll(cons_color); - } - break; - } -} - -static int -get_videomode(void) -{ - struct int_pb ic = {0}; - int error; - - ic.ax = 0x0f00; - - if ((error = bios_doint(0x10, &ic)) & PS_C) { - dprintf("get_videomode: bios_doint failed: %d\n", error); - return (-1); - } - - return (ic.ax & 0xFF); -} - -/* serial port stuff */ -static int port; - -static void -serial_init(void) -{ - extern int bios_free; - extern void mdelay(); - - /* initialize only once */ - if (port != 0) - return; - - /* - * wait 2 seconds for serial console redirection to settle - * NOTE we only need to wait if BIOS console redirection - * is enabled, but we can't really tell without working - * through a scary Microsoft license. - */ - if (!bios_free) - mdelay(2000); - - switch (console) { - case CONS_TTYA: - port = 0x3f8; - break; - case CONS_TTYB: - port = 0x2f8; - break; - } - - outb(port + ISR, 0x20); - if (inb(port + ISR) & 0x20) { - /* - * 82510 chip is present - */ - outb(port + DAT+7, 0x04); /* clear status */ - outb(port + ISR, 0x40); /* set to bank 2 */ - outb(port + MCR, 0x08); /* IMD */ - outb(port + DAT, 0x21); /* FMD */ - outb(port + ISR, 0x00); /* set to bank 0 */ - } else { - /* - * set the UART in FIFO mode if it has FIFO buffers. - * use 16550 fifo reset sequence specified in NS - * application note. disable fifos until chip is - * initialized. - */ - outb(port + FIFOR, 0x00); /* clear */ - outb(port + FIFOR, FIFO_ON); /* enable */ - outb(port + FIFOR, FIFO_ON|FIFORXFLSH); /* reset */ - outb(port + FIFOR, - FIFO_ON|FIFODMA|FIFOTXFLSH|FIFORXFLSH|0x80); - if ((inb(port + ISR) & 0xc0) != 0xc0) { - /* - * no fifo buffers so disable fifos. - * this is true for 8250's - */ - outb(port + FIFOR, 0x00); - } - } - - /* disable interrupts */ - outb(port + ICR, 0); - - /* adjust setting based on tty properties */ - serial_adjust_prop(); - - /* - * Do a full reset to match console behavior. - * In verbose mode (-V), we only reset ansi attributes, - * leaving existing output on screen. - * 0x1B + c - reset everything - * 0x1B + - * [ - attribute change (blick, inverse, color, etc.) - * 0 - attribute value - * m - terminate escape sequence - * - */ - if (verbosemode) { - serial_putchar(0x1B); - serial_putchar('['); - serial_putchar('0'); - serial_putchar('m'); - } else { - serial_putchar(0x1B); - serial_putchar('c'); - } -} - -/* adjust serial port based on properties */ -static void -serial_adjust_prop(void) -{ - int plen; - char propname[20], propval[20]; - - (void) snprintf(propname, sizeof (propname), "tty%c-mode", - 'a' + console - CONS_TTYA); - plen = bgetproplen(NULL, propname); - if (plen > 0 && plen <= sizeof (propval)) { - (void) bgetprop(NULL, propname, propval); - } else { - (void) strcpy(propval, "9600,8,n,1,-"); - } - - { - char *p; - ulong_t baud; - uchar_t lcr = 0; - - /* property is of the form: "9600,8,n,1,-" */ - p = strtok(propval, ","); - if (strcmp(p, "110") == 0) - baud = ASY110; - else if (strcmp(p, "150") == 0) - baud = ASY150; - else if (strcmp(p, "300") == 0) - baud = ASY300; - else if (strcmp(p, "600") == 0) - baud = ASY600; - else if (strcmp(p, "1200") == 0) - baud = ASY1200; - else if (strcmp(p, "2400") == 0) - baud = ASY2400; - else if (strcmp(p, "4800") == 0) - baud = ASY4800; - else if (strcmp(p, "19200") == 0) - baud = ASY19200; - else if (strcmp(p, "38400") == 0) - baud = ASY38400; - else if (strcmp(p, "57600") == 0) - baud = ASY57600; - else if (strcmp(p, "115200") == 0) - baud = ASY115200; - else - baud = ASY9600; - - /* set baud */ - outb(port + LCR, DLAB); - outb(port + DAT+DLL, baud & 0xff); - outb(port + DAT+DLH, (baud >> 8) & 0xff); - - p = strtok(NULL, ","); - if (p) { - switch (*p) { - case '5': - lcr |= BITS5; - break; - case '6': - lcr |= BITS6; - break; - case '7': - lcr |= BITS7; - break; - case '8': - default: - lcr |= BITS8; - break; - } - } - - p = strtok(NULL, ","); - if (p) { - switch (*p) { - case 'n': - lcr |= PARITY_NONE; - break; - case 'o': - lcr |= PARITY_ODD; - break; - case 'e': - default: - lcr |= PARITY_EVEN; - break; - } - } - - p = strtok(NULL, ","); - if (p) { - switch (*p) { - case '1': - /* STOP1 is 0 */ - break; - default: - lcr |= STOP2; - break; - } - } - - /* set parity bits */ - outb(port + LCR, lcr); - } - - (void) snprintf(propname, sizeof (propname), - "tty%c-rts-dtr-off", 'a' + console - CONS_TTYA); - plen = bgetproplen(NULL, propname); - if (plen > 0 && plen <= sizeof (propval)) { - (void) bgetprop(NULL, propname, propval); - } else { - (void) strcpy(propval, "false"); - } - - { - uchar_t mcr = DTR | RTS; - if (propval[0] != 'f' && propval[0] != 'F') - mcr = 0; - /* set modem control bits */ - outb(port + MCR, mcr | OUT2); - } -} - -/* For console=usb-serial, store early output in a buffer */ -static char *usbser_buf; -static char *usbser_cur; - -static void -usbser_init(void) -{ - if (usbser_buf) - return; - - usbser_cur = usbser_buf = bkmem_zalloc(MMU_PAGESIZE); - (void) bsetprop(NULL, "usb-serial-buf", &usbser_buf, sizeof (char *)); -} - -static void -usbser_putchar(int c) -{ - if (usbser_buf == 0 || usbser_cur >= usbser_buf + MMU_PAGESIZE - 1) - return; - - *usbser_cur++ = c; -} - -char * -console_init(char *bootstr) -{ - char *cons; - - console = CONS_INVALID; - - cons = strstr(bootstr, "console="); - if (cons) - cons += strlen("console="); - else { - cons = strstr(bootstr, "output-device="); - if (cons) - cons += strlen("output-device="); - } - - /* both "graphics" and "text" mean "detect graphics mode" now */ - if (cons) { - if (strncmp(cons, "ttya", 4) == 0) { - console = CONS_TTYA; - cons = "ttya"; - } else if (strncmp(cons, "ttyb", 4) == 0) { - console = CONS_TTYB; - cons = "ttyb"; - } else if (strncmp(cons, "graphics", 9) == 0) { - console = CONS_SCREEN_TEXT; - cons = "graphics"; - } else if (strncmp(cons, "text", 4) == 0) { - console = CONS_SCREEN_TEXT; - cons = "text"; - } else if (strncmp(cons, "screen", 6) == 0) { - console = CONS_SCREEN_TEXT; - cons = "text"; - } else if (strncmp(cons, "usb-serial", 10) == 0) { - console = CONS_USBSER; - cons = "usb-serial"; - } - } - - /* - * If no console device specified, default to text. - * Remember what was specified for second phase. - */ - console_state = console; - if (console == CONS_INVALID) - console = CONS_SCREEN_TEXT; - - switch (console) { - case CONS_TTYA: - case CONS_TTYB: - case CONS_USBSER: - /* leave initialization till later, when we know tty mode */ - break; - case CONS_SCREEN_TEXT: - default: - clear_screen(); - kb_init(); - break; - } - - return (cons); -} - -/* - * Second phase of possible console redirection, - * based on input-device & output-device eeprom(1M) properties. - * Also support a unified "console" property. - */ -void -console_init2(char *inputdev, char *outputdev, char *consoledev) -{ - int cons = CONS_INVALID; - - if (console_state == CONS_INVALID) { - - /* both "graphics" and "text" mean "detect graphics mode" now */ - if (consoledev) { - if (strcmp(consoledev, "ttya") == 0) - cons = CONS_TTYA; - else if (strcmp(consoledev, "ttyb") == 0) - cons = CONS_TTYB; - else if (strcmp(consoledev, "usb-serial") == 0) - cons = CONS_USBSER; - else if (strcmp(consoledev, "text") == 0) - cons = CONS_SCREEN_TEXT; - else if (strcmp(consoledev, "graphics") == 0) - cons = CONS_SCREEN_TEXT; - else if (strcmp(consoledev, "screen") == 0) - cons = CONS_SCREEN_TEXT; - } - - if (cons == CONS_INVALID) { - if (inputdev) { - if (strcmp(inputdev, "ttya") == 0) - cons = CONS_TTYA; - else if (strcmp(inputdev, "ttyb") == 0) - cons = CONS_TTYB; - } - if (outputdev) { - if (strcmp(outputdev, "ttya") == 0) - cons = CONS_TTYA; - else if (strcmp(outputdev, "ttyb") == 0) - cons = CONS_TTYB; - } - } - - if (cons == CONS_INVALID) - cons = CONS_SCREEN_TEXT; - console = cons; - - switch (console) { - case CONS_TTYA: - case CONS_TTYB: - if (console_state != CONS_TTYA && - console_state != CONS_TTYB) { - serial_init(); - } - break; - case CONS_USBSER: - break; - case CONS_SCREEN_TEXT: - if (console_state != CONS_SCREEN_TEXT) { - clear_screen(); - kb_init(); - } - break; - } - } - - /* special handling for graphics boot and serial console */ - switch (console) { - case CONS_TTYA: - case CONS_TTYB: - serial_init(); - break; - case CONS_USBSER: - usbser_init(); - break; - default: - if (get_videomode() == VGA_GRAPHICS) { - console_state = CONS_SCREEN_GRAPHICS; - (void) bsetprop(NULL, "console", "graphics", - sizeof ("graphics")); - } else { - console_state = CONS_SCREEN_TEXT; - (void) bsetprop(NULL, "console", "text", - sizeof ("text")); - } - }; -} - -static void -serial_putchar(int c) -{ - int checks = 10000; - - while (((inb(port + LSR) & XHRE) == 0) && checks--) - ; - outb(port + DAT, (char)c); -} - -static int -serial_getchar(void) -{ - uchar_t lsr; - - while (serial_ischar() == 0) - ; - - lsr = inb(port + LSR); - if (lsr & (SERIAL_BREAK | SERIAL_FRAME | - SERIAL_PARITY | SERIAL_OVERRUN)) { - if (lsr & SERIAL_OVERRUN) { - printf("silo overflow\n"); - return (inb(port + DAT)); - } else { - /* Toss the garbage */ - (void) inb(port + DAT); - return (0); - } - } - return (inb(port + DAT)); -} - -static int -serial_ischar(void) -{ - return (inb(port + LSR) & RCA); -} - -static void -_doputchar(int c) -{ - switch (console) { - case CONS_TTYA: - case CONS_TTYB: - serial_putchar(c); - return; - case CONS_USBSER: - /* - * usbser_putchar() prints to memory buffer. - * The buffer is displayed after consconfig(). - */ - usbser_putchar(c); - return; - case CONS_SCREEN_TEXT: - screen_putchar(c); - return; - } -} - -void -putchar(int c) -{ - static int bhcharpos = 0; - - if (c == '\t') { - do { - _doputchar(' '); - } while (++bhcharpos % 8); - return; - } else if (c == '\n' || c == '\r') { - bhcharpos = 0; - _doputchar('\r'); - _doputchar(c); - return; - } else if (c == '\b') { - if (bhcharpos) - bhcharpos--; - _doputchar(c); - return; - } - - bhcharpos++; - _doputchar(c); -} - - -int -getchar(void) -{ - switch (console) { - case CONS_TTYA: - case CONS_TTYB: - return (serial_getchar()); - default: - return (kb_getchar()); - } -} - -int -ischar(void) -{ - switch (console) { - case CONS_TTYA: - case CONS_TTYB: - return (serial_ischar()); - default: - return (kb_ischar()); - } -} - -/* - * Read from the console (using getchar) into string str, - * until a carriage return or until n-1 characters are read. - * Null terminate the string, and return. - * This all is made complicated by the fact that we must - * do our own echoing during input. - * N.B.: Returns the *number of characters in str*. - */ - -int -cons_gets(char *str, int n) -{ - int c; - int t; - char *p; - - p = str; - c = 0; - - while ((t = getchar()) != '\r') { - putchar(t); - if (t == '\b') { - if (c) { - printf(" \b"); - c--; p--; - } else - putchar(' '); - continue; - } - if (c < n - 1) { - *p++ = t; - c++; - } - } - putchar('\n'); - *p = '\0'; - - return (c); -} - -/*PRINTFLIKE1*/ -void -printf(const char *fmt, ...) -{ - va_list adx; - - va_start(adx, fmt); - prom_vprintf(fmt, adx); - va_end(adx); -} - -/* setup boot syscall fields needed by the kernel */ -static struct boot_syscalls sc = { - getchar, - putchar, - ischar -}; - -struct boot_syscalls *sysp = ≻ diff --git a/usr/src/psm/stand/boot/i386/common/cpu_id.h b/usr/src/psm/stand/boot/i386/common/cpu_id.h deleted file mode 100644 index 8948d8031b..0000000000 --- a/usr/src/psm/stand/boot/i386/common/cpu_id.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 2001 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _CPU_ID_H -#define _CPU_ID_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define GenuineIntel 0x1 -#define AuthenticAMD 0x2 - -#define Genu 0x756e6547 -#define ineI 0x49656e69 -#define ntel 0x6c65746e - -#define Auth 0x68747541 -#define enti 0x69746e65 -#define cAMD 0x444d4163 - -#ifndef _ASM - -extern int max_std_cpuid_level; -extern unsigned int cpu_vendor; - -extern int is486(void); -extern int enable_cpuid(void); -extern int largepage_supported(void); -extern int enable_large_pages(void); -extern int global_bit(void); -extern int enable_global_pages(void); -extern int pae_supported(void); - -#endif /* !_ASM */ - -#ifdef __cplusplus -} -#endif - -#endif /* _CPU_ID_H */ diff --git a/usr/src/psm/stand/boot/i386/common/debug.h b/usr/src/psm/stand/boot/i386/common/debug.h deleted file mode 100644 index 858cb21245..0000000000 --- a/usr/src/psm/stand/boot/i386/common/debug.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _DEBUG_H -#define _DEBUG_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -extern int debug; -extern int verbosemode; - -/* Mask bits for debug */ -#define D_BPROP 0x01 -#define D_MBINFO 0x02 -#define D_KEYBOARD 0x04 -#define D_ALLOC 0x08 -#define D_BOP 0x10 -#define D_BIOS 0x20 -#define D_GRAPHICS 0x40 - -#ifdef __cplusplus -} -#endif - -#endif /* _DEBUG_H */ diff --git a/usr/src/psm/stand/boot/i386/common/i86.il b/usr/src/psm/stand/boot/i386/common/i86.il deleted file mode 100644 index 180cb5135a..0000000000 --- a/usr/src/psm/stand/boot/i386/common/i86.il +++ /dev/null @@ -1,122 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1992,2000 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/ -/ In-line functions for i86 calls. -/ - - -/ -/ in and out -/ - .inline inb,4 - movl (%esp), %edx - xorl %eax, %eax - inb (%dx) - .end - - .inline inw,4 - movl (%esp), %edx - xorl %eax, %eax - inw (%dx) - .end - - .inline inl,4 - movl (%esp), %edx - xorl %eax, %eax - inl (%dx) - .end - - .inline outb,8 - movl (%esp), %edx - movl 4(%esp), %eax - outb (%dx) - .end - - .inline outw,8 - movl (%esp), %edx - movl 4(%esp), %eax - outw (%dx) - .end - - .inline outl,8 - movl (%esp), %edx - movl 4(%esp), %eax - outl (%dx) - .end - -/ -/ Networking byte order functions (too bad, Intel has the wrong byte order) -/ - - .inline htonl,4 - movl (%esp), %eax - bswap %eax - .end - - .inline ntohl,4 - movl (%esp), %eax - bswap %eax - .end - - .inline htons,4 - movl (%esp), %eax - bswap %eax - shrl $16, %eax - .end - - .inline ntohs,4 - movl (%esp), %eax - bswap %eax - shrl $16, %eax - .end - -/ -/ disable interrupts and return value describing if interrupts were enabled -/ - .inline clear_int_flag,0 - pushfl - cli - popl %eax - .end - -/ -/ restore interrupt enable flag to value returned from 'clear_int_flag' above -/ - .inline restore_int_flag,4 - pushl (%esp) - popfl - .end - -/ -/ stub function. -/ i386 arch currently has a unified cache -/ - .inline sync_instruction_memory,8 - nop - .end diff --git a/usr/src/psm/stand/boot/i386/common/machine.h b/usr/src/psm/stand/boot/i386/common/machine.h deleted file mode 100644 index d841cb8526..0000000000 --- a/usr/src/psm/stand/boot/i386/common/machine.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ -/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ -/* All Rights Reserved */ - -/* - * Copyrighted as an unpublished work. - * (c) Copyright INTERACTIVE Systems Corporation 1986, 1988, 1990 - * All rights reserved. - */ - -#ifndef _MACHINE_H -#define _MACHINE_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -struct machconfig { - char *sigaddr; /* Machine signature location */ - unsigned char siglen; /* Signature length */ - unsigned char sigid[10]; /* Signature to match */ - unsigned char old_mt; /* OLD Machine type */ - unsigned char machine; /* Machine type */ - ulong_t m_flag; /* status flag */ - int (*m_entry)(); /* machine entry point */ -}; - -#define M_FLG_SRGE 1 /* sig scattered in a range of memory */ - -#define M_ID_AT386 0 -#define M_ID_MC386 1 -#define M_ID_EISA 2 - -#define SYS_MODEL() *(char *)0xFFFFE -#define MODEL_AT (uchar_t)0xFC -#define MODEL_MC (uchar_t)0xF8 -#define USER_START 0x100000 - -#define NPTEPERPT 1024 -typedef struct ptbl { - int page[NPTEPERPT]; -} ptbl_t; - -/* combine later with ../../../uts/i86/sys/pte.h */ -#define PG_P 0x1 /* page is present */ -#define PG_RW 0x2 /* page is read/write */ -#define PG_SIZE 0x80 /* page is 4MB */ -#define PG_GLOBAL 0x100 /* page is persistent */ - -/* - * keyboard controller I/O port addresses - */ - -#define KB_OUT 0x60 /* output buffer R/O */ -#define KB_IDAT 0x60 /* input buffer data write W/O */ -#define KB_STAT 0x64 /* keyboard controller status R/O */ -#define KB_ICMD 0x64 /* input buffer command write W/O */ - -/* - * keyboard controller commands and flags - */ -#define KB_INBF 0x02 /* input buffer full flag */ -#define KB_OUTBF 0x01 /* output buffer full flag */ -#define KB_GATE20 0x02 /* set this bit to allow addresses > 1Mb */ -#define KB_ROP 0xD0 /* read output port command */ -#define KB_WOP 0xD1 /* write output port command */ -#define KB_RCB 0x20 /* read command byte command */ -#define KB_WCB 0x60 /* write command byte command */ -#define KB_ENAB 0xae /* enable keyboard interface */ -#define KB_DISAB 0x10 /* disable keyboard */ -#define KB_EOBFI 0x01 /* enable interrupt on output buffer full */ -#define KB_ACK 0xFA /* Acknowledgement byte from keyboard */ -#define KB_RESETCPU 0xFE /* command to reset AT386 cpu */ -#define KB_READID 0xF2 /* command to read keyboard id */ -#define KB_RESEND 0xFE /* response from keyboard to resend data */ -#define KB_ERROR 0xFF /* response from keyboard to resend data */ -#define KB_RESET 0xFF /* command to reset keyboard */ -/* - * command to to enable keyboard - * this is different from KB_ENAB above in - * that KB_ENAB is a command to the 8042 to - * enable the keyboard interface, not the - * keyboard itself - */ -#define KB_ENABLE 0xF4 - -/* move later into immu.h */ -#ifndef PTSIZE -#define PTSIZE 4096 -#endif - -#define ptround(p) ((int *)(((int)p + PTSIZE-1) & ~(PTSIZE-1))) -#define FOURMEG 4194304 -#define FOURMB_PTE (PG_P | PG_RW | PG_SIZE) - -#ifdef __cplusplus -} -#endif - -#endif /* _MACHINE_H */ diff --git a/usr/src/psm/stand/boot/i386/common/memory.c b/usr/src/psm/stand/boot/i386/common/memory.c deleted file mode 100644 index 591c7781fe..0000000000 --- a/usr/src/psm/stand/boot/i386/common/memory.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * i86pc memory routines - * - * This file contains memory management routines to provide - * functionality found in proms on Sparc machines - */ - -#include <sys/types.h> -#include <sys/sysmacros.h> -struct cpu; /* get around mmu.h warning */ -#include <sys/mmu.h> -#include <sys/promif.h> -#include <sys/memlist.h> -#include "standalloc.h" -#include "util.h" -#include "machine.h" -#include "debug.h" -#include "cpu_id.h" - -/* These are the various memory lists in boot.c */ -extern struct memlist *pfreelistp, /* physmem available */ - *vfreelistp, /* virtmem available */ - *pinstalledp, /* physmem installed */ - *pbooterp, /* booter occupied */ - *pramdiskp; /* ramdisk memory */ - -extern uint_t magic_phys; -extern uint_t bpd_loc; -extern int use_align; - -extern void start_paging(void); -extern int map_phys(int, size_t, caddr_t, uint64_t); - -static int global_pages; -static void fiximp(void); - -#define ALIGN(x, a) ((a) == 0 ? (intptr_t)(x) : \ - (((intptr_t)(x) + (intptr_t)(a) - 1l) & ~((intptr_t)(a) - 1l))) - -#define MMU_L1_INDEX(a) (((uint_t)(a)) >> 22) -#define MMU_L2_INDEX(a) ((((uint_t)(a)) >> 12) & 0x3ff) - -void -init_paging(void) -{ - ptbl_t *pdp; - int mode; - struct memlist *entry; - - fiximp(); /* figure out cpu capabilities */ - - /* allocate boot page table directory */ - pdp = (ptbl_t *)resalloc(RES_BOOTSCRATCH, MMU_PAGESIZE, 0, 0); - if (pdp == (ptbl_t *)0) { - prom_panic("init_paging dir"); - } - bpd_loc = (uint_t)pdp; - (void) bzero(pdp, MMU_PAGESIZE); - - /* map in scratch memory */ - mode = PG_P | PG_RW; - (void) map_phys(mode, magic_phys, 0, 0); - - /* map in booter occupied memory */ - entry = pbooterp; - while (entry) { - (void) map_phys(mode, (size_t)entry->size, - (caddr_t)(uintptr_t)entry->address, entry->address); - entry = entry->next; - } - - /* map in ramdisk memory: disallow write */ - entry = pramdiskp; - while (entry) { - (void) map_phys(PG_P, (size_t)entry->size, - (caddr_t)(uintptr_t)entry->address, entry->address); - entry = entry->next; - } - - start_paging(); - if (verbosemode) - printf("start paging\n"); -} - -static int -map_4m_page(caddr_t vaddr, uint64_t paddr) -{ - ptbl_t *pdp = (ptbl_t *)bpd_loc; - uint_t pdir = MMU_L1_INDEX(vaddr); - - if (pdp->page[pdir] & PG_P) - return (-1); /* already mapped */ - - /* don't set global flag for Pentium or earlier */ - pdp->page[pdir] = - (FOURMB_PTE | ((uint_t)paddr & FOURMB_PAGEMASK)); - if (global_pages) - pdp->page[pdir] |= PG_GLOBAL; - - return (0); -} - -static int -map_4k_pages(int mode, size_t bytes, caddr_t vaddr, uint64_t paddr) -{ - ptbl_t *pdp, *ptp; - uint_t v, vaddr_end; - - pdp = (ptbl_t *)bpd_loc; - - v = (uint_t)vaddr; - vaddr_end = (v + bytes + MMU_PAGESIZE - 1) & MMU_STD_PAGEMASK; - - while (v < vaddr_end) { - uint_t pdir = MMU_L1_INDEX(v); - - if (pdp->page[pdir] & PG_P) { - ptp = (ptbl_t *) - ((uint_t)pdp->page[pdir] & MMU_STD_PAGEMASK); - } else { - /* allocate a new page table */ - ptp = (ptbl_t *)resalloc(RES_BOOTSCRATCH, - MMU_PAGESIZE, 0, 0); - pdp->page[pdir] = ((uint_t)ptp | PG_P | PG_RW); - (void) bzero(ptp, MMU_PAGESIZE); - } - - /* as long as we are on this page table */ - while ((pdir == MMU_L1_INDEX(v)) && (v < vaddr_end)) { - uint_t pndx = MMU_L2_INDEX(v); - if (ptp->page[pndx] & PG_P) { - /* - * If we are already mapped, panic! - * This should not happen under the - * current memory allocation scheme - * where physmem is either mapped 1:1 - * or mapped above kernelbase. - */ - printf("remapping page at 0x%x\n", v); - prom_panic("remapping unsupported in booter"); - ptp->page[pndx] |= mode; - } else { - ptp->page[pndx] = - (((uint_t)paddr & MMU_STD_PAGEMASK) | mode); - } - paddr += MMU_PAGESIZE; - v += MMU_PAGESIZE; - } - } - - return (0); -} - -int -map_phys(int mode, size_t bytes, caddr_t vaddr, uint64_t paddr) -{ - if (paddr >> 32) /* don't handle PAE */ - return (-1); - - if (use_align && (bytes == FOURMB_PAGESIZE) && - ((uint_t)vaddr & (FOURMB_PAGESIZE - 1)) == 0 && - ((uint_t)paddr & (FOURMB_PAGESIZE - 1)) == 0) - return (map_4m_page(vaddr, paddr)); /* ignore mode */ - - if (mode == 0) - mode = PG_P | PG_RW; - return (map_4k_pages(mode, bytes, vaddr, paddr)); -} - -static void -fiximp(void) -{ - /* need to support at least standard cpuid level 1 to continue */ - (void) enable_cpuid(); - if (max_std_cpuid_level < 1) - return; - - use_align = largepage_supported(); - - if (use_align) { - (void) enable_large_pages(); - - global_pages = global_bit(); - } - - if (global_pages) - (void) enable_global_pages(); -} diff --git a/usr/src/psm/stand/boot/i386/common/mkbin.c b/usr/src/psm/stand/boot/i386/common/mkbin.c deleted file mode 100644 index 423ecec781..0000000000 --- a/usr/src/psm/stand/boot/i386/common/mkbin.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 1994, 2002 Sun Microsystems, Inc. - * All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#undef _KERNEL - -#include <sys/types.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/exechdr.h> -#include <sys/elf.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -int -main(int argc, char **argv) -{ - int ofd, - ifd; - struct stat sbuf; - void * elffile; - unsigned int i, - total, - bytes; - Elf32_Ehdr *ehdr; - Elf32_Shdr *s; - Elf32_Shdr *first_shdr = NULL, - *nobits_shdr = NULL; - - if (argc < 3) { - (void) printf("usage: mkbin elf_file binary_file \n"); - exit(1); - } - if ((ifd = open(argv[1], O_RDONLY)) == -1) { - perror("open elf input"); - exit(2); - } - - if ((ofd = open(argv[2], O_RDWR | O_TRUNC | O_CREAT, 0777)) == -1) { - perror("open output binary"); - exit(3); - } - if (fstat(ifd, &sbuf) == -1) { - perror("fstat"); - exit(1); - } - - /* - * mmap in the whole file to work with it. - */ - if ((elffile = (void *)mmap(NULL, sbuf.st_size, PROT_READ, - MAP_PRIVATE, ifd, 0)) == MAP_FAILED) { - perror("mmap failed"); - exit(1); - } - ehdr = (Elf32_Ehdr *)elffile; - - if (*(int *)(ehdr->e_ident) != *(int *)(ELFMAG)) { - perror("not elf file "); - exit(5); - } - - s = (Elf32_Shdr *)((char *)elffile + ehdr->e_shoff); - /* - * find a pointer to the first allocated section header - * and the bss(NOBITS) section header. - */ - for (i = 0; i < ehdr->e_shnum; i++, s++) { - if (!(s->sh_flags & SHF_ALLOC)) - continue; - if (!first_shdr) { - first_shdr = s; - continue; - } - if (s->sh_type == SHT_NOBITS) { - nobits_shdr = s; - break; - } - } - - if ((first_shdr == NULL) || (nobits_shdr == NULL)) { - (void) fprintf(stderr, "ERROR: Missing headers in elf file.\n"); - exit(1); - } - - bytes = nobits_shdr->sh_offset - first_shdr->sh_offset; - if (write(ofd, (char *)elffile + first_shdr->sh_offset, - bytes) != bytes) { - perror("write sections"); - exit(1); - } - total = bytes + nobits_shdr->sh_size; - /* - * round up to the next 512k block - */ - if (total % 512 != 0) - total += 512 - (total % 512); - - if (ftruncate(ofd, total) == -1) { - perror("ftruncate"); - exit(1); - } - - (void) close(ifd); - (void) close(ofd); - exit(0); -} diff --git a/usr/src/psm/stand/boot/i386/common/multiboot.c b/usr/src/psm/stand/boot/i386/common/multiboot.c deleted file mode 100644 index 79bacf01ba..0000000000 --- a/usr/src/psm/stand/boot/i386/common/multiboot.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * This program is loaded and executed by GRUB on x86 platforms. - * It is responsible for interpreting the miniroot archive - * loaded by GRUB, read unix and krtld, and jump to the kernel. - * - * Currently the kernel (_kobj_boot) expects a syscall vector, - * bootops, and elfbootvec. So we oblige by providing the - * same services for now. - */ - -#include <sys/types.h> -#include <sys/memlist.h> -#include <sys/reboot.h> -#include <amd64/machregs.h> -#include "multiboot.h" -#include "debug.h" -#include "standalloc.h" -#include "bootprop.h" -#include "util.h" -#include "console.h" - -typedef int (*func_t)(); -extern void setup_bootops(); -extern void setup_memlists(); -extern void init_paging(void); -extern int mountroot(char *); -extern int openfile(char *, char *); -extern int close(int); -extern char *console_init(char *); -extern void kmem_init(void); -extern void init_biosprog(); -extern func_t readfile(int fd, int print); -extern void exitto(func_t); - -static void print_mbinfo(void); - -int debug; -static int started_bootfile = 0; - -#define dprintf if (debug & D_MBOOT) printf - -#define STACK_LINES 9 -#define WORDS_PER_LINE 6 - -multiboot_info_t *mbi; -multiboot_header_t *mbh; - -char *bootfile_prop = NULL; -char *inputdevice_prop = NULL; -char *outputdevice_prop = NULL; -char *console_prop = NULL; - -extern uint_t bpd_loc; -extern char *bootfile; -extern char *module_path; -int is_amd64; - -#ifdef BOOTAMD64 -extern void amd64_handoff(uint64_t); -extern int amd64_config_cpu(); -extern uint32_t amd64_special_hw(void); - -int amd64_elf64; -uint64_t elf64_go2; -#endif /* BOOTAMD64 */ - -extern void get_bootenv_props(void); -extern void vga_probe(void); - -void -main(ulong_t magic, ulong_t addr, ulong_t header) -{ - int fd; - char *grub_bootstr; - int (*entry)(); - - if (magic != MB_BOOTLOADER_MAGIC) { - /* printf isn't working, so we return to loader */ - return; - } - - /* Set MBI to the address of the Multiboot information structure. */ - mbi = (multiboot_info_t *)addr; - mbh = (multiboot_header_t *)header; - - grub_bootstr = (char *)mbi->cmdline; - console_prop = console_init(grub_bootstr); /* so we can do printf */ - kmem_init(); /* initialize memory allocator */ - setup_memlists(); /* memory core for the allocator */ - - get_grub_bootargs(grub_bootstr); /* get grub cmd options */ - if (debug & D_MBINFO) - print_mbinfo(); - setup_bootdev_props(); /* boot device related props */ - setup_bootops(); /* 32-bit memory ops and lists */ - init_paging(); /* turn on paging to before loading kernel */ - mbi = NULL; /* can't access multiboot info from now on */ - - if (mountroot("boot") != 0) { /* mount the ramdisk */ - panic("cannot mount boot archive\n"); - } else if (verbosemode) { - printf("mountroot succeeded\n"); - } - - init_biosprog(); /* install bios service program */ - get_bootenv_props(); /* read bootenv.rc properties */ - vga_probe(); /* probe bios for vga */ - setup_bootprop(); /* set up boot properties for the kernel */ - - /* - * Set console as per eeprom(1M) if not yet specified. - * May set graphics mode, for which bios support is required. - */ - console_init2(inputdevice_prop, outputdevice_prop, - console_prop); - -#ifdef BOOTAMD64 - /* Test to see if this CPU is an AMD64 */ - is_amd64 = amd64_config_cpu(); - if (verbosemode && is_amd64) - printf("cpu is amd64 capable\n"); - if (is_amd64 == 0 && !amd64_special_hw()) - (void) bsetprop(NULL, "CPU_not_amd64", "true", sizeof ("true")); -#endif /* BOOTAMD64 */ - - /* - * Determine the boot file - * precedence given to what's specified via grub, - * fall back to boot-file property set by eeprom(1M). - * If boot-file not set, fall back to defaults - */ - if (bootfile == NULL) { - get_eeprom_bootargs(bootfile_prop); - if (bootfile == NULL) { - bootfile = is_amd64 ? - "kernel/amd64/unix" : "kernel/unix"; - } - } - - printf("\n"); - fd = openfile(bootfile, 0); /* open the kernel file */ - if (fd == -1) { - panic("cannot open %s\n", bootfile); - } else { - extern char filename[]; - (void) bsetprop(NULL, "whoami", filename, strlen(filename) + 1); - if (verbosemode) - printf("open kernel file: %s\n", filename); - } - - entry = readfile(fd, verbosemode); - (void) close(fd); - if (module_path) { - (void) bsetprop(NULL, "module-path", module_path, - strlen(module_path) + 1); - if (verbosemode) - printf("module_path set to: %s\n", module_path); - } - if (entry == (int (*)())-1) { - panic("no entry point in %s\n", bootfile); - } - -#ifdef BOOTAMD64 - if (amd64_elf64) { - if (verbosemode) - printf("Boot about to exit to AMD64 image at 0x%llx.\n", - (uint64_t)elf64_go2); - amd64_handoff(elf64_go2); - } -#endif - - if (verbosemode) - printf("Boot about to exit to 32-bit kernel image at 0x%x.\n", - entry); - - /* - * It's a while before the kernel actually gets around to setting - * up traps; if we die during that period, multiboot's trap handler - * will get control. We want to at least know roughly where we - * died. - */ - started_bootfile = 1; - exitto(entry); - - panic("failed to boot %s\n", bootfile); -} - -static void -print_mbinfo(void) -{ - int tmp; - - /* multiboot header */ - printf("header_addr = 0x%lx\n", mbh->header_addr); - printf("load_addr = 0x%lx, end = 0x%lx, bss_end = 0x%lx\n", - mbh->load_addr, mbh->load_end_addr, mbh->bss_end_addr); - printf("entry_addr = 0x%lx\n", mbh->entry_addr); - - /* multiboot info location */ - printf("mbi = 0x%p, size = 0x%x\n", (void *) mbi, sizeof (*mbi)); - - /* flags */ - printf("flags = 0x%x\n", (unsigned)mbi->flags); - - if (MB_CHECK_FLAG(mbi->flags, 9)) - printf("boot loader: %s\n", (char *)mbi->boot_loader_name); - - if (MB_CHECK_FLAG(mbi->flags, 2)) - printf("command line: %s\n", (char *)mbi->cmdline); - - /* memory range */ - if (MB_CHECK_FLAG(mbi->flags, 0)) - printf("mem_lower = %uKB, mem_upper = %uKB\n", - (unsigned)mbi->mem_lower, (unsigned)mbi->mem_upper); - - /* Is boot_device valid? */ - if (MB_CHECK_FLAG(mbi->flags, 1)) { - tmp = ((mbi->boot_device >> 24) & 0xff); - printf("boot_device = 0x%x", tmp); - tmp = ((mbi->boot_device >> 16) & 0xff); - printf(", part1 = 0x%x", tmp); - tmp = ((mbi->boot_device >> 8) & 0xff); - printf(", part2 = 0x%x", tmp); - tmp = (mbi->boot_device & 0xff); - printf(", part3 = 0x%x\n", tmp); - } - - /* Is the command line passed? */ - if (MB_CHECK_FLAG(mbi->flags, 2)) - printf("cmdline = %s\n", (char *)mbi->cmdline); - - /* Are mods_* valid? */ - if (MB_CHECK_FLAG(mbi->flags, 3)) { - mb_module_t *mod; - int i; - - printf("mods_count = %d, mods_addr = 0x%x\n", - (int)mbi->mods_count, (int)mbi->mods_addr); - for (i = 0, mod = (mb_module_t *)mbi->mods_addr; - i < mbi->mods_count; i++, mod++) { - printf( - " mod_start = 0x%x, mod_end = 0x%x, string = %s\n", - (unsigned)mod->mod_start, - (unsigned)mod->mod_end, (char *)mod->string); - } - } - - /* make sure we are not a.out */ - if (MB_CHECK_FLAG(mbi->flags, 4)) { - printf("Bit 4 is set, we shouldn't be using a.out format.\n"); - return; - } - - /* Is the section header table of ELF valid? */ - if (MB_CHECK_FLAG(mbi->flags, 5)) { - mb_elf_shtable_t *elf_sec = &(mbi->elf_sec); - - printf("elf_sec: num = %u, size = 0x%x," - " addr = 0x%x, shndx = 0x%x\n", - (unsigned)elf_sec->num, (unsigned)elf_sec->size, - (unsigned)elf_sec->addr, (unsigned)elf_sec->shndx); - } - - /* print drives info */ - if (MB_CHECK_FLAG(mbi->flags, 7)) { - printf("drives length %ld, drives addr 0x%lx\n", - mbi->drives_length, mbi->drives_addr); - } -} - -static void -show_regs_and_stack(struct i386_machregs *regs, int stack_lines) -{ - int i, j; - uint32_t *esp = (uint32_t *)regs->r_esp; - - printf("trap type %d (0x%x) err code 0x%x eip=0x%x\n", - regs->r_trapno, regs->r_trapno, regs->r_err, - regs->r_eip); - printf("%%eflags = 0x%08x\t%%cs:%%eip = 0x%04x:0x%08x\n", - regs->r_efl, regs->r_cs, regs->r_eip); - printf("%%eax = 0x%08x\t%%ebx = 0x%08x\t%%ecx = 0x%08x\n", - regs->r_eax, regs->r_ebx, regs->r_ecx); - printf("%%edx = 0x%08x\t%%esi = 0x%08x\t%%edi = 0x%08x\n", - regs->r_edx, regs->r_esi, regs->r_edi); - printf("%%esp = 0x%08x\t%%ebp = 0x%08x\n", - regs->r_esp, regs->r_ebp); - printf("%%ss = 0x%04x\t%%ds = 0x%04x\t%%es = 0x%04x\t%%fs = 0x%04x\n", - regs->r_ss, regs->r_ds, regs->r_es, regs->r_fs); - printf("GDT @ 0x%08x lim 0x%04x\t\tIDT @ 0x%08x lim 0x%04x\n", - regs->r_gdt.dtr_base, regs->r_gdt.dtr_limit, - regs->r_idt.dtr_base, regs->r_idt.dtr_limit); - printf("LDT = 0x%04x\tTASK = 0x%04x\n", - regs->r_ldt, regs->r_tr); - printf("%%cr0 = 0x%08x\t%%cr2 = 0x%08x\t%%cr3 = 0x%08x\n", - regs->r_cr0, regs->r_cr2, regs->r_cr3); - printf("%%cr4 = 0x%08x\n", - regs->r_cr4); - - printf("\nStack (starting at 0x%x):\n", (uint32_t)esp); - for (j = 0; j < stack_lines; j++) { - for (i = 0; i < WORDS_PER_LINE; i++) { - printf("0x%08x", esp[(j * WORDS_PER_LINE) + i]); - if (i < (WORDS_PER_LINE - 1)) - printf(" "); - } - printf("\n"); - } -} - -void -trap(struct i386_machregs *regs) -{ - /* Show registers and stack: [24 lines max (prevents scrolling)] */ - show_regs_and_stack(regs, STACK_LINES); - - if (started_bootfile == 0) - panic("unexpected trap in boot loader\n"); - else - panic("unexpected trap after starting %s\n", bootfile); -} diff --git a/usr/src/psm/stand/boot/i386/common/serial.h b/usr/src/psm/stand/boot/i386/common/serial.h deleted file mode 100644 index d63264fa74..0000000000 --- a/usr/src/psm/stand/boot/i386/common/serial.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1997, Sun Microsystems, Inc. All Rights Reserved. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* ---- ports on 16550 serial chips ---- */ -#define DAT 0 /* ... data */ -#define ICR 1 /* ... intr control reg */ -#define ISR 2 /* ... intr status reg */ -#define LCR 3 /* ... line control reg */ -#define MCR 4 /* ... modem control reg */ -#define LSR 5 /* ... line status reg */ -#define MSR 6 /* ... modem status reg */ -#define DLL 0 /* ... data latch low (used for baud rate) */ -#define DLH 1 /* ... data latch high (ditto) */ -#define FIFOR ISR /* ... fifo write reg */ - -/* ---- convenant macros ---- */ -/* this macro uses the _chario_io_p structure */ -#define INB(a, off) \ - (inb((a) + off)) -#define OUTB(a, off, val) \ - (outb((a)+(off), (char)(val))) - -/* ---- LSR bits ---- */ -#define RCA 0x01 /* ... receive char avail */ -#define XHRE 0x20 /* ... xmit hold buffer empty */ - -/* ---- Modem bits ---- */ -#define DTR 0x01 -#define RTS 0x02 -#define OUT2 0x08 - -#define FIFO_ON 0x01 -#define FIFO_OFF 0x00 -#define FIFORXFLSH 0x02 -#define FIFOTXFLSH 0x04 -#define FIFODMA 0x08 - -/* ---- LCR bits ---- */ -#define STOP1 00 -#define STOP2 0x04 -#define BITS5 0x00 /* 5 bits per char */ -#define BITS6 0x01 /* 6 bits per char */ -#define BITS7 0x02 /* 7 bits per char */ -#define BITS8 0x03 /* 8 bits per char */ - -/* baud rate definitions */ -#define DLAB 0x80 /* divisor latch access bit */ -#define ASY110 1047 /* 110 baud rate for serial console */ -#define ASY150 768 /* 150 baud rate for serial console */ -#define ASY300 384 /* 300 baud rate for serial console */ -#define ASY600 192 /* 600 baud rate for serial console */ -#define ASY1200 96 /* 1200 baud rate for serial console */ -#define ASY2400 48 /* 2400 baud rate for serial console */ -#define ASY4800 24 /* 4800 baud rate for serial console */ -#define ASY9600 12 /* 9600 baud rate for serial console */ -#define ASY19200 6 /* 19200 baud rate for serial console */ -#define ASY38400 3 /* 38400 baud rate for serial console */ -#define ASY57600 2 /* 57600 baud rate for serial console */ -#define ASY115200 1 /* 115200 baud rate for serial console */ diff --git a/usr/src/psm/stand/boot/i386/common/standalloc.c b/usr/src/psm/stand/boot/i386/common/standalloc.c deleted file mode 100644 index 4e8af8667a..0000000000 --- a/usr/src/psm/stand/boot/i386/common/standalloc.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/promif.h> -#include <sys/memlist.h> -#include <sys/bootconf.h> -#include "multiboot.h" -#include "util.h" -#include "standalloc.h" -#include "debug.h" - -#define dprintf if (debug & D_ALLOC) printf - -/* memory lists */ -struct memlist *pinstalledp, *pfreelistp, *vfreelistp, *pbooterp; -struct memlist *ppcimemp, *pramdiskp; - -extern multiboot_info_t *mbi; -extern multiboot_header_t *mbh; -extern int verbosemode; - -extern int map_phys(int, size_t, caddr_t, uint64_t); - -/* scratch memory */ -uint_t magic_phys = MAGIC_PHYS; -uint_t lomem_phys = 0x1000000; /* try not to use memory below 16M */ -uint64_t scratchmem_start, scratchmem_end; -uint64_t ramdisk_start, ramdisk_end; - -static void -memlist_dump(struct memlist *listp) -{ - while (listp) { - dprintf("(0x%x%x, 0x%x%x)", - (int)(listp->address >> 32), (int)listp->address, - (int)(listp->size >> 32), (int)listp->size); - listp = listp->next; - } - dprintf("\n"); -} - -static struct memlist * -memlist_alloc() -{ - return ((struct memlist *)bkmem_alloc(sizeof (struct memlist))); -} - -static void -memlist_free(struct memlist *buf) -{ - bkmem_free(buf, sizeof (struct memlist)); -} - -/* insert in the order of addresses */ -static void -memlist_insert(struct memlist **listp, uint64_t addr, uint64_t size) -{ - struct memlist *entry; - struct memlist *prev = 0, *next; - - /* find the location in list */ - next = *listp; - while (next && next->address < addr) { - prev = next; - next = prev->next; - } - - if (prev == 0) { - entry = memlist_alloc(); - entry->address = addr; - entry->size = size; - entry->next = *listp; - *listp = entry; - return; - } - - /* coalesce entries if possible */ - if (addr == prev->address + prev->size) { - prev->size += size; - } else { - entry = memlist_alloc(); - entry->address = addr; - entry->size = size; - entry->next = next; - prev->next = entry; - } -} - -/* delet memory chunks, assuming list sorted by address */ -static int -memlist_remove(struct memlist **listp, uint64_t addr, uint64_t size) -{ - struct memlist *entry; - struct memlist *prev = 0, *next; - - /* find the location in list */ - next = *listp; - while (next && (next->address + next->size < addr)) { - prev = next; - next = prev->next; - } - - if (next == 0 || (addr < next->address)) { - dprintf("memlist_remove: addr 0x%x%x, size 0x%x%x" - " not contained in list\n", - (int)(addr >> 32), (int)addr, - (int)(size >> 32), (int)size); - memlist_dump(*listp); - return (-1); - } - - if (addr > next->address) { - uint64_t oldsize = next->size; - next->size = addr - next->address; - if ((next->address + oldsize) > (addr + size)) { - entry = memlist_alloc(); - entry->address = addr + size; - entry->size = next->address + oldsize - addr - size; - entry->next = next->next; - next->next = entry; - } - } else if ((next->address + next->size) > (addr + size)) { - /* addr == next->address */ - next->address = addr + size; - next->size -= size; - } else { - /* the entire chunk is deleted */ - if (prev == 0) { - *listp = next->next; - } else { - prev->next = next->next; - } - memlist_free(next); - } - - return (0); -} - -/* - * find and claim a memory chunk of given size, bypassing - * scratch memory + room below 8MB - */ -static uint64_t -memlist_find(struct memlist **listp, uint_t size, int align) -{ - uint_t delta; - uint64_t paddr; - struct memlist *prev = 0, *next; - - /* find the chunk with sufficient size */ - next = *listp; - while (next && - (next->address < lomem_phys || (next->size < size + align - 1))) { - prev = next; - next = prev->next; - } - - if (next == NULL) - return (0); - - paddr = next->address; - delta = (uint_t)paddr & (align - 1); - if (delta) - paddr += align - delta; - (void) memlist_remove(listp, paddr, size); - return (paddr); -} - -static void -memlists_print() -{ - printf("Installed physical memory:\n"); - memlist_dump(pinstalledp); - printf("BIOS reserved physical memory:\n"); - memlist_dump(ppcimemp); - printf("Booter occupied memory (including modules):\n"); - memlist_dump(pbooterp); - printf("Ramdisk memory:\n"); - memlist_dump(pramdiskp); - printf("Available physical memory:\n"); - memlist_dump(pfreelistp); - printf("Available virtual memory:\n"); - memlist_dump(vfreelistp); -} - -void -setup_memlists(void) -{ - int i; - uint64_t address, size; - mb_memory_map_t *mmap; - mb_module_t *mod; - struct memlist *entry; - - /* - * initialize scratch memory so we can call bkmem_alloc - * to get memory for keeping track of memory lists - */ - reset_alloc(); - - /* - * initialize RAM list (pinstalledp) and available pci memory - * PCI memory excludes memory below 1M (realmode) - */ - memlist_insert(&ppcimemp, 0x100000, 0xFFF00000ULL); - for (mmap = (mb_memory_map_t *)mbi->mmap_addr; - (unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length; - mmap = (mb_memory_map_t *)((unsigned long)mmap - + mmap->size + sizeof (mmap->size))) { - address = ((uint64_t)mmap->base_addr_high << 32) + - (uint64_t)mmap->base_addr_low; - size = ((uint64_t)mmap->length_high << 32) + - (uint64_t)mmap->length_low; - - switch (mmap->type) { - case 1: /* RAM */ - memlist_insert(&pinstalledp, address, size); - memlist_insert(&pfreelistp, address, size); - /*FALLTHROUGH*/ - default: /* Take out of available pci memory space */ - (void) memlist_remove(&ppcimemp, address, size); - break; - } - } - - /* - * initialize memory occupied by the booter - * make the boundary page aligned to simplify - * MMU stuff - */ - address = rounddown(mbh->load_addr, PAGESIZE); - size = roundup(mbh->bss_end_addr, PAGESIZE) - - rounddown(mbh->load_addr, PAGESIZE); - memlist_insert(&pbooterp, address, size); - - /* where the modules are in memory */ - for (i = 0, mod = (mb_module_t *)mbi->mods_addr; - i < mbi->mods_count; i++, mod++) { - /* round up to page boundaries */ - address = rounddown(mod->mod_start, PAGESIZE); - size = roundup(mod->mod_end, PAGESIZE) - - rounddown(mod->mod_start, PAGESIZE); - - /* assume first one is ramdisk */ - if (ramdisk_end == 0) { - ramdisk_start = mod->mod_start; - ramdisk_end = mod->mod_end; - if (verbosemode) { - printf("ramdisk is at 0x%llx-0x%llx\n", - ramdisk_start, ramdisk_end); - } - memlist_insert(&pramdiskp, address, size); - } else { - memlist_insert(&pbooterp, address, size); - } - } - - /* delete booter memory from pfreelistp */ - entry = pbooterp; - while (entry) { - address = entry->address; - size = entry->size; - (void) memlist_remove(&pfreelistp, address, size); - entry = entry->next; - } - - /* delete ramdisk memory */ - entry = pramdiskp; - while (entry) { - address = entry->address; - size = entry->size; - (void) memlist_remove(&pfreelistp, address, size); - entry = entry->next; - } - - /* - * initialize free virtual memory list - * start withe the entire range - * delete booter memory - */ - memlist_insert(&vfreelistp, 0, 0x100000000LL); - entry = pbooterp; - while (entry) { - address = entry->address; - size = entry->size; - (void) memlist_remove(&vfreelistp, address, size); - entry = entry->next; - } - - if (debug & D_ALLOC) - memlists_print(); -} - -/* resource allocate routines */ -void -reset_alloc(void) -{ - if (verbosemode) - printf("initialize scratch memory \n"); - - /* reclaim existing scratch memory */ - if (scratchmem_end > scratchmem_start) { - memlist_insert(&pfreelistp, scratchmem_start, - (uint64_t)magic_phys - scratchmem_start); - } - - /* start allocating at 1MB */ - scratchmem_end = scratchmem_start = 0x100000; -} - -/* - * allocate memory with an identical physical and virtual address - */ -caddr_t -idmap_mem(uint32_t virthint, size_t bytes, int align) -{ - caddr_t addr = 0; - - /* sanity checks */ - if (bytes == 0) - return ((caddr_t)0); - - if (virthint == 0) { - addr = (caddr_t)(uintptr_t) - memlist_find(&pfreelistp, bytes, align); - } else if (memlist_remove( - &pfreelistp, (uint64_t)virthint, (uint64_t)bytes) == 0) { - addr = (caddr_t)virthint; - } - - if (addr == 0) { - printf("idmap_mem: failed to find phys 0x%lx bytes at 0x%x\n", - bytes, virthint); - return (0); - } - - /* - * For any piece of low (< kernelbase) physical memory, we - * either map it 1:1 or map it above kernelbase. Hence, the - * corresponding virtual memory is always available by design. - */ - if (memlist_remove(&vfreelistp, - (uint64_t)(uintptr_t)addr, (uint64_t)bytes) != 0) { - printf("idmap_mem: failed to find virtual " - "0x%lx bytes at 0x%p\n", bytes, (void *)addr); - (void) memlist_insert(&pfreelistp, (uint64_t)(uintptr_t)addr, - (uint64_t)bytes); - return (0); - } - - if (map_phys(0, bytes, addr, (uint64_t)(uintptr_t)addr) == -1) { - printf("idmap_mem: failed to 1:1 map 0x%lx bytes at 0x%p\n", - bytes, (void *)addr); - (void) memlist_insert(&pfreelistp, (uint64_t)(uintptr_t)addr, - (uint64_t)bytes); - (void) memlist_insert(&vfreelistp, (uint64_t)(uintptr_t)addr, - (uint64_t)bytes); - return (0); - } - - return (addr); -} - -/* - * allocate memory with a physical mapping - */ -/*ARGSUSED*/ -caddr_t -phys_alloc_mem(size_t bytes, int align) -{ - /* sanity checks */ - if (bytes == 0) - return ((caddr_t)0); - - return ((caddr_t)(uintptr_t)memlist_find(&pfreelistp, bytes, align)); -} - -/*ARGSUSED*/ -caddr_t -resalloc(enum RESOURCES type, size_t bytes, caddr_t virthint, int align) -{ - uint_t delta; - caddr_t vaddr; - uint64_t paddr; - - /* sanity checks */ - if (bytes == 0) - return ((caddr_t)0); - - if (scratchmem_end == 0) - prom_panic("scratch memory uninitialized\n"); - - switch (type) { - case RES_BOOTSCRATCH: - - /* scratch memory */ - vaddr = (caddr_t)(uintptr_t)scratchmem_end; - bytes = roundup(bytes, PAGESIZE); - scratchmem_end += bytes; - if (scratchmem_end > magic_phys) - prom_panic("scratch memory overflow!"); - return (vaddr); - /*NOTREACHED*/ - - case RES_CHILDVIRT: - - /* program memory */ - - delta = (uint_t)virthint & (PAGESIZE - 1); - if (delta) - goto fail; /* not page aligned */ - - vaddr = virthint - delta; - bytes += delta; - bytes = roundup(bytes, PAGESIZE); - - if (memlist_remove(&vfreelistp, - (uint64_t)(uintptr_t)vaddr, (uint64_t)bytes)) - goto fail; /* virtual memory not available */ - if (align == 0) - align = 1; - paddr = memlist_find(&pfreelistp, bytes, align); - if (paddr == -1) - goto fail; /* out of physical memory */ - if (map_phys(0, bytes, vaddr, paddr) == -1) - goto fail; - return (vaddr); - /*NOTREACHED*/ - } - -fail: - dprintf("resalloc of 0x%lx bytes at 0x%p failed", - bytes, (void *)virthint); - return (0); -} - -void -resfree(caddr_t addr, size_t bytes) -{ - /* scratch memory is freed one one shot */ - if ((uint_t)addr < magic_phys) - return; - dprintf("resfree: 0x%p 0x%lx not implemented\n", - (void *)addr, bytes); -} - -int -get_progmemory(caddr_t vaddr, size_t size, int align) -{ - uint_t n = (uint_t)vaddr & (PAGESIZE - 1); - - if (n) { - vaddr -= n; - size += n; - } - - if (resalloc(RES_CHILDVIRT, size, vaddr, align) != vaddr) - return (-1); - return (0); -} diff --git a/usr/src/psm/stand/boot/i386/common/standalloc.h b/usr/src/psm/stand/boot/i386/common/standalloc.h deleted file mode 100644 index ee99de104b..0000000000 --- a/usr/src/psm/stand/boot/i386/common/standalloc.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_STANDALLOC_H -#define _SYS_STANDALLOC_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/saio.h> - -#define NULL 0 -#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) -#define rounddown(x, y) (((x)/(y))*(y)) - -/* backing resources for memory allocation */ -caddr_t resalloc(enum RESOURCES type, size_t, caddr_t, int); -void resfree(caddr_t, size_t); -void reset_alloc(void); - -/* memory allocation */ -void *bkmem_alloc(size_t); -void *bkmem_zalloc(size_t); -void bkmem_free(void *, size_t); -int get_progmemory(caddr_t, size_t, int); -void *vmx_zalloc_identity(size_t); - -/* - * BOPF_X86_ALLOC_IDMAP: identical virtual/physical address - * BOPF_X86_ALLOC_PHYS: physical address - */ -caddr_t idmap_mem(uint32_t, size_t, int); -caddr_t phys_alloc_mem(size_t, int); - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_STANDALLOC_H */ diff --git a/usr/src/psm/stand/boot/i386/common/util.h b/usr/src/psm/stand/boot/i386/common/util.h deleted file mode 100644 index 0aa18da2a6..0000000000 --- a/usr/src/psm/stand/boot/i386/common/util.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _UTIL_H -#define _UTIL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/varargs.h> -#include <sys/promif.h> -#include "asm/sunddi.h" - -/* - * This header file contains most of the libc-like interfaces - */ - -#ifdef __cplusplus -extern "C" { -#endif - -extern uchar_t inb(int); -extern void outb(int, uint8_t); -extern void sync_instruction_memory(caddr_t v, size_t len); - -extern void bzero(void *, size_t); -extern void bcopy(const void *, void *, size_t); -extern size_t strlen(const char *); -extern int strcmp(const char *, const char *); -extern int strncmp(const char *, const char *, size_t); -extern char *strcat(char *, const char *); -extern char *strcpy(char *, const char *); -extern char *strrchr(const char *, int); -extern char *strstr(const char *, const char *); - -extern void prom_init(char *, void *); -extern int openfile(char *, char *); -extern int close(int); - -extern void printf(const char *, ...); - -extern void reset(void) __NORETURN; -extern void efi_reset(void) __NORETURN; -extern void prom_panic(char *fmt) __NORETURN; -extern void panic(const char *fmt, ...) __NORETURN; - -#ifdef __cplusplus -} -#endif - -#endif /* _UTIL_H */ diff --git a/usr/src/psm/stand/boot/i386/common/vgaprobe.c b/usr/src/psm/stand/boot/i386/common/vgaprobe.c deleted file mode 100644 index d93df5a3ac..0000000000 --- a/usr/src/psm/stand/boot/i386/common/vgaprobe.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/controlregs.h> -#include <sys/bootconf.h> -#include <sys/bootvfs.h> -#include <sys/psw.h> -#include "multiboot.h" -#include "bootprop.h" -#include "biosint.h" -#include "machine.h" -#include "standalloc.h" -#include "console.h" -#include "util.h" -#include "debug.h" - -#define FP_SEG(fp) ((((unsigned long)(fp)) >> 16) & 0xffff) -#define FP_OFF(fp) (((unsigned long)(fp)) & 0xffff) - -#define VESABIOS_SUPP_FUNC 0x4f -#define VESABIOS_DISPLAY_ID_EXT 0x15 - -#pragma pack(1) -/* - * Structure returned by monitors that support VESA DDC - */ -struct EDIFinfo { - unsigned char hdr[8]; - unsigned short mfname; /* EISA style compressed id */ - unsigned short pid; - unsigned long serialno; - char mfweek; - unsigned char mfyear; - unsigned char edidver; - unsigned char edidrev; - unsigned char vidindef; - unsigned char maxHimagesz; /* cm */ - unsigned char maxVimagesz; /* cm */ - unsigned char displayxferchar; - unsigned char DPMSfeat; - unsigned char RGlowbits; - unsigned char BWlowbits; - unsigned char redx; - unsigned char redy; - unsigned char greenx; - unsigned char greeny; - unsigned char bluex; - unsigned char bluey; - unsigned char whitex; - unsigned char whitey; - unsigned char esttimings1; - unsigned char esttimings2; - unsigned char rsvdtimings; - short stdtimingid1; - short stdtimingid2; - short stdtimingid3; - short stdtimingid4; - short stdtimingid5; - short stdtimingid6; - short stdtimingid7; - short stdtimingid8; - unsigned char dettimingdesc1[18]; - unsigned char dettimingdesc2[18]; - unsigned char dettimingdesc3[18]; - unsigned char dettimingdesc4[18]; - unsigned char extflg; - unsigned char chksum; -}; -#pragma pack() - -/* - * Address at which we can read/write a structure - * in common with the bios. - * - * Current memory layout: - * 1mb: multiboot - * 0x6000: our scratch memory - * 0x5000: stack, grows downward - * 0x2000: biosint - * 0x1000: bios - */ -#define LOMEM_SCRATCH_ADDR 0x6000 - - -#define dprintf if (debug & D_BIOS) printf - -int (*bios_doint)(int, struct int_pb *); - - -static const char hextab[] = "0123456789ABCDEF"; - -static void -DecompressName(unsigned long id, char *np) -{ - /* - * Expand an EISA device name - * - * This converts a 32-bit EISA device "id" to a - * 7-byte ASCII device name, which is stored at "np". - */ - - *np++ = '@' + ((id >> 2) & 0x1F); - *np++ = '@' + ((id << 3) & 0x18) + ((id >> 13) & 0x07); - *np++ = '@' + ((id >> 8) & 0x1F); - *np++ = hextab[(id >> 20) & 0x0F]; - *np++ = hextab[(id >> 16) & 0x0F]; - *np++ = hextab[(id >> 28) & 0x0F]; - *np++ = hextab[(id >> 24) & 0x0F]; - *np = 0; -} - -void -vga_probe(void) -{ - int ret; - struct int_pb ic = {0}; - char *fp; - char name[8]; - struct EDIFinfo *edifp = (struct EDIFinfo *)LOMEM_SCRATCH_ADDR; - - /* - * See what level of VESA DDC is supported (if any) - */ - ic.ax = (VESABIOS_SUPP_FUNC << 8) | VESABIOS_DISPLAY_ID_EXT; - ic.bx = 0x00; /* Report DDC Capcbilities */ - ic.cx = 0; - ic.dx = 0; - ic.es = 0; - ic.dx = 0; - ret = bios_doint(0x10, &ic); - dprintf("vga probe report ddc: ret=%0x ax=0x%x dx=0x%x\n", - ret, ic.ax, ic.dx); - if (!(ret & PS_C) && (ic.ax & 0xff) == VESABIOS_SUPP_FUNC) { - /* - * BIOS supports VBE/DDC extension - */ - if (ic.bx & 0x03) { /* DDC1 or DDC2 supported */ - unsigned long mfn, compid; - - /* - * Get VESA DDC EDIF info - */ - edifp->edidver = 0; - ic.ax = (VESABIOS_SUPP_FUNC << 8) | - VESABIOS_DISPLAY_ID_EXT; - ic.bx = 0x01; /* Read EDID */ - ic.cx = 0; - ic.dx = 0; - fp = (char *)edifp; - ic.es = FP_SEG(fp); - ic.di = FP_OFF(fp); - dprintf("addr 0x%p, seg 0x%lx, off 0x%lx\n", - (void *)fp, FP_SEG(fp), FP_OFF(fp)); - - ret = bios_doint(0x10, &ic); - dprintf( - "vga probe read edid: ret=%0x ax=0x%x dx=0x%x\n", - ret, ic.ax, ic.dx); - if (!(ret & PS_C) && edifp->edidver != 0) { - dprintf("display-edif-block: len %d\n", - sizeof (struct EDIFinfo)); - (void) bsetprop(NULL, "display-edif-block", - edifp, sizeof (struct EDIFinfo)); - /* - * Set edif id as a property - */ - mfn = (long)edifp->mfname; - compid = (long)edifp->pid << 24 | mfn | - ((long)(edifp->pid & 0xff00) << 8); - DecompressName(compid, name); - dprintf("display-edif-id: %s\n", name); - (void) bsetprop(NULL, "display-edif-id", - name, strlen(name) + 1); - } - } - } -} diff --git a/usr/src/psm/stand/boot/i386/i86pc/Makefile b/usr/src/psm/stand/boot/i386/i86pc/Makefile deleted file mode 100644 index 672e381b2c..0000000000 --- a/usr/src/psm/stand/boot/i386/i86pc/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# - -TOPDIR = ../../../../.. -PLATFORM = i86pc -KARCH = $(PLATFORM) -ARCHVERS = -ARCHOPTS = -Di386 -D__i386 -DI386BOOT -DBOOTAMD64 -D_ELF64_SUPPORT -ARCHOPTS += -DMULTIBOOT - -PLAT_C_SRC = -ARCH_C_SRC = -ARCH_S_SRC = cpu_id.s idttab.s samuldiv64.s -START_S_SRC = asm.s -BIOS_S_SRC = biosint.s - -TOOLSRC = $(TOPDIR)/tools - -include ../Makefile.com - -$(ROOT_PSM_UNIBOOT):= OWNER= root -$(ROOT_PSM_UNIBOOT):= GROUP= sys -$(ROOT_PSM_UNIBOOT):= FILEMODE= 755 - -$(ROOT_PSM_BIOSINT):= OWNER= root -$(ROOT_PSM_BIOSINT):= GROUP= sys -$(ROOT_PSM_BIOSINT):= FILEMODE= 755 diff --git a/usr/src/psm/stand/boot/i386/i86pc/asm.s b/usr/src/psm/stand/boot/i386/i86pc/asm.s deleted file mode 100644 index 27dbb67aac..0000000000 --- a/usr/src/psm/stand/boot/i386/i86pc/asm.s +++ /dev/null @@ -1,502 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* Copyright 2006 Sun Microsystems, Inc. All rights reserved. */ -/* Use is subject to license terms. */ - -#if defined(lint) - -#include <sys/types.h> -#include <sys/bootconf.h> - -extern void printf(const char *, ...); - -uint_t bpd_loc; -struct bootops *bop; - -void start(void) {} -void start_paging(void) { return; } -void halt(char *msg) { printf("%s", msg); } -/*ARGSUSED*/ -void exitto(int (*entrypoint)()) {} -void reset(void) {} -void efi_reset(void) {} - -/* lint for inline functions in i86.il */ -/*ARGSUSED*/ -uint8_t inb(int port) { return (*(uint8_t *)port); } -uint16_t inw(int port) { return (*(uint16_t *)port); } -uint32_t inl(int port) { return (*(uint32_t *)port); } -void outb(int port, uint8_t v) { *(uint8_t *)port = v; } -void outw(int port, uint16_t v) { *(uint16_t *)port = v; } -void outl(int port, uint32_t v) { *(uint32_t *)port = v; } - -#else - -.ident "%Z%%M% %I% %E% SMI" - -#include <sys/asm_linkage.h> -#include <sys/controlregs.h> -#include <sys/segment.h> -#include <assym.h> -#include "../common/multiboot.h" - -.file "asm.s" -.text - -.globl _start -_start: - jmp multiboot_entry - -/* - * The following header must be present within the first 8K of - * the binary, according to the Multiboot Specification - */ -.align 4 - -multiboot_header: - .long MB_HEADER_MAGIC / multiboot magic - .long MB_HEADER_FLAGS / flags - .long MB_HEADER_CHECKSUM / checksum - .long multiboot_header / header address - .long _start / load start addr - .long _edata / load end addr - .long _end / bss end - .long multiboot_entry / entry addr - -/* - * Start from where GRUB left off. The processor state is - * as defined in the Multiboot Specification. We start with: - * - initialize the stack, "stack" is declared at the end of file - * - push register contents to stack to pass multiboot info - * - initialize GDT and (a dummy) IDT - * - call main() to load the kernel - */ -multiboot_entry: - movl $[stack + STACK_SIZE], %esp - pushl $0 / reset flags - popf - - push $0 / terminate debugger - push $0 - movl %esp, %ebp - - movl $[multiboot_header], %ecx - pushl %ecx / multiboot header - pushl %ebx / multiboot info - pushl %eax / multiboot magic - - lgdt gdtdesc / load gdt - mov $0x08, %eax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - ljmp $0x10, $newgdt -newgdt: - - movl $slbidt, %eax / load idt - movl $0x7ff, %ecx - call munge_table - lidt IDTptr - - call main / invoke the kernel - hlt / shouldn't get here - -/ help function -.globl halt -halt: - pushl $halt_message / halt - call printf / defined in kernel -loop1: - hlt - jmp loop1 - -halt_message: - .string "Halted." - -/ turn on paging - ENTRY(start_paging) - movl bpd_loc, %eax - movl %eax, %cr3 - - movl %cr0, %eax - orl $[CR0_PG|CR0_PE], %eax - movl %eax, %cr0 - - jmp page_flush / flush the prefetch queue -page_flush: - nop - nop - ret - SET_SIZE(start_paging) - -/ exitto 32-bit kernel - ENTRY(exitto) - push %ebp / save stack - mov %esp, %ebp - pushal / protect secondary boot - - movl %esp, %eax - movl %eax, save_esp2 - - movl $elfbootvec, %eax - pushl (%eax) - - movl $bop, %eax - movl (%eax), %ebx - pushl %ebx - - pushl $0 / no debug vector - - movl $sysp, %eax - movl (%eax), %ecx - pushl %ecx - - movl 8(%ebp), %eax - call *%eax / jump to the kernel - - movl save_esp2, %eax - movl %eax, %esp - - popal - pop %ebp / restore frame pointer - ret - SET_SIZE(exitto) - -/********************************************************************** */ -/**/ -/* munge_table: */ -/* This procedure will 'munge' a descriptor table to */ -/* change it from initialized format to runtime format. */ -/**/ -/* Assumes: */ -/* %eax -- contains the base address of table. */ -/* %ecx -- contains size of table. */ -/**/ -/* ********************************************************************* */ - ENTRY(munge_table) - - addl %eax, %ecx /* compute end of IDT array */ - movl %eax, %esi /* beginning of IDT */ - -moretable: - cmpl %esi, %ecx - jl donetable /* Have we done every descriptor?? */ - - movl %esi, %ebx /*long-vector/*short-selector/*char-rsrvd/*char- -type */ - - movb 7(%ebx), %al /* Find the byte containing the type field */ - testb $0x10, %al /* See if this descriptor is a segment */ - jne notagate - testb $0x04, %al /* See if this destriptor is a gate */ - je notagate - /* Rearrange a gate descriptor. */ - movl 4(%ebx), %edx /* Selector, type lifted out. */ - movw 2(%ebx), %ax /* Grab Offset 16..31 */ - movl %edx, 2(%ebx) /* Put back Selector, type */ - movw %ax, 6(%ebx) /* Offset 16..31 now in right place */ - jmp descdone - -notagate: /* Rearrange a non gate descriptor. */ - movw 4(%ebx), %dx /* Limit 0..15 lifted out */ - movw 6(%ebx), %ax /* acc1, acc2 lifted out */ - movb %ah, 5(%ebx) /* acc2 put back */ - movw 2(%ebx), %ax /* 16-23, 24-31 picked up */ - movb %al, 7(%ebx) /* 24-31 put back */ - movb %ah, 4(%ebx) /* 16-23 put back */ - movw (%ebx), %ax /* base 0-15 picked up */ - movw %ax, 2(%ebx) /* base 0-15 put back */ - movw %dx, (%ebx) /* lim 0-15 put back */ - -descdone: - addl $8, %esi /* Go for the next descriptor */ - jmp moretable - -donetable: - ret - SET_SIZE(munge_table) - -/ reset machine -/ Resetting by Triple-Fault only makes emulators like VMWare warn -/ the user each time a reset is performed. Here, we try a number -/ of techniques and only fall back on triple faulting the CPU -/ under extreme circumstances. - - ENTRY(reset) - / - / Try the classic keyboard controller-triggered reset. - / - movw $0x64, %dx - movb $0xfe, %al - outb (%dx) - - / Wait up to 500 ms for the keyboard controller to pull the reset line - pushl $500 - call mdelay - addl $4, %esp - - / - / Try port 0x92 fast reset - / - movw $0x92, %dx - inb (%dx) - cmpb $0xff, %al / If port's not there, we should get back 0xFF - je 1f - testb $1, %al / If bit 0 - jz 2f / is clear, jump to perform the reset - andb $0xfe, %al / otherwise, - outb (%dx) / clear bit 0 first, then -2: - orb $1, %al / Set bit 0 - outb (%dx) / and reset the system -1: - - / Wait up to 500 ms for the port 92 reset method to reset the CPU - pushl $500 - call mdelay - addl $4, %esp - - / Try the PCI (soft) reset vector (should work on all modern systems, - / but has been shown to cause problems on 450NX systems, and some newer - / systems (e.g. ATI IXP400-equipped systems)) - / When resetting via this method, 2 writes are required. The first - / targets bit 1 (0=hard reset without power cycle, 1=hard reset with - / power cycle). - / The reset occurs on the second write, during bit 2's transition from - / 0->1. - movw $0xcf9, %dx - movb $0x2, %al / Reset mode = hard, no power cycle - outb (%dx) - movb $0x6, %al - outb (%dx) - - / Wait up to 500 ms for the port cf9 reset method to reset the CPU - pushl $500 - call mdelay - addl $4, %esp - - / - / port 0xcf9 failed also. Last-ditch effort is to - / triple-fault the CPU. - / - ENTRY(efi_reset) - movw $0, IDTlimit / generate faulty table - lidt IDTptr / load faulty table - int $10 / trigger an interrupt - - cli - hlt / Wait forever - /*NOTREACHED*/ - SET_SIZE(efi_reset) - SET_SIZE(reset) - - ENTRY(_cmntrap) - / - / Stack looks like the following on entry: - / - / EFLAGS %esp + SIZEOF_i386_machregs + 16 - / CS %esp + SIZEOF_i386_machregs + 12 - / EIP %esp + SIZEOF_i386_machregs + 8 - / ERRCODE %esp + SIZEOF_i386_machregs + 4 - / TRAPNO %esp + SIZEOF_i386_machregs - / STRUCT MACHREGS %esp + 0 - / - subl $SIZEOF_i386_machregs, %esp - - movl %eax, i386_REG_EAX(%esp) - movl %ebx, i386_REG_EBX(%esp) - movl %ecx, i386_REG_ECX(%esp) - movl %edx, i386_REG_EDX(%esp) - movl %edi, i386_REG_EDI(%esp) - movl %esi, i386_REG_ESI(%esp) - movl %ebp, i386_REG_EBP(%esp) - - / Copy in the saved EFLAGS - leal SIZEOF_i386_machregs(%esp), %eax - addl $16, %eax - movl (%eax), %eax - movl %eax, i386_REG_EFL(%esp) - - / Copy in the saved CS - leal SIZEOF_i386_machregs(%esp), %eax - addl $12, %eax - movl (%eax), %eax - movl %eax, i386_REG_CS(%esp) - - / Copy in the saved EIP - leal SIZEOF_i386_machregs(%esp), %eax - addl $8, %eax - movl (%eax), %eax - movl %eax, i386_REG_EIP(%esp) - - / Copy in the saved ERRCODE - leal SIZEOF_i386_machregs(%esp), %eax - addl $4, %eax - movl (%eax), %eax - movl %eax, i386_REG_ERR(%esp) - - / Copy in the saved TRAPNO - leal SIZEOF_i386_machregs(%esp), %eax - movl (%eax), %eax - movl %eax, i386_REG_TRAPNO(%esp) - - movl %esp, i386_REG_ESP(%esp) - movl %esp, i386_REG_UESP(%esp) - - / - / The original %esp is +SIZEOF_i386_machregs - / - addl $SIZEOF_i386_machregs, i386_REG_ESP(%esp) - addl $SIZEOF_i386_machregs, i386_REG_UESP(%esp) - - / Save the segment registers - xorl %eax, %eax - - movw %ss, %ax - movw $0, _CONST(i386_REG_SS + 2)(%esp) - movl %eax, i386_REG_SS(%esp) - movw %ds, %ax - movw $0, _CONST(i386_REG_DS + 2)(%esp) - movl %eax, i386_REG_DS(%esp) - movw %es, %ax - movw $0, _CONST(i386_REG_ES + 2)(%esp) - movl %eax, i386_REG_ES(%esp) - movw %fs, %ax - movw $0, _CONST(i386_REG_FS + 2)(%esp) - movl %eax, i386_REG_FS(%esp) - movw %gs, %ax - movw $0, _CONST(i386_REG_GS + 2)(%esp) - movl %eax, i386_REG_GS(%esp) - - / Save the control registers - movl %cr0, %eax - movl %eax, i386_REG_CR0(%esp) - movl %cr2, %eax - movl %eax, i386_REG_CR2(%esp) - movl %cr3, %eax - movl %eax, i386_REG_CR3(%esp) - movl %cr4, %eax - movl %eax, i386_REG_CR4(%esp) - - / Save the task, interrupt, gdt, ldt registers - movw $0, _CONST(i386_REG_TR + 2)(%esp) - str i386_REG_TR(%esp) - sidt i386_REG_IDT(%esp) - sgdt i386_REG_GDT(%esp) - movw $0, _CONST(i386_REG_LDT + 2)(%esp) - sldt i386_REG_LDT(%esp) - - pushl %esp - call trap - addl $4, %esp - - addl $SIZEOF_i386_machregs, %esp - iret - SET_SIZE(_cmntrap) - -/ Data definitions -.align 4 -.globl bpd_loc -bpd_loc: - .long 0 -.globl save_esp2 -save_esp2: - .long 0 -.globl save_esp -save_esp: - .long 0 -.globl bop -bop: - .long 0 -IDTptr: -IDTlimit: - .value 0x7ff -IDTbase: - .long slbidt - -.align 4 -gdt_start: - .long 0 - .long 0 - -flatdesc: / offset = 0x08 (GDT_BOOTFLAT << 3) - - .value 0xFFFF / segment limit 0..15 - .value 0x0000 / segment base 0..15 - .byte 0x0 / segment base 16..23; set for 0K - .byte 0x92 / flags; A=0, Type=001, DPL=00, P=1 - / Present expand down - .byte 0xCF / flags; Limit (16..19)=1111, AVL=0, G=1, B=1 - .byte 0x0 / segment base 24..32 - -codedesc: / offset = 0x10 (GDT_CODESEL << 3) - - .value 0xFFFF / segment limit 0..15 - .value 0x0000 / segment base 0..15 - .byte 0x0 / segment base 16..23; set for 0k - .byte 0x9E / flags; A=0, Type=111, DPL=00, P=1 - .byte 0xCF / flags; Limit (16..19)=1111, AVL=0, G=1, D=1 - .byte 0x0 / segment base 24..32 - -code16desc: / offset = 0x18 - - .value 0xFFFF / segment limit 0..15 - .value 0x0000 / segment base 0..15 - .byte 0x0 / segment base 16..23; set for 0k - .byte 0x9E / flags; A=0, Type=111, DPL=00, P=1 - .byte 0x0F / flags; Limit (16..19)=1111, AVL=0, G=0, D=0 - .byte 0x0 / segment base 24..32 - -datadesc: / offset = 0x20 - - .value 0xFFFF / segment limit 0..15 - .value 0x0000 / segment base 0..15 - .byte 0x0 / segment base 16..23; set for 0K - .byte 0x92 / flags; A=0, Type=001, DPL=00, P=1 - / Present expand down - .byte 0x4F / flags; Limit (16..19)=1111, AVL=0, G=1, B=1 - .byte 0x0 / segment base 24..32 - -dummy_entries: - .long 0 / 0x28 - .long 0 - .long 0 / 0x30 - .long 0 - -gsdesc: / 0x38 - for kmdb - .value 0 - .value 0 - .byte 0 - .byte 0x92 / flags; A=0, Type=001, DPL=00, P=1 - .byte 0xC0 / flags; Limit (16..19)=0000, AVL=0, G=1, B=1 - .byte 0 - -gdt_end: - -gdtdesc: - .value gdt_end - gdt_start - .long gdt_start - -.comm stack, STACK_SIZE / stack area - -#endif diff --git a/usr/src/psm/stand/boot/i386/i86pc/biosint.s b/usr/src/psm/stand/boot/i386/i86pc/biosint.s deleted file mode 100644 index dd5326c9e5..0000000000 --- a/usr/src/psm/stand/boot/i386/i86pc/biosint.s +++ /dev/null @@ -1,341 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/asm_linkage.h> - -/* - * biosint.s - installed by kernel to make bios calls - * - * The kernel jumps here from protected mode to make a bios service call. - * Calling syntax: bios_doint(int intnum, struct int_pb *ic) - */ - .globl _start -_start: - pushl %ebp - movl %esp, %ebp - - / Save segment registers of caller. - movw %cs, call_cs - movw %ds, call_ds - movw %es, call_es - movw %fs, call_fs - movw %gs, call_gs - movw %ss, call_ss - movl %esp, call_esp - movl %esi, call_esi - movl %ebx, call_ebx - movl %ecx, call_ecx - movl %edx, call_edx - movl %edi, call_edi - / - / We need to save cr0 here and restore it after we return - / from BIOS call to avoid unexpectedly modification to cr0 - / by the buggy firmware of some storage HBAs - / - movl %cr0, %eax - movl %eax, call_cr0 - - / switch stack to 0x5000 - movl $0x5000, %eax - movl %eax, %esp - jmp donelowstack -donelowstack: - - / copy args from high memory to low memory - pushl 12(%ebp) - pushl 8(%ebp) - call copyin_args - addl $8, %esp - - / insert proper interrupt for later. - movl ic_int, %eax - movb %al, newintcode+1 - - / Jump here for P5 94 byte instruction prefetch queue - jmp qflush1 -qflush1: - - / call print_regs - - / Switch interrupt descriptor tables. - cli - sidt kernIDTptr - lidt bioIDTptr - - / Save global descriptor table - sgdt kernGDTptr - - call goreal - -/ -/ NOW in REAL MODE -/ - / Clear the upper (extended) half of all registers. - / Having stray high bits on causes strange - / and unpredictable failures to occur in real mode. - / - D16 xorl %eax, %eax - A16 movw ic_ds, %ax - push %eax / save for later - D16 A16 movw ic_ax, %ax - D16 xorl %ebx, %ebx - A16 mov ic_bx, %ebx - D16 xorl %ecx, %ecx - A16 mov ic_cx, %ecx - D16 xorl %edx, %edx - A16 mov ic_dx, %edx - D16 xorl %ebp, %ebp - A16 mov ic_bp, %ebp - D16 xorl %edi,%edi - A16 mov ic_di, %edi - D16 xorl %esi,%esi - A16 mov ic_si, %esi - A16 movw ic_es, %es - - sti - A16 pop %ds / set effective ds -newintcode: - int $0x10 / do BIOS call - cli - pushf / save carry for later - - / save results of the BIOS call - / - A16 movw %ax, ic_ax - A16 movw %bx, ic_bx - A16 movw %cx, ic_cx - A16 movw %dx, ic_dx - A16 movw %bp, ic_bp - A16 movw %si, ic_si - A16 movw %di, ic_di - A16 movw %ds, ic_ds / real mode - stack 2-bytes word - A16 movw %es, ic_es - - D16 movw %cs, %ax - movw %ax, %ds / restore entry ds, es - movw %ax, %es - - D16 call goprot / protect mode - -/ -/ NOW back in PROTECTED MODE. -/ - / copy results to caller's location - movl call_esp, %eax - pushl 12(%eax) - call copyout_args - addl $4, %esp - - xorl %eax, %eax / initialize return to zero - popw %ax / get eflags - - / Interrupt descriptor table - lidt kernIDTptr - - / Returned from BIOS call, restore cr0 here - movl call_cr0, %edx - movl %edx, %cr0 - movl call_edx, %edx - movl call_ecx, %ecx - movl call_ebx, %ebx - movl call_edi, %edi - movl call_esi, %esi - - / switch back to caller's stack - movl call_esp, %esp - popl %ebp - ret - -/ ---------------------------------------------------- -/ Enter real mode. -/ -/ Real mode GDT descriptors are always present as code 0x18, data 0x20 -/ - .globl goreal -goreal: - - / Transfer control to a 16 bit code segment - / This relies on knowledge of kernel's GDT - ljmp $0x18, $set16cs -set16cs: - - / need to have all segment regs sane - / before we can enter real mode - D16 movl $0x20, %eax - movw %ax, %es - movw %ax, %ds - movw %ax, %fs - movw %ax, %gs - - / clear the protection and paging bits - / jump should clear prefetch q - mov %cr0, %eax - D16 and $0x7ffffffe, %eax - mov %eax, %cr0 - - / Do a long jump here to establish %cs in real mode. - / It appears that this has to be a ljmp as opposed to - / a lret probably due to the way Intel fixed errata #25 - / on the A2 step. This leads to self modifying code. - - ljmp $0x0, $restorecs -restorecs: - / flush tlb - mov %cr3, %eax - mov %eax, %cr3 - - / we are loading in first 64K, so all segment reg should be zero - movw %cs, %ax - movw %ax, %ss - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - D16 ret - -/ ---------------------------------------------------- -/ Enter protected mode. -/ - .globl goprot -goprot: - - / Workaround for BIOSes that mess with GDT during INT call without - / restoring original value on the way back. Hence restore it here. - - D16 A16 lgdt kernGDTptr - - D16 popl %ebx / get return %eip, for later use - - / set protect mode and page mode - mov %cr0, %eax - D16 A16 orl $0x80000001, %eax - mov %eax, %cr0 - - jmp qflush2 / flush the prefetch queue -qflush2: - - / Restore caller's segment registers. - / Still in 16-bit mode till %cs is restored - A16 movw call_ds, %ds - A16 movw call_es, %es - A16 movw call_fs, %fs - A16 movw call_gs, %gs - A16 movw call_ss, %ss - - / Now, set up %cs by fiddling with the return stack and doing an lret - - D16 A16 movw call_cs, %ax / push %cs - D16 pushl %eax - D16 pushl %ebx / push %eip - D16 lret - -/ Data definitions - .align 4 -bioIDTptr: -bioIDTlimit: - .value 0x3ff -bioIDTbase: - .long 0 - -kernGDTptr: -kernGDTlimit: - .value 0 -kernGDTbase: - .long 0 - -kernIDTptr: -kernIDTlimit: - .value 0 -kernIDTbase: - .long 0 - -/ BIOS int call arguments -.globl ic_int -ic_int: - .long 0 -.globl ic_ax -ic_ax: - .value 0 -.globl ic_bx -ic_bx: - .value 0 -.globl ic_cx -ic_cx: - .value 0 -.globl ic_dx -ic_dx: - .value 0 -.globl ic_bp -ic_bp: - .value 0 -.globl ic_si -ic_si: - .value 0 -.globl ic_di -ic_di: - .value 0 -.globl ic_ds -ic_ds: - .value 0 -.globl ic_es -ic_es: - .value 0 - -/ Caller's registers -.globl call_cs -call_cs: - .value 0 -call_ds: - .value 0 -call_es: - .value 0 -call_fs: - .value 0 -call_gs: - .value 0 -.globl call_ss -call_ss: - .value 0 -.globl call_cr0 -call_cr0: - .long 0 -.globl call_esp -call_esp: - .long 0 -call_ebp: - .long 0 -call_esi: - .long 0 -call_edi: - .long 0 -call_ebx: - .long 0 -call_ecx: - .long 0 -call_edx: - .long 0 diff --git a/usr/src/psm/stand/boot/i386/i86pc/cpu_id.s b/usr/src/psm/stand/boot/i386/i86pc/cpu_id.s deleted file mode 100644 index 8301a2a3b0..0000000000 --- a/usr/src/psm/stand/boot/i386/i86pc/cpu_id.s +++ /dev/null @@ -1,246 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <sys/regset.h> -#include <sys/psw.h> -#include <sys/privregs.h> -#include "../common/cpu_id.h" - -#ifdef __lint -int is486(void) { return (1); } -#else - - .file "cpu_id.s" - - .ident "%Z%%M% %I% %E% SMI" - - .text - -/ We only support 486 or better. So just return 1. - - .globl is486 -is486: - movl $1, %eax - ret - -#endif /* !lint */ - -#ifdef lint -/* - * Enable cpuid. Set max_std_cpuid_level and cpu_vendor appropriately. Returns - * 1 if cpuid present and enabled, 0 otherwise. - */ -int enable_cpuid(void) { return(1); } -int max_std_cpuid_level; -unsigned int cpu_vendor; -#else - .text - .globl enable_cpuid -enable_cpuid: - / Since no documented Cyrix cpu supports PSE, we do not care about - / enabling cpuid, yet. This routine is currently only responsible - / for setting max_std_cpuid_level and cpu_vendor. - pushl %esp - pushfl - popl %eax - movl %eax, %ecx - xorl $PS_ID, %eax - pushl %eax - popfl - pushfl - popl %eax / The above all lifted from locore.s - cmpl %eax, %ecx - jne has_it - movl $0, %eax / cpuid is not present or enabled - jmp enable_cpuid_out -has_it: - / store maxium standard cpuid level - movl $0, %eax - cpuid - movl %eax, max_std_cpuid_level - - / check to see if we are a GenuineIntel - cmpl $Genu, %ebx - jne not_intel - cmpl $ineI, %edx - jne not_intel - cmpl $ntel, %ecx - jne not_intel - movl $GenuineIntel, cpu_vendor - jmp vendor_done -not_intel: - / check to see if we are an AuthenticAMD - cmpl $Auth, %ebx - jne not_amd - cmpl $enti, %edx - jne not_amd - cmpl $cAMD, %ecx - jne not_amd - movl $AuthenticAMD, cpu_vendor -not_amd: -vendor_done: - movl $1, %eax / cpuid present and enabled -enable_cpuid_out: - popl %esp - ret - - .data - .align 4 - .globl max_std_cpuid_level - .globl cpu_vendor -max_std_cpuid_level: .long 0xffffffff -cpu_vendor: .long 0 -#endif - -#ifdef lint -int largepage_supported(void) { return(1); } -#else - .text - .globl largepage_supported -largepage_supported: - pushl %esp / save our stack value - - / test to see if cpuid level 1 supported - cmpl $1, max_std_cpuid_level - jl no - - / are we a vendor for which we know how to test for PSE - testl $[GenuineIntel|AuthenticAMD], cpu_vendor - jz no - - movl $1, %eax / capability test. Mov 1 to eax for cpuid - cpuid - andl $0x8, %edx / do you have large pages? - jz no - movl $1, %eax / yes we do have large pages - popl %esp - ret -no: - movl $0, %eax / no we don't have large pages - popl %esp - ret -#endif - -#ifdef lint -int enable_large_pages(void) { return(1); } -#else - .text - .globl enable_large_pages -enable_large_pages: - movl %cr4, %eax - orl $CR4_PSE, %eax / since we have large pages enable them - movl %eax, %cr4 -#endif - -#ifdef lint -int global_bit(void) { return(1); } -#else - .text - .globl global_bit -global_bit: - pushl %esp / save our stack value - - / test to see if cpuid level 1 supported - cmpl $1, max_std_cpuid_level - jl nogbit - - / are we a vendor for which we know how to test for PGE - testl $[GenuineIntel|AuthenticAMD], cpu_vendor - jz nogbit - - movl $1, %eax / capability test. Mov 1 to eax for cpuid - cpuid - - / are we an AMD - testl $AuthenticAMD, cpu_vendor - jz pge_at_13 - - / test to see if we are an AMD-K5 model 0 - andw $0xff0, %ax - cmpw $0x500, %ax - jl nogbit - jne pge_at_13 - - / we are an AMD-K5 model 0, so GPE is at bit 9 - testl $0x200, %edx / do you have GPE? - jmp test_pge - -pge_at_13: - testl $0x2000, %edx / do you have PGE? -test_pge: - jnz hasgbit -nogbit: - movl $0, %eax / no we don't have global pdtes - jmp global_bit_out -hasgbit: - movl $1, %eax / yes we do have global pdtes -global_bit_out: - popl %esp - ret -#endif - -#ifdef lint -int enable_global_pages(void) { return(1); } -#else - .text - .globl enable_global_pages -enable_global_pages: - movl %cr4, %eax - orl $CR4_PGE, %eax / since we have global pages enable them - movl %eax, %cr4 -#endif - -#ifdef lint -int pae_supported(void) { return (1); } -#else -.set PAE_AND_CXS, 0x140 / PAE = 0x40 & CXS = 0x100 - - .text - .globl pae_supported -pae_supported: - pushl %esp / save our stack value - - / test to see if cpuid level 1 supported - cmpl $1, max_std_cpuid_level - jl nopae - - / are we a vendor for which we know how to test for PAE and CXS - testl $[GenuineIntel|AuthenticAMD], cpu_vendor - jz nopae - - movl $1, %eax / capability test. Mov 1 to eax for cpuid - cpuid - andl $PAE_AND_CXS, %edx / do you support pae and cmpxchg8b? - cmpl $PAE_AND_CXS, %edx - jne nopae - movl $1, %eax / yes we do support pae and cmpxchg8b - popl %esp - ret -nopae: - movl $0, %eax / no we don't support pae and cmpxchg8b - popl %esp - ret -#endif diff --git a/usr/src/psm/stand/boot/i386/i86pc/idttab.s b/usr/src/psm/stand/boot/i386/i86pc/idttab.s deleted file mode 100644 index f205856ab6..0000000000 --- a/usr/src/psm/stand/boot/i386/i86pc/idttab.s +++ /dev/null @@ -1,712 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#if defined(__lint) - -void *slbidt; - -#else - .file "idttab.s" - .ident "%Z%%M% %I% %E% SMI" - - .text - -#define VECT(label, num) \ - .align 4; \ - .globl label; \ -label: \ - push $0; \ - push $num; \ - jmp _cmntrap - - /* - * VECT_EC pushes the trap number ONLY before jumping to cmnint - * for traps that have pushed an error code on the stack already. - * (So that cmnint can expect a common stack frame) - */ -#define VECT_EC(label, num) \ - .align 4; \ - .globl label; \ -label: \ - push $num; \ - jmp _cmntrap - - VECT(div0trap, 0) - VECT(dbgtrap, 1) - VECT(nmiint, 2) - VECT(brktrap, 3) - VECT(ovflotrap, 4) - VECT(boundstrap, 5) - VECT(invoptrap, 6) - VECT(ndptrap0, 7) - VECT_EC(dbfault, 8) - VECT(overrun, 9) - VECT_EC(invtsstrap, 10) - VECT_EC(segnptrap, 11) - VECT_EC(stktrap, 12) - VECT_EC(gptrap, 13) - VECT_EC(pftrap, 14) - VECT(resvtrap, 15) - VECT(ndperr, 16) - VECT_EC(alignflt, 17) - VECT(mceabort, 18) - VECT(simdflt, 19) - VECT(progent, 20) - VECT(inval21, 21) - VECT(inval22, 22) - VECT(inval23, 23) - VECT(inval24, 24) - VECT(inval25, 25) - VECT(inval26, 26) - VECT(inval27, 27) - VECT(inval28, 28) - VECT(inval29, 29) - VECT(inval30, 30) - VECT(inval31, 31) - VECT(ndptrap2, 32) - VECT(inval33, 33) - VECT(inval34, 34) - VECT(inval35, 35) - VECT(inval36, 36) - VECT(inval37, 37) - VECT(inval38, 38) - VECT(inval39, 39) - VECT(inval40, 40) - VECT(inval41, 41) - VECT(inval42, 42) - VECT(inval43, 43) - VECT(inval44, 44) - VECT(inval45, 45) - VECT(inval46, 46) - VECT(inval47, 47) - VECT(inval48, 48) - VECT(inval49, 49) - VECT(inval50, 50) - VECT(inval51, 51) - VECT(inval52, 52) - VECT(inval53, 53) - VECT(inval54, 54) - VECT(inval55, 55) - VECT(inval56, 56) - VECT(inval57, 57) - VECT(inval58, 58) - VECT(inval59, 59) - VECT(inval60, 60) - VECT(inval61, 61) - VECT(inval62, 62) - VECT(inval63, 63) - VECT(ivctM0, 64) - VECT(ivctM1, 65) - VECT(ivctM2, 66) - VECT(ivctM3, 67) - VECT(ivctM4, 68) - VECT(ivctM5, 69) - VECT(ivctM6, 70) - VECT(ivctM7, 71) - VECT(ivctM0S0, 72) - VECT(ivctM0S1, 73) - VECT(ivctM0S2, 74) - VECT(ivctM0S3, 75) - VECT(ivctM0S4, 76) - VECT(ivctM0S5, 77) - VECT(ivctM0S6, 78) - VECT(ivctM0S7, 79) - VECT(ivctM1S0, 80) - VECT(ivctM1S1, 81) - VECT(ivctM1S2, 82) - VECT(ivctM1S3, 83) - VECT(ivctM1S4, 84) - VECT(ivctM1S5, 85) - VECT(ivctM1S6, 86) - VECT(ivctM1S7, 87) - VECT(ivctM2S0, 88) - VECT(ivctM2S1, 89) - VECT(ivctM2S2, 90) - VECT(ivctM2S3, 91) - VECT(ivctM2S4, 92) - VECT(ivctM2S5, 93) - VECT(ivctM2S6, 94) - VECT(ivctM2S7, 95) - VECT(ivctM3S0, 96) - VECT(ivctM3S1, 97) - VECT(ivctM3S2, 98) - VECT(ivctM3S3, 99) - VECT(ivctM3S4, 100) - VECT(ivctM3S5, 101) - VECT(ivctM3S6, 102) - VECT(ivctM3S7, 103) - VECT(ivctM4S0, 104) - VECT(ivctM4S1, 105) - VECT(ivctM4S2, 106) - VECT(ivctM4S3, 107) - VECT(ivctM4S4, 108) - VECT(ivctM4S5, 109) - VECT(ivctM4S6, 110) - VECT(ivctM4S7, 111) - VECT(ivctM5S0, 112) - VECT(ivctM5S1, 113) - VECT(ivctM5S2, 114) - VECT(ivctM5S3, 115) - VECT(ivctM5S4, 116) - VECT(ivctM5S5, 117) - VECT(ivctM5S6, 118) - VECT(ivctM5S7, 119) - VECT(ivctM6S0, 120) - VECT(ivctM6S1, 121) - VECT(ivctM6S2, 122) - VECT(ivctM6S3, 123) - VECT(ivctM6S4, 124) - VECT(ivctM6S5, 125) - VECT(ivctM6S6, 126) - VECT(ivctM6S7, 127) - VECT(ivctM7S0, 128) - VECT(ivctM7S1, 129) - VECT(ivctM7S2, 130) - VECT(ivctM7S3, 131) - VECT(ivctM7S4, 132) - VECT(ivctM7S5, 133) - VECT(ivctM7S6, 134) - VECT(ivctM7S7, 135) - VECT(invaltrap, 255) - - .data - .align 4 - .globl slbidt -slbidt: - .4byte div0trap - .4byte 0x8f000010 - .4byte dbgtrap - .4byte 0x8f000010 - .4byte nmiint - .4byte 0x8e000010 - .4byte brktrap - .4byte 0x8f000010 - .4byte ovflotrap - .4byte 0x8f000010 - .4byte boundstrap - .4byte 0x8f000010 - .4byte invoptrap - .4byte 0x8f000010 - .4byte ndptrap0 - .4byte 0x8f000010 - .4byte dbfault - .4byte 0x8f000010 - .4byte overrun - .4byte 0x8f000010 - .4byte invtsstrap - .4byte 0x8f000010 - .4byte segnptrap - .4byte 0x8f000010 - .4byte stktrap - .4byte 0x8f000010 - .4byte gptrap - .4byte 0x8f000010 - .4byte pftrap - .4byte 0x8f000010 - .4byte resvtrap - .4byte 0x8f000010 - .4byte ndperr - .4byte 0x8f000010 - .4byte alignflt - .4byte 0x8f000010 - .4byte mceabort - .4byte 0x8f000010 - .4byte simdflt - .4byte 0x8f000010 - .4byte progent - .4byte 0x8f000010 - .4byte inval21 - .4byte 0x8f000010 - .4byte inval22 - .4byte 0x8f000010 - .4byte inval23 - .4byte 0x8f000010 - .4byte inval24 - .4byte 0x8f000010 - .4byte inval25 - .4byte 0x8f000010 - .4byte inval26 - .4byte 0x8f000010 - .4byte inval27 - .4byte 0x8f000010 - .4byte inval28 - .4byte 0x8f000010 - .4byte inval29 - .4byte 0x8f000010 - .4byte inval30 - .4byte 0x8f000010 - .4byte inval31 - .4byte 0x8f000010 - .4byte ndptrap2 - .4byte 0x8f000010 - .4byte inval33 - .4byte 0x8f000010 - .4byte inval34 - .4byte 0x8f000010 - .4byte inval35 - .4byte 0x8f000010 - .4byte inval36 - .4byte 0x8f000010 - .4byte inval37 - .4byte 0x8f000010 - .4byte inval38 - .4byte 0x8f000010 - .4byte inval39 - .4byte 0x8f000010 - .4byte inval40 - .4byte 0x8f000010 - .4byte inval41 - .4byte 0x8f000010 - .4byte inval42 - .4byte 0x8f000010 - .4byte inval43 - .4byte 0x8f000010 - .4byte inval44 - .4byte 0x8f000010 - .4byte inval45 - .4byte 0x8f000010 - .4byte inval46 - .4byte 0x8f000010 - .4byte inval47 - .4byte 0x8f000010 - .4byte inval48 - .4byte 0x8f000010 - .4byte inval49 - .4byte 0x8f000010 - .4byte inval50 - .4byte 0x8f000010 - .4byte inval51 - .4byte 0x8f000010 - .4byte inval52 - .4byte 0x8f000010 - .4byte inval53 - .4byte 0x8f000010 - .4byte inval54 - .4byte 0x8f000010 - .4byte inval55 - .4byte 0x8f000010 - .4byte inval56 - .4byte 0x8f000010 - .4byte inval57 - .4byte 0x8f000010 - .4byte inval58 - .4byte 0x8f000010 - .4byte inval59 - .4byte 0x8f000010 - .4byte inval60 - .4byte 0x8f000010 - .4byte inval61 - .4byte 0x8f000010 - .4byte inval62 - .4byte 0x8f000010 - .4byte inval63 - .4byte 0x8f000010 - .4byte ivctM0 - .4byte 0x8e000010 - .4byte ivctM1 - .4byte 0x8e000010 - .4byte ivctM2 - .4byte 0x8e000010 - .4byte ivctM3 - .4byte 0x8e000010 - .4byte ivctM4 - .4byte 0x8e000010 - .4byte ivctM5 - .4byte 0x8e000010 - .4byte ivctM6 - .4byte 0x8e000010 - .4byte ivctM7 - .4byte 0x8e000010 - .4byte ivctM0S0 - .4byte 0x8e000010 - .4byte ivctM0S1 - .4byte 0x8e000010 - .4byte ivctM0S2 - .4byte 0x8e000010 - .4byte ivctM0S3 - .4byte 0x8e000010 - .4byte ivctM0S4 - .4byte 0x8e000010 - .4byte ivctM0S5 - .4byte 0x8e000010 - .4byte ivctM0S6 - .4byte 0x8e000010 - .4byte ivctM0S7 - .4byte 0x8e000010 - .4byte ivctM1S0 - .4byte 0x8e000010 - .4byte ivctM1S1 - .4byte 0x8e000010 - .4byte ivctM1S2 - .4byte 0x8e000010 - .4byte ivctM1S3 - .4byte 0x8e000010 - .4byte ivctM1S4 - .4byte 0x8e000010 - .4byte ivctM1S5 - .4byte 0x8e000010 - .4byte ivctM1S6 - .4byte 0x8e000010 - .4byte ivctM1S7 - .4byte 0x8e000010 - .4byte ivctM2S0 - .4byte 0x8e000010 - .4byte ivctM2S1 - .4byte 0x8e000010 - .4byte ivctM2S2 - .4byte 0x8e000010 - .4byte ivctM2S3 - .4byte 0x8e000010 - .4byte ivctM2S4 - .4byte 0x8e000010 - .4byte ivctM2S5 - .4byte 0x8e000010 - .4byte ivctM2S6 - .4byte 0x8e000010 - .4byte ivctM2S7 - .4byte 0x8e000010 - .4byte ivctM3S0 - .4byte 0x8e000010 - .4byte ivctM3S1 - .4byte 0x8e000010 - .4byte ivctM3S2 - .4byte 0x8e000010 - .4byte ivctM3S3 - .4byte 0x8e000010 - .4byte ivctM3S4 - .4byte 0x8e000010 - .4byte ivctM3S5 - .4byte 0x8e000010 - .4byte ivctM3S6 - .4byte 0x8e000010 - .4byte ivctM3S7 - .4byte 0x8e000010 - .4byte ivctM4S0 - .4byte 0x8e000010 - .4byte ivctM4S1 - .4byte 0x8e000010 - .4byte ivctM4S2 - .4byte 0x8e000010 - .4byte ivctM4S3 - .4byte 0x8e000010 - .4byte ivctM4S4 - .4byte 0x8e000010 - .4byte ivctM4S5 - .4byte 0x8e000010 - .4byte ivctM4S6 - .4byte 0x8e000010 - .4byte ivctM4S7 - .4byte 0x8e000010 - .4byte ivctM5S0 - .4byte 0x8e000010 - .4byte ivctM5S1 - .4byte 0x8e000010 - .4byte ivctM5S2 - .4byte 0x8e000010 - .4byte ivctM5S3 - .4byte 0x8e000010 - .4byte ivctM5S4 - .4byte 0x8e000010 - .4byte ivctM5S5 - .4byte 0x8e000010 - .4byte ivctM5S6 - .4byte 0x8e000010 - .4byte ivctM5S7 - .4byte 0x8e000010 - .4byte ivctM6S0 - .4byte 0x8e000010 - .4byte ivctM6S1 - .4byte 0x8e000010 - .4byte ivctM6S2 - .4byte 0x8e000010 - .4byte ivctM6S3 - .4byte 0x8e000010 - .4byte ivctM6S4 - .4byte 0x8e000010 - .4byte ivctM6S5 - .4byte 0x8e000010 - .4byte ivctM6S6 - .4byte 0x8e000010 - .4byte ivctM6S7 - .4byte 0x8e000010 - .4byte ivctM7S0 - .4byte 0x8e000010 - .4byte ivctM7S1 - .4byte 0x8e000010 - .4byte ivctM7S2 - .4byte 0x8e000010 - .4byte ivctM7S3 - .4byte 0x8e000010 - .4byte ivctM7S4 - .4byte 0x8e000010 - .4byte ivctM7S5 - .4byte 0x8e000010 - .4byte ivctM7S6 - .4byte 0x8e000010 - .4byte ivctM7S7 - .4byte 0x8e000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - .4byte invaltrap - .4byte 0x8f000010 - -#endif /*__lint*/ diff --git a/usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s b/usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s deleted file mode 100644 index fae6774331..0000000000 --- a/usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s +++ /dev/null @@ -1,1129 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. - * Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T - * All Rights Reserved - * - * this file includes portions of uts/i86/ml/i86_subr.s - */ - -#ident "%Z%%M% %I% %E% SMI" - -#include <sys/asm_linkage.h> -#include <sys/asm_misc.h> -#include <sys/regset.h> - -#if defined(lint) || defined(__lint) -#include <sys/types.h> -#include <sys/thread.h> -#include <sys/archsystm.h> -#endif /* lint */ - -#if defined(lint) || defined(__lint) - -/* ARGSUSED */ -long long -__mul64(long long a, long long b) -{ return (0); } - -#else /* lint */ - -/ -/ function __mul64(A,B:Longint):Longint; -/ {Overflow is not checked} -/ -/ We essentially do multiply by longhand, using base 2**32 digits. -/ a b parameter A -/ x c d parameter B -/ --------- -/ ad bd -/ ac bc -/ ----------------- -/ ac ad+bc bd -/ -/ We can ignore ac and top 32 bits of ad+bc: if <> 0, overflow happened. -/ - ENTRY(__mul64) - push %ebp - mov %esp,%ebp - pushl %esi - mov 12(%ebp),%eax / A.hi (a) - mull 16(%ebp) / Multiply A.hi by B.lo (produces ad) - xchg %ecx,%eax / ecx = bottom half of ad. - movl 8(%ebp),%eax / A.Lo (b) - movl %eax,%esi / Save A.lo for later - mull 16(%ebp) / Multiply A.Lo by B.LO (dx:ax = bd.) - addl %edx,%ecx / cx is ad - xchg %eax,%esi / esi is bd, eax = A.lo (d) - mull 20(%ebp) / Multiply A.lo * B.hi (producing bc) - addl %ecx,%eax / Produce ad+bc - movl %esi,%edx - xchg %eax,%edx - popl %esi - movl %ebp,%esp - popl %ebp - ret $16 - SET_SIZE(__mul64) - -#endif /* lint */ - -/* - * multiply two long numbers and yield a u_longlong_t result, callable from C. - * Provided to manipulate hrtime_t values. - */ -#if defined(lint) || defined(__lint) - -/* result = a * b; */ - -/* ARGSUSED */ -unsigned long long -mul32(ulong a, ulong b) -{ return (0); } - -#else /* lint */ - - ENTRY(mul32) - movl 8(%esp), %eax - movl 4(%esp), %ecx - mull %ecx - ret - SET_SIZE(mul32) - -#endif /* lint */ - -/* - * C support for 64-bit modulo and division. - * Hand-customized compiler output - see comments for details. - */ - -#if defined(lint) || defined(__lint) - -/* ARGSUSED */ -uint64_t -__udiv64(uint64_t a, uint64_t b) -{ return (0); } - -/* ARGSUSED */ -uint64_t __udivrem64(uint64_t a, uint64_t b) -{ return (0); } - -/* ARGSUSED */ -uint64_t -__urem64(int64_t a, int64_t b) -{ return (0); } - -/* ARGSUSED */ -int64_t -__div64(int64_t a, int64_t b) -{ return (0); } - -/* ARGSUSED */ -int64_t __divrem64(int64_t a, int64_t b) -{ return (0); } - -/* ARGSUSED */ -int64_t -__rem64(int64_t a, int64_t b) - -{ return (0); } - -#else /* lint */ - -/* - * int32_t/int64_t division/manipulation - * - * Hand-customized compiler output: the non-GCC entry points depart from - * the SYS V ABI by requiring their arguments to be popped, and in the - * [u]divrem64 cases returning the remainder in %ecx:%esi. Note the - * compiler-generated use of %edx:%eax for the first argument of - * internal entry points. - * - * Inlines for speed: - * - counting the number of leading zeros in a word - * - multiplying two 32-bit numbers giving a 64-bit result - * - dividing a 64-bit number by a 32-bit number, giving both quotient - * and remainder - * - subtracting two 64-bit results - */ -/ #define LO(X) ((uint32_t)(X) & 0xffffffff) -/ #define HI(X) ((uint32_t)((X) >> 32) & 0xffffffff) -/ #define HILO(H, L) (((uint64_t)(H) << 32) + (L)) -/ -/ /* give index of highest bit */ -/ #define HIBIT(a, r) \ -/ asm("bsrl %1,%0": "=r"((uint32_t)(r)) : "g" (a)) -/ -/ /* multiply two uint32_ts resulting in a uint64_t */ -/ #define A_MUL32(a, b, lo, hi) \ -/ asm("mull %2" \ -/ : "=a"((uint32_t)(lo)), "=d"((uint32_t)(hi)) : "g" (b), "0"(a)) -/ -/ /* divide a uint64_t by a uint32_t */ -/ #define A_DIV32(lo, hi, b, q, r) \ -/ asm("divl %2" \ -/ : "=a"((uint32_t)(q)), "=d"((uint32_t)(r)) \ -/ : "g" (b), "0"((uint32_t)(lo)), "1"((uint32_t)hi)) -/ -/ /* subtract two uint64_ts (with borrow) */ -/ #define A_SUB2(bl, bh, al, ah) \ -/ asm("subl %4,%0\n\tsbbl %5,%1" \ -/ : "=&r"((uint32_t)(al)), "=r"((uint32_t)(ah)) \ -/ : "0"((uint32_t)(al)), "1"((uint32_t)(ah)), "g"((uint32_t)(bl)), \ -/ "g"((uint32_t)(bh))) -/ -/ /* -/ * Unsigned division with remainder. -/ * Divide two uint64_ts, and calculate remainder. -/ */ -/ uint64_t -/ UDivRem(uint64_t x, uint64_t y, uint64_t * pmod) -/ { -/ /* simple cases: y is a single uint32_t */ -/ if (HI(y) == 0) { -/ uint32_t div_hi, div_rem; -/ uint32_t q0, q1; -/ -/ /* calculate q1 */ -/ if (HI(x) < LO(y)) { -/ /* result is a single uint32_t, use one division */ -/ q1 = 0; -/ div_hi = HI(x); -/ } else { -/ /* result is a double uint32_t, use two divisions */ -/ A_DIV32(HI(x), 0, LO(y), q1, div_hi); -/ } -/ -/ /* calculate q0 and remainder */ -/ A_DIV32(LO(x), div_hi, LO(y), q0, div_rem); -/ -/ /* return remainder */ -/ *pmod = div_rem; -/ -/ /* return result */ -/ return (HILO(q1, q0)); -/ -/ } else if (HI(x) < HI(y)) { -/ /* HI(x) < HI(y) => x < y => result is 0 */ -/ -/ /* return remainder */ -/ *pmod = x; -/ -/ /* return result */ -/ return (0); -/ -/ } else { -/ /* -/ * uint64_t by uint64_t division, resulting in a one-uint32_t -/ * result -/ */ -/ uint32_t y0, y1; -/ uint32_t x1, x0; -/ uint32_t q0; -/ uint32_t normshift; -/ -/ /* normalize by shifting x and y so MSB(y) == 1 */ -/ HIBIT(HI(y), normshift); /* index of highest 1 bit */ -/ normshift = 31 - normshift; -/ -/ if (normshift == 0) { -/ /* no shifting needed, and x < 2*y so q <= 1 */ -/ y1 = HI(y); -/ y0 = LO(y); -/ x1 = HI(x); -/ x0 = LO(x); -/ -/ /* if x >= y then q = 1 (note x1 >= y1) */ -/ if (x1 > y1 || x0 >= y0) { -/ q0 = 1; -/ /* subtract y from x to get remainder */ -/ A_SUB2(y0, y1, x0, x1); -/ } else { -/ q0 = 0; -/ } -/ -/ /* return remainder */ -/ *pmod = HILO(x1, x0); -/ -/ /* return result */ -/ return (q0); -/ -/ } else { -/ /* -/ * the last case: result is one uint32_t, but we need to -/ * normalize -/ */ -/ uint64_t dt; -/ uint32_t t0, t1, x2; -/ -/ /* normalize y */ -/ dt = (y << normshift); -/ y1 = HI(dt); -/ y0 = LO(dt); -/ -/ /* normalize x (we need 3 uint32_ts!!!) */ -/ x2 = (HI(x) >> (32 - normshift)); -/ dt = (x << normshift); -/ x1 = HI(dt); -/ x0 = LO(dt); -/ -/ /* estimate q0, and reduce x to a two uint32_t value */ -/ A_DIV32(x1, x2, y1, q0, x1); -/ -/ /* adjust q0 down if too high */ -/ /* -/ * because of the limited range of x2 we can only be -/ * one off -/ */ -/ A_MUL32(y0, q0, t0, t1); -/ if (t1 > x1 || (t1 == x1 && t0 > x0)) { -/ q0--; -/ A_SUB2(y0, y1, t0, t1); -/ } -/ /* return remainder */ -/ /* subtract product from x to get remainder */ -/ A_SUB2(t0, t1, x0, x1); -/ *pmod = (HILO(x1, x0) >> normshift); -/ -/ /* return result */ -/ return (q0); -/ } -/ } -/ } - ENTRY(UDivRem) - pushl %ebp - pushl %edi - pushl %esi - subl $48, %esp - movl 68(%esp), %edi / y, - testl %edi, %edi / tmp63 - movl %eax, 40(%esp) / x, x - movl %edx, 44(%esp) / x, x - movl %edi, %esi /, tmp62 - movl %edi, %ecx / tmp62, tmp63 - jne .LL2 - movl %edx, %eax /, tmp68 - cmpl 64(%esp), %eax / y, tmp68 - jae .LL21 -.LL4: - movl 72(%esp), %ebp / pmod, - xorl %esi, %esi / <result> - movl 40(%esp), %eax / x, q0 - movl %ecx, %edi / <result>, <result> - divl 64(%esp) / y - movl %edx, (%ebp) / div_rem, - xorl %edx, %edx / q0 - addl %eax, %esi / q0, <result> - movl $0, 4(%ebp) - adcl %edx, %edi / q0, <result> - addl $48, %esp - movl %esi, %eax / <result>, <result> - popl %esi - movl %edi, %edx / <result>, <result> - popl %edi - popl %ebp - ret - .align 16 -.LL2: - movl 44(%esp), %eax / x, - xorl %edx, %edx - cmpl %esi, %eax / tmp62, tmp5 - movl %eax, 32(%esp) / tmp5, - movl %edx, 36(%esp) - jae .LL6 - movl 72(%esp), %esi / pmod, - movl 40(%esp), %ebp / x, - movl 44(%esp), %ecx / x, - movl %ebp, (%esi) - movl %ecx, 4(%esi) - xorl %edi, %edi / <result> - xorl %esi, %esi / <result> -.LL22: - addl $48, %esp - movl %esi, %eax / <result>, <result> - popl %esi - movl %edi, %edx / <result>, <result> - popl %edi - popl %ebp - ret - .align 16 -.LL21: - movl %edi, %edx / tmp63, div_hi - divl 64(%esp) / y - movl %eax, %ecx /, q1 - jmp .LL4 - .align 16 -.LL6: - movl $31, %edi /, tmp87 - bsrl %esi,%edx / tmp62, normshift - subl %edx, %edi / normshift, tmp87 - movl %edi, 28(%esp) / tmp87, - jne .LL8 - movl 32(%esp), %edx /, x1 - cmpl %ecx, %edx / y1, x1 - movl 64(%esp), %edi / y, y0 - movl 40(%esp), %esi / x, x0 - ja .LL10 - xorl %ebp, %ebp / q0 - cmpl %edi, %esi / y0, x0 - jb .LL11 -.LL10: - movl $1, %ebp /, q0 - subl %edi,%esi / y0, x0 - sbbl %ecx,%edx / tmp63, x1 -.LL11: - movl %edx, %ecx / x1, x1 - xorl %edx, %edx / x1 - xorl %edi, %edi / x0 - addl %esi, %edx / x0, x1 - adcl %edi, %ecx / x0, x1 - movl 72(%esp), %esi / pmod, - movl %edx, (%esi) / x1, - movl %ecx, 4(%esi) / x1, - xorl %edi, %edi / <result> - movl %ebp, %esi / q0, <result> - jmp .LL22 - .align 16 -.LL8: - movb 28(%esp), %cl - movl 64(%esp), %esi / y, dt - movl 68(%esp), %edi / y, dt - shldl %esi, %edi /, dt, dt - sall %cl, %esi /, dt - andl $32, %ecx - jne .LL23 -.LL17: - movl $32, %ecx /, tmp102 - subl 28(%esp), %ecx /, tmp102 - movl %esi, %ebp / dt, y0 - movl 32(%esp), %esi - shrl %cl, %esi / tmp102, - movl %edi, 24(%esp) / tmp99, - movb 28(%esp), %cl - movl %esi, 12(%esp) /, x2 - movl 44(%esp), %edi / x, dt - movl 40(%esp), %esi / x, dt - shldl %esi, %edi /, dt, dt - sall %cl, %esi /, dt - andl $32, %ecx - je .LL18 - movl %esi, %edi / dt, dt - xorl %esi, %esi / dt -.LL18: - movl %edi, %ecx / dt, - movl %edi, %eax / tmp2, - movl %ecx, (%esp) - movl 12(%esp), %edx / x2, - divl 24(%esp) - movl %edx, %ecx /, x1 - xorl %edi, %edi - movl %eax, 20(%esp) - movl %ebp, %eax / y0, t0 - mull 20(%esp) - cmpl %ecx, %edx / x1, t1 - movl %edi, 4(%esp) - ja .LL14 - je .LL24 -.LL15: - movl %ecx, %edi / x1, - subl %eax,%esi / t0, x0 - sbbl %edx,%edi / t1, - movl %edi, %eax /, x1 - movl %eax, %edx / x1, x1 - xorl %eax, %eax / x1 - xorl %ebp, %ebp / x0 - addl %esi, %eax / x0, x1 - adcl %ebp, %edx / x0, x1 - movb 28(%esp), %cl - shrdl %edx, %eax /, x1, x1 - shrl %cl, %edx /, x1 - andl $32, %ecx - je .LL16 - movl %edx, %eax / x1, x1 - xorl %edx, %edx / x1 -.LL16: - movl 72(%esp), %ecx / pmod, - movl 20(%esp), %esi /, <result> - xorl %edi, %edi / <result> - movl %eax, (%ecx) / x1, - movl %edx, 4(%ecx) / x1, - jmp .LL22 - .align 16 -.LL24: - cmpl %esi, %eax / x0, t0 - jbe .LL15 -.LL14: - decl 20(%esp) - subl %ebp,%eax / y0, t0 - sbbl 24(%esp),%edx /, t1 - jmp .LL15 -.LL23: - movl %esi, %edi / dt, dt - xorl %esi, %esi / dt - jmp .LL17 - SET_SIZE(UDivRem) - -/* - * Unsigned division without remainder. - */ -/ uint64_t -/ UDiv(uint64_t x, uint64_t y) -/ { -/ if (HI(y) == 0) { -/ /* simple cases: y is a single uint32_t */ -/ uint32_t div_hi, div_rem; -/ uint32_t q0, q1; -/ -/ /* calculate q1 */ -/ if (HI(x) < LO(y)) { -/ /* result is a single uint32_t, use one division */ -/ q1 = 0; -/ div_hi = HI(x); -/ } else { -/ /* result is a double uint32_t, use two divisions */ -/ A_DIV32(HI(x), 0, LO(y), q1, div_hi); -/ } -/ -/ /* calculate q0 and remainder */ -/ A_DIV32(LO(x), div_hi, LO(y), q0, div_rem); -/ -/ /* return result */ -/ return (HILO(q1, q0)); -/ -/ } else if (HI(x) < HI(y)) { -/ /* HI(x) < HI(y) => x < y => result is 0 */ -/ -/ /* return result */ -/ return (0); -/ -/ } else { -/ /* -/ * uint64_t by uint64_t division, resulting in a one-uint32_t -/ * result -/ */ -/ uint32_t y0, y1; -/ uint32_t x1, x0; -/ uint32_t q0; -/ unsigned normshift; -/ -/ /* normalize by shifting x and y so MSB(y) == 1 */ -/ HIBIT(HI(y), normshift); /* index of highest 1 bit */ -/ normshift = 31 - normshift; -/ -/ if (normshift == 0) { -/ /* no shifting needed, and x < 2*y so q <= 1 */ -/ y1 = HI(y); -/ y0 = LO(y); -/ x1 = HI(x); -/ x0 = LO(x); -/ -/ /* if x >= y then q = 1 (note x1 >= y1) */ -/ if (x1 > y1 || x0 >= y0) { -/ q0 = 1; -/ /* subtract y from x to get remainder */ -/ /* A_SUB2(y0, y1, x0, x1); */ -/ } else { -/ q0 = 0; -/ } -/ -/ /* return result */ -/ return (q0); -/ -/ } else { -/ /* -/ * the last case: result is one uint32_t, but we need to -/ * normalize -/ */ -/ uint64_t dt; -/ uint32_t t0, t1, x2; -/ -/ /* normalize y */ -/ dt = (y << normshift); -/ y1 = HI(dt); -/ y0 = LO(dt); -/ -/ /* normalize x (we need 3 uint32_ts!!!) */ -/ x2 = (HI(x) >> (32 - normshift)); -/ dt = (x << normshift); -/ x1 = HI(dt); -/ x0 = LO(dt); -/ -/ /* estimate q0, and reduce x to a two uint32_t value */ -/ A_DIV32(x1, x2, y1, q0, x1); -/ -/ /* adjust q0 down if too high */ -/ /* -/ * because of the limited range of x2 we can only be -/ * one off -/ */ -/ A_MUL32(y0, q0, t0, t1); -/ if (t1 > x1 || (t1 == x1 && t0 > x0)) { -/ q0--; -/ } -/ /* return result */ -/ return (q0); -/ } -/ } -/ } - ENTRY(UDiv) - pushl %ebp - pushl %edi - pushl %esi - subl $40, %esp - movl %edx, 36(%esp) / x, x - movl 60(%esp), %edx / y, - testl %edx, %edx / tmp62 - movl %eax, 32(%esp) / x, x - movl %edx, %ecx / tmp61, tmp62 - movl %edx, %eax /, tmp61 - jne .LL26 - movl 36(%esp), %esi / x, - cmpl 56(%esp), %esi / y, tmp67 - movl %esi, %eax /, tmp67 - movl %esi, %edx / tmp67, div_hi - jb .LL28 - movl %ecx, %edx / tmp62, div_hi - divl 56(%esp) / y - movl %eax, %ecx /, q1 -.LL28: - xorl %esi, %esi / <result> - movl %ecx, %edi / <result>, <result> - movl 32(%esp), %eax / x, q0 - xorl %ecx, %ecx / q0 - divl 56(%esp) / y - addl %eax, %esi / q0, <result> - adcl %ecx, %edi / q0, <result> -.LL25: - addl $40, %esp - movl %esi, %eax / <result>, <result> - popl %esi - movl %edi, %edx / <result>, <result> - popl %edi - popl %ebp - ret - .align 16 -.LL26: - movl 36(%esp), %esi / x, - xorl %edi, %edi - movl %esi, 24(%esp) / tmp1, - movl %edi, 28(%esp) - xorl %esi, %esi / <result> - xorl %edi, %edi / <result> - cmpl %eax, 24(%esp) / tmp61, - jb .LL25 - bsrl %eax,%ebp / tmp61, normshift - movl $31, %eax /, tmp85 - subl %ebp, %eax / normshift, normshift - jne .LL32 - movl 24(%esp), %eax /, x1 - cmpl %ecx, %eax / tmp62, x1 - movl 56(%esp), %esi / y, y0 - movl 32(%esp), %edx / x, x0 - ja .LL34 - xorl %eax, %eax / q0 - cmpl %esi, %edx / y0, x0 - jb .LL35 -.LL34: - movl $1, %eax /, q0 -.LL35: - movl %eax, %esi / q0, <result> - xorl %edi, %edi / <result> -.LL45: - addl $40, %esp - movl %esi, %eax / <result>, <result> - popl %esi - movl %edi, %edx / <result>, <result> - popl %edi - popl %ebp - ret - .align 16 -.LL32: - movb %al, %cl - movl 56(%esp), %esi / y, - movl 60(%esp), %edi / y, - shldl %esi, %edi - sall %cl, %esi - andl $32, %ecx - jne .LL43 -.LL40: - movl $32, %ecx /, tmp96 - subl %eax, %ecx / normshift, tmp96 - movl %edi, %edx - movl %edi, 20(%esp) /, dt - movl 24(%esp), %ebp /, x2 - xorl %edi, %edi - shrl %cl, %ebp / tmp96, x2 - movl %esi, 16(%esp) /, dt - movb %al, %cl - movl 32(%esp), %esi / x, dt - movl %edi, 12(%esp) - movl 36(%esp), %edi / x, dt - shldl %esi, %edi /, dt, dt - sall %cl, %esi /, dt - andl $32, %ecx - movl %edx, 8(%esp) - je .LL41 - movl %esi, %edi / dt, dt - xorl %esi, %esi / dt -.LL41: - xorl %ecx, %ecx - movl %edi, %eax / tmp1, - movl %ebp, %edx / x2, - divl 8(%esp) - movl %edx, %ebp /, x1 - movl %ecx, 4(%esp) - movl %eax, %ecx /, q0 - movl 16(%esp), %eax / dt, - mull %ecx / q0 - cmpl %ebp, %edx / x1, t1 - movl %edi, (%esp) - movl %esi, %edi / dt, x0 - ja .LL38 - je .LL44 -.LL39: - movl %ecx, %esi / q0, <result> -.LL46: - xorl %edi, %edi / <result> - jmp .LL45 -.LL44: - cmpl %edi, %eax / x0, t0 - jbe .LL39 -.LL38: - decl %ecx / q0 - movl %ecx, %esi / q0, <result> - jmp .LL46 -.LL43: - movl %esi, %edi - xorl %esi, %esi - jmp .LL40 - SET_SIZE(UDiv) -/* - * __udiv64 - * - * Perform division of two unsigned 64-bit quantities, returning the - * quotient in %edx:%eax. __udiv64 pops the arguments on return, - */ - ENTRY(__udiv64) - movl 4(%esp), %eax / x, x - movl 8(%esp), %edx / x, x - pushl 16(%esp) / y - pushl 16(%esp) - call UDiv - addl $8, %esp - ret $16 - SET_SIZE(__udiv64) - -/* - * __urem64 - * - * Perform division of two unsigned 64-bit quantities, returning the - * remainder in %edx:%eax. __urem64 pops the arguments on return - */ - ENTRY(__urem64) - subl $12, %esp - movl %esp, %ecx /, tmp65 - movl 16(%esp), %eax / x, x - movl 20(%esp), %edx / x, x - pushl %ecx / tmp65 - pushl 32(%esp) / y - pushl 32(%esp) - call UDivRem - movl 12(%esp), %eax / rem, rem - movl 16(%esp), %edx / rem, rem - addl $24, %esp - ret $16 - SET_SIZE(__urem64) - -/* - * __div64 - * - * Perform division of two signed 64-bit quantities, returning the - * quotient in %edx:%eax. __div64 pops the arguments on return. - */ -/ int64_t -/ __div64(int64_t x, int64_t y) -/ { -/ int negative; -/ uint64_t xt, yt, r; -/ -/ if (x < 0) { -/ xt = -(uint64_t) x; -/ negative = 1; -/ } else { -/ xt = x; -/ negative = 0; -/ } -/ if (y < 0) { -/ yt = -(uint64_t) y; -/ negative ^= 1; -/ } else { -/ yt = y; -/ } -/ r = UDiv(xt, yt); -/ return (negative ? (int64_t) - r : r); -/ } - ENTRY(__div64) - pushl %ebp - pushl %edi - pushl %esi - subl $8, %esp - movl 28(%esp), %edx / x, x - testl %edx, %edx / x - movl 24(%esp), %eax / x, x - movl 32(%esp), %esi / y, y - movl 36(%esp), %edi / y, y - js .LL84 - xorl %ebp, %ebp / negative - testl %edi, %edi / y - movl %eax, (%esp) / x, xt - movl %edx, 4(%esp) / x, xt - movl %esi, %eax / y, yt - movl %edi, %edx / y, yt - js .LL85 -.LL82: - pushl %edx / yt - pushl %eax / yt - movl 8(%esp), %eax / xt, xt - movl 12(%esp), %edx / xt, xt - call UDiv - popl %ecx - testl %ebp, %ebp / negative - popl %esi - je .LL83 - negl %eax / r - adcl $0, %edx /, r - negl %edx / r -.LL83: - addl $8, %esp - popl %esi - popl %edi - popl %ebp - ret $16 - .align 16 -.LL84: - negl %eax / x - adcl $0, %edx /, x - negl %edx / x - testl %edi, %edi / y - movl %eax, (%esp) / x, xt - movl %edx, 4(%esp) / x, xt - movl $1, %ebp /, negative - movl %esi, %eax / y, yt - movl %edi, %edx / y, yt - jns .LL82 - .align 16 -.LL85: - negl %eax / yt - adcl $0, %edx /, yt - negl %edx / yt - xorl $1, %ebp /, negative - jmp .LL82 - SET_SIZE(__div64) - -/* - * __rem64 - * - * Perform division of two signed 64-bit quantities, returning the - * remainder in %edx:%eax. __rem64 pops the arguments on return. - */ -/ int64_t -/ __rem64(int64_t x, int64_t y) -/ { -/ uint64_t xt, yt, rem; -/ -/ if (x < 0) { -/ xt = -(uint64_t) x; -/ } else { -/ xt = x; -/ } -/ if (y < 0) { -/ yt = -(uint64_t) y; -/ } else { -/ yt = y; -/ } -/ (void) UDivRem(xt, yt, &rem); -/ return (x < 0 ? (int64_t) - rem : rem); -/ } - ENTRY(__rem64) - pushl %edi - pushl %esi - subl $20, %esp - movl 36(%esp), %ecx / x, - movl 32(%esp), %esi / x, - movl 36(%esp), %edi / x, - testl %ecx, %ecx - movl 40(%esp), %eax / y, y - movl 44(%esp), %edx / y, y - movl %esi, (%esp) /, xt - movl %edi, 4(%esp) /, xt - js .LL92 - testl %edx, %edx / y - movl %eax, %esi / y, yt - movl %edx, %edi / y, yt - js .LL93 -.LL90: - leal 8(%esp), %eax /, tmp66 - pushl %eax / tmp66 - pushl %edi / yt - pushl %esi / yt - movl 12(%esp), %eax / xt, xt - movl 16(%esp), %edx / xt, xt - call UDivRem - addl $12, %esp - movl 36(%esp), %edi / x, - testl %edi, %edi - movl 8(%esp), %eax / rem, rem - movl 12(%esp), %edx / rem, rem - js .LL94 - addl $20, %esp - popl %esi - popl %edi - ret $16 - .align 16 -.LL92: - negl %esi - adcl $0, %edi - negl %edi - testl %edx, %edx / y - movl %esi, (%esp) /, xt - movl %edi, 4(%esp) /, xt - movl %eax, %esi / y, yt - movl %edx, %edi / y, yt - jns .LL90 - .align 16 -.LL93: - negl %esi / yt - adcl $0, %edi /, yt - negl %edi / yt - jmp .LL90 - .align 16 -.LL94: - negl %eax / rem - adcl $0, %edx /, rem - addl $20, %esp - popl %esi - negl %edx / rem - popl %edi - ret $16 - SET_SIZE(__rem64) - -/* - * __udivrem64 - * - * Perform division of two unsigned 64-bit quantities, returning the - * quotient in %edx:%eax, and the remainder in %ecx:%esi. __udivrem64 - * pops the arguments on return. - */ - ENTRY(__udivrem64) - subl $12, %esp - movl %esp, %ecx /, tmp64 - movl 16(%esp), %eax / x, x - movl 20(%esp), %edx / x, x - pushl %ecx / tmp64 - pushl 32(%esp) / y - pushl 32(%esp) - call UDivRem - movl 16(%esp), %ecx / rem, tmp63 - movl 12(%esp), %esi / rem - addl $24, %esp - ret $16 - SET_SIZE(__udivrem64) - -/* - * Signed division with remainder. - */ -/ int64_t -/ SDivRem(int64_t x, int64_t y, int64_t * pmod) -/ { -/ int negative; -/ uint64_t xt, yt, r, rem; -/ -/ if (x < 0) { -/ xt = -(uint64_t) x; -/ negative = 1; -/ } else { -/ xt = x; -/ negative = 0; -/ } -/ if (y < 0) { -/ yt = -(uint64_t) y; -/ negative ^= 1; -/ } else { -/ yt = y; -/ } -/ r = UDivRem(xt, yt, &rem); -/ *pmod = (x < 0 ? (int64_t) - rem : rem); -/ return (negative ? (int64_t) - r : r); -/ } - ENTRY(SDivRem) - pushl %ebp - pushl %edi - pushl %esi - subl $24, %esp - testl %edx, %edx / x - movl %edx, %edi / x, x - js .LL73 - movl 44(%esp), %esi / y, - xorl %ebp, %ebp / negative - testl %esi, %esi - movl %edx, 12(%esp) / x, xt - movl %eax, 8(%esp) / x, xt - movl 40(%esp), %edx / y, yt - movl 44(%esp), %ecx / y, yt - js .LL74 -.LL70: - leal 16(%esp), %eax /, tmp70 - pushl %eax / tmp70 - pushl %ecx / yt - pushl %edx / yt - movl 20(%esp), %eax / xt, xt - movl 24(%esp), %edx / xt, xt - call UDivRem - movl %edx, 16(%esp) /, r - movl %eax, 12(%esp) /, r - addl $12, %esp - testl %edi, %edi / x - movl 16(%esp), %edx / rem, rem - movl 20(%esp), %ecx / rem, rem - js .LL75 -.LL71: - movl 48(%esp), %edi / pmod, pmod - testl %ebp, %ebp / negative - movl %edx, (%edi) / rem,* pmod - movl %ecx, 4(%edi) / rem, - movl (%esp), %eax / r, r - movl 4(%esp), %edx / r, r - je .LL72 - negl %eax / r - adcl $0, %edx /, r - negl %edx / r -.LL72: - addl $24, %esp - popl %esi - popl %edi - popl %ebp - ret - .align 16 -.LL73: - negl %eax - adcl $0, %edx - movl 44(%esp), %esi / y, - negl %edx - testl %esi, %esi - movl %edx, 12(%esp) /, xt - movl %eax, 8(%esp) /, xt - movl $1, %ebp /, negative - movl 40(%esp), %edx / y, yt - movl 44(%esp), %ecx / y, yt - jns .LL70 - .align 16 -.LL74: - negl %edx / yt - adcl $0, %ecx /, yt - negl %ecx / yt - xorl $1, %ebp /, negative - jmp .LL70 - .align 16 -.LL75: - negl %edx / rem - adcl $0, %ecx /, rem - negl %ecx / rem - jmp .LL71 - SET_SIZE(SDivRem) - -/* - * __divrem64 - * - * Perform division of two signed 64-bit quantities, returning the - * quotient in %edx:%eax, and the remainder in %ecx:%esi. __divrem64 - * pops the arguments on return. - */ - ENTRY(__divrem64) - subl $20, %esp - movl %esp, %ecx /, tmp64 - movl 24(%esp), %eax / x, x - movl 28(%esp), %edx / x, x - pushl %ecx / tmp64 - pushl 40(%esp) / y - pushl 40(%esp) - call SDivRem - movl 16(%esp), %ecx - movl 12(%esp),%esi / rem - addl $32, %esp - ret $16 - SET_SIZE(__divrem64) -#endif /* lint */ - - -#if defined(__lint) -/*ARGSUSED*/ -unsigned long long -__udivdi3(unsigned long long a, unsigned long long b) -{ return (0); } - -/*ARGSUSED*/ -unsigned long long -__umoddi3(unsigned long long a, unsigned long long b) -{ return (0); } - -#else - -/* - * __udivdi3 - * - * Perform division of two unsigned 64-bit quantities, returning the - * quotient in %edx:%eax. - */ - ENTRY(__udivdi3) - movl 4(%esp), %eax / x, x - movl 8(%esp), %edx / x, x - pushl 16(%esp) / y - pushl 16(%esp) - call UDiv - addl $8, %esp - ret - SET_SIZE(__udivdi3) - -/* - * __umoddi3 - * - * Perform division of two unsigned 64-bit quantities, returning the - * remainder in %edx:%eax. - */ - ENTRY(__umoddi3) - subl $12, %esp - movl %esp, %ecx /, tmp65 - movl 16(%esp), %eax / x, x - movl 20(%esp), %edx / x, x - pushl %ecx / tmp65 - pushl 32(%esp) / y - pushl 32(%esp) - call UDivRem - movl 12(%esp), %eax / rem, rem - movl 16(%esp), %edx / rem, rem - addl $24, %esp - ret - SET_SIZE(__umoddi3) -#endif diff --git a/usr/src/psm/stand/cpr/common/Makefile.com b/usr/src/psm/stand/cpr/common/Makefile.com index 033907f0c8..8d448c539f 100644 --- a/usr/src/psm/stand/cpr/common/Makefile.com +++ b/usr/src/psm/stand/cpr/common/Makefile.com @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,7 +21,7 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # psm/stand/cpr/common/Makefile.com @@ -66,7 +65,8 @@ CPPINCS += -I$(SYSDIR)/sun4 -I$(SYSDIR)/common -I$(TOPDIR)/head CPPFLAGS = $(CPPDEFS) $(CPPINCS) $(CPPFLAGS.master) CPPFLAGS += $(CCYFLAG)$(SYSDIR)/common -CFLAGS = $(CCVERBOSE) -O +C99MODE = $(C99_ENABLE) +CFLAGS = $(CCVERBOSE) -O $(C99MODE) ASFLAGS = -P -D_ASM $(CPPDEFS) -DLOCORE -D_LOCORE -D__STDC__ AS_CPPFLAGS = $(CPPINCS) $(CPPFLAGS.master) diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.c b/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.c index e2973d2fcb..5881aa2fca 100644 --- a/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.c +++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -363,7 +362,7 @@ cb_read_statefile(void) cb_nbitmaps = cdump.cdd_bitmaprec; cpr_test_mode = cdump.cdd_test_mode; sfile.kpages = cdump.cdd_dumppgsize; - DEBUG4(prom_printf("%s: total kpages %d\n", prog, sfile.kpages)); + CPR_DEBUG(CPR_DEBUG4, "%s: total kpages %d\n", prog, sfile.kpages); /* * alloc virt and phys space with 512K alignment; @@ -401,7 +400,7 @@ cb_read_statefile(void) cnt = 0; dtlb_index = cb_dents - 1; (void) prom_seek(sfile.fd, specialstate ? CPR_SPEC_OFFSET : 0); - DEBUG1(prom_printf("%s: reading statefile... ", prog)); + CPR_DEBUG(CPR_DEBUG1, "%s: reading statefile... ", prog); for (resid = cdump.cdd_filesize; resid; resid -= len) { /* * do a full spin (4 spin chars) @@ -432,7 +431,7 @@ cb_read_statefile(void) dst_virt += len; dst_phys += len; } - DEBUG1(prom_printf(" \b\n")); + CPR_DEBUG(CPR_DEBUG1, " \b\n"); /* * free up any unused phys pages trailing the statefile buffer; diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.h b/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.h index 52807b6616..2102820146 100644 --- a/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.h +++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/cprboot.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -81,7 +80,7 @@ extern "C" { #define NULLP (char *)0 -#define CPR_DBG(n) (cpr_debug & LEVEL##n) +#define CPR_DBG(n) (cpr_debug & CPR_DEBUG##n) /* diff --git a/usr/src/psm/stand/cpr/sparcv9/sun4u/pages.c b/usr/src/psm/stand/cpr/sparcv9/sun4u/pages.c index e8781db864..a8513319e9 100644 --- a/usr/src/psm/stand/cpr/sparcv9/sun4u/pages.c +++ b/usr/src/psm/stand/cpr/sparcv9/sun4u/pages.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -285,7 +284,7 @@ cb_restore_kpages(void) str = "cb_restore_kpages"; CB_VPRINTF((ent_fmt, str, entry)); - DEBUG1(prom_printf("%s: restoring kpages... ", prog)); + CPR_DEBUG(CPR_DEBUG1, "%s: restoring kpages... ", prog); npages = compressed = regular = 0; while (npages < sfile.kpages) { get_phys_data(&desc, sizeof (desc)); @@ -310,7 +309,7 @@ cb_restore_kpages(void) if ((sfile.ngroups++ & 0x1f) == 0) cb_spin(); } - DEBUG1(prom_printf(" \b\n")); + CPR_DEBUG(CPR_DEBUG1, " \b\n"); dtlb_cleanup(); @@ -322,9 +321,9 @@ cb_restore_kpages(void) sfile.ngroups, sfile.recycle); } - DEBUG4(prom_printf( + CPR_DEBUG(CPR_DEBUG4, "%s: total=%d, npages=%d, compressed=%d, regular=%d\n", - str, sfile.kpages, npages, compressed, regular)); + str, sfile.kpages, npages, compressed, regular); /* * sanity check diff --git a/usr/src/tools/Makefile b/usr/src/tools/Makefile index 3bf6dcf572..82af4e14a5 100644 --- a/usr/src/tools/Makefile +++ b/usr/src/tools/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -60,8 +60,10 @@ sparc_SUBDIRS= \ stabs \ tokenize -i386_SUBDIRS= \ - aw +i386_SUBDIRS= \ + aw \ + elfextract \ + mbh_patch LINTSUBDIRS= \ codereview \ diff --git a/usr/src/tools/ctf/cvt/ctfmerge.c b/usr/src/tools/ctf/cvt/ctfmerge.c index 3afea434de..70ca22c7fe 100644 --- a/usr/src/tools/ctf/cvt/ctfmerge.c +++ b/usr/src/tools/ctf/cvt/ctfmerge.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -879,8 +878,16 @@ main(int argc, char **argv) * don't need to specify labels. */ if (read_ctf(ifiles, nifiles, NULL, merge_ctf_cb, - &wq, require_ctf) == 0) + &wq, require_ctf) == 0) { + /* + * If we're verifying that C files have CTF, it's safe to + * assume that in this case, we're building only from assembly + * inputs. + */ + if (require_ctf) + exit(0); terminate("No ctf sections found to merge\n"); + } pthread_mutex_lock(&wq.wq_queue_lock); wq.wq_nomorefiles = 1; diff --git a/usr/src/tools/ctf/cvt/dwarf.c b/usr/src/tools/ctf/cvt/dwarf.c index 961f7e6610..a7e97dfb23 100644 --- a/usr/src/tools/ctf/cvt/dwarf.c +++ b/usr/src/tools/ctf/cvt/dwarf.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -935,8 +935,11 @@ die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp, (void) die_unsigned(dw, str, DW_AT_byte_size, &sz, DW_ATTR_REQ); tdp->t_size = sz; + /* + * GCC allows empty SOUs as an extension. + */ if ((mem = die_child(dw, str)) == NULL) - terminate("die %llu: %s has no members", off, typename); + goto out; mlastp = &tdp->t_members; @@ -1026,10 +1029,11 @@ die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp, if (tdp->t_name != NULL) free(tdp->t_name); tdp->t_name = new; - + return; } - if (tdp->t_name != NULL && tdp->t_members != NULL) { +out: + if (tdp->t_name != NULL) { ii = xcalloc(sizeof (iidesc_t)); ii->ii_type = II_SOU; ii->ii_name = xstrdup(tdp->t_name); @@ -1066,10 +1070,22 @@ die_sou_resolve(tdesc_t *tdp, tdesc_t **tdpp, void *private) for (ml = tdp->t_members; ml != NULL; ml = ml->ml_next) { if (ml->ml_size == 0) { - if ((ml->ml_size = tdesc_bitsize(ml->ml_type)) == 0) { - dw->dw_nunres++; - return (1); - } + mt = tdesc_basetype(ml->ml_type); + + if ((ml->ml_size = tdesc_bitsize(mt)) != 0) + continue; + + /* + * For empty members, or GCC/C99 flexible array + * members, a size of 0 is correct. + */ + if (mt->t_members == NULL) + continue; + if (mt->t_type == ARRAY && mt->t_ardef->ad_nelems == 0) + continue; + + dw->dw_nunres++; + return (1); } if ((mt = tdesc_basetype(ml->ml_type)) == NULL) { diff --git a/usr/src/cmd/prtdiag/i386/i86pc/Makefile b/usr/src/tools/elfextract/Makefile index 77891ef8e4..7a3e6838d4 100644 --- a/usr/src/cmd/prtdiag/i386/i86pc/Makefile +++ b/usr/src/tools/elfextract/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -21,23 +20,25 @@ # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" -SRCDIR = ../.. -PLATFORM = i86pc -PLATLINKS = +include ../Makefile.tools -include $(SRCDIR)/Makefile.com +PROG = elfextract + +include ../Makefile.tools -FILEMODE = 555 -LDLIBS += -lsmbios -OBJS += smbios.o .KEEP_STATE: all: $(PROG) -include $(SRCDIR)/Makefile.targ +install: all .WAIT $(ROOTONBLDMACHPROG) + +clean: + $(RM) elfextract + +include ../Makefile.targ diff --git a/usr/src/tools/elfextract/elfextract.c b/usr/src/tools/elfextract/elfextract.c new file mode 100644 index 0000000000..71cd685888 --- /dev/null +++ b/usr/src/tools/elfextract/elfextract.c @@ -0,0 +1,274 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdlib.h> +#include <fcntl.h> +#include <strings.h> +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/inttypes.h> +#include <sys/elf.h> +#include <sys/elf_notes.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/statvfs.h> + +static char *pname; +static char *fname; +static char *image; /* pointer to the ELF file in memory */ + +#define ELFSEEK(offset) ((void *)(image + offset)) + +/* + * Extract the PT_LOAD bits and format them into a .s + */ +static void +extract32(Elf32_Ehdr *eh) +{ + Elf32_Phdr *phdr; + caddr_t allphdrs; + int i; + int c; + unsigned char *bytes; + uint_t cnt = 10; + + allphdrs = NULL; + + if (eh->e_type != ET_EXEC) { + (void) fprintf(stderr, "%s: not ET_EXEC, e_type = 0x%x\n", + pname, eh->e_type); + exit(1); + } + if (eh->e_phnum == 0 || eh->e_phoff == 0) { + (void) fprintf(stderr, "%s: no program headers\n", pname); + exit(1); + } + + /* + * Get the program headers. + */ + allphdrs = ELFSEEK(eh->e_phoff); + if (allphdrs == NULL) { + (void) fprintf(stderr, "%s: Failed to get %d program hdrs\n", + pname, eh->e_phnum); + exit(1); + } + + /* + * Find the PT_LOAD section + */ + for (i = 0; i < eh->e_phnum; i++) { + /*LINTED [ELF program header alignment]*/ + phdr = (Elf32_Phdr *)(allphdrs + eh->e_phentsize * i); + + if (phdr->p_type != PT_LOAD) + continue; + + if (phdr->p_memsz == 0) + continue; + + bytes = ELFSEEK(phdr->p_offset); + for (c = 0; c < phdr->p_filesz; ++c) { + if (c % cnt == 0) + (void) printf("\n .byte "); + else + (void) printf(","); + (void) printf("0x%x", bytes[c]); + } + for (; c < phdr->p_memsz; ++c) { + if (c % cnt == 0) { + (void) printf("\n .byte "); + cnt = 20; + } else { + (void) printf(", "); + } + (void) printf("0"); + } + (void) printf("\n"); + return; + } + + (void) fprintf(stderr, "%s: Failed finding PT_LOAD section\n", pname); + exit(1); +} + +static void +extract64(Elf64_Ehdr *eh) +{ + Elf64_Phdr *phdr; + caddr_t allphdrs; + int i; + int c; + unsigned char *bytes; + uint_t cnt = 10; + + allphdrs = NULL; + + if (eh->e_type != ET_EXEC) { + (void) fprintf(stderr, "%s: not ET_EXEC, e_type = 0x%x\n", + pname, eh->e_type); + exit(1); + } + if (eh->e_phnum == 0 || eh->e_phoff == 0) { + (void) fprintf(stderr, "%s: no program headers\n", pname); + exit(1); + } + + /* + * Get the program headers. + */ + allphdrs = ELFSEEK(eh->e_phoff); + if (allphdrs == NULL) { + (void) fprintf(stderr, "%s: Failed to get %d program hdrs\n", + pname, eh->e_phnum); + exit(1); + } + + /* + * Find the PT_LOAD section + */ + for (i = 0; i < eh->e_phnum; i++) { + /*LINTED [ELF program header alignment]*/ + phdr = (Elf64_Phdr *)(allphdrs + eh->e_phentsize * i); + + if (phdr->p_type != PT_LOAD) + continue; + + if (phdr->p_memsz == 0) + continue; + + bytes = ELFSEEK(phdr->p_offset); + for (c = 0; c < phdr->p_filesz; ++c) { + if (c % cnt == 0) + (void) printf("\n .byte "); + else + (void) printf(","); + (void) printf("0x%x", bytes[c]); + } + for (; c < phdr->p_memsz; ++c) { + if (c % cnt == 0) { + (void) printf("\n .byte "); + cnt = 20; + } else { + (void) printf(", "); + } + (void) printf("0"); + } + (void) printf("\n"); + return; + } + + (void) fprintf(stderr, "%s: Failed finding PT_LOAD section\n", pname); + exit(1); +} + +int +main(int argc, char **argv) +{ + int fd; + uchar_t *ident; + void *hdr = NULL; + struct stat stats; + ssize_t r; + uint_t len; + + /* + * we expect one argument -- the elf file + */ + if (argc != 2) { + (void) fprintf(stderr, "usage: %s <unix-elf-file>\n", argv[0]); + exit(1); + } + + pname = strrchr(argv[0], '/'); + if (pname == NULL) + pname = argv[0]; + else + ++pname; + + fname = argv[1]; + fd = open(fname, O_RDONLY); + if (fd < 0) { + (void) fprintf(stderr, "%s: open(%s, O_RDONLY) failed, %s\n", + pname, fname, strerror(errno)); + exit(1); + } + + if (stat(fname, &stats) < 0) { + (void) fprintf(stderr, "%s: stat(%s, ...) failed, %s\n", + pname, fname, strerror(errno)); + exit(1); + } + + len = stats.st_blocks * 512; + len += 0xfff; + len &= ~0xfff; + +#ifdef BUG_6491065_IS_FIXED + /* + * mmap the file + */ + image = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0); + if (image == MAP_FAILED) { + (void) fprintf(stderr, "%s: mmap() of %s failed, %s\n", + pname, fname, strerror(errno)); + exit(1); + } +#else + if ((image = malloc(stats.st_size)) == NULL) { + (void) fprintf(stderr, "%s: out of memory\n", pname); + exit(1); + } + if ((r = read(fd, image, stats.st_size)) != stats.st_size) { + (void) fprintf(stderr, "%s: stat(%s, ...) failed, %s\n", + pname, fname, strerror(errno)); + exit(1); + } +#endif + + ident = ELFSEEK(0); + if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 || + ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) { + (void) fprintf(stderr, "%s: not an ELF file!\n", pname); + exit(1); + } + + if (ident[EI_CLASS] == ELFCLASS32) { + hdr = ELFSEEK(0); + extract32(hdr); + } else if (ident[EI_CLASS] == ELFCLASS64) { + hdr = ELFSEEK(0); + extract64(hdr); + } else { + (void) fprintf(stderr, "%s: Wrong ELF class 0x%x\n", pname, + ident[EI_CLASS]); + exit(1); + } + return (0); +} diff --git a/usr/src/tools/findunref/exception_list b/usr/src/tools/findunref/exception_list index de4da39448..e2db37045c 100644 --- a/usr/src/tools/findunref/exception_list +++ b/usr/src/tools/findunref/exception_list @@ -18,7 +18,7 @@ # # CDDL HEADER END # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -112,7 +112,7 @@ ./src/prototypes */tools ./src/cmd/pools/poold/com/sun/solaris/*/*/package.html -./src/uts/i86pc/io/acpica/cmp_ca.sh +./src/uts/intel/io/acpica/cmp_ca.sh # # Ignore files that are only used by internal packages. diff --git a/usr/src/tools/mbh_patch/Makefile b/usr/src/tools/mbh_patch/Makefile new file mode 100644 index 0000000000..68d2559864 --- /dev/null +++ b/usr/src/tools/mbh_patch/Makefile @@ -0,0 +1,45 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" + +include ../Makefile.tools + +PROG = mbh_patch + +include ../Makefile.tools + +CPPFLAGS += -I../../uts/common + +.KEEP_STATE: + +all: $(PROG) + +install: all .WAIT $(ROOTONBLDMACHPROG) + +clean: + $(RM) mbh_patch + +include ../Makefile.targ diff --git a/usr/src/tools/mbh_patch/mbh_patch.c b/usr/src/tools/mbh_patch/mbh_patch.c new file mode 100644 index 0000000000..404b1f3871 --- /dev/null +++ b/usr/src/tools/mbh_patch/mbh_patch.c @@ -0,0 +1,213 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdlib.h> +#include <fcntl.h> +#include <strings.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/inttypes.h> +#include <sys/elf.h> +#include <sys/elf_notes.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include "sys/multiboot.h" + +static char *pname; +static char *fname; +static char *image; /* pointer to the ELF file in memory */ + +#define ELFSEEK(offset) ((void *)(image + offset)) + +/* + * patch the load address / entry address + * Find the physical load address of the 1st PT_LOAD segment. + * Find the amount that e_entry exceeds that amount. + * Now go back and subtract the excess from the p_paddr of the LOAD segment. + */ +static void +patch64(Elf64_Ehdr *eh) +{ + Elf64_Phdr *phdr; + caddr_t allphdrs; + int i; + int m; + int extra; + multiboot_header_t *mbh; + + allphdrs = NULL; + + if (eh->e_type != ET_EXEC) { + (void) fprintf(stderr, "%s: not ET_EXEC, e_type = 0x%x\n", + pname, eh->e_type); + exit(1); + } + if (eh->e_phnum == 0 || eh->e_phoff == 0) { + (void) fprintf(stderr, "%s: no program headers\n", pname); + exit(1); + } + + /* + * Get the program headers. + */ + allphdrs = ELFSEEK(eh->e_phoff); + if (allphdrs == NULL) { + (void) fprintf(stderr, "%s: Failed to get %d program hdrs\n", + pname, eh->e_phnum); + exit(1); + } + + /* + * Look for multiboot header. It must be 32-bit aligned and + * completely contained in the 1st 8K of the file. + */ + for (m = 0; m < 8192 - sizeof (multiboot_header_t); m += 4) { + mbh = (void *)(image + m); + if (mbh->magic == MB_HEADER_MAGIC) + break; + } + + if (m >= 8192 - sizeof (multiboot_header_t)) { + (void) fprintf(stderr, "%s: Didn't find multiboot header\n", + pname); + exit(1); + } + + /* + * Find the 1:1 mapped PT_LOAD section + */ + for (i = 0; i < eh->e_phnum; i++) { + /*LINTED [ELF program header alignment]*/ + phdr = (Elf64_Phdr *)(allphdrs + eh->e_phentsize * i); + + /* + * Find the low memory 1:1 PT_LOAD section! + */ + if (phdr->p_type != PT_LOAD) + continue; + + if (phdr->p_memsz == 0) + continue; + + if (phdr->p_paddr != phdr->p_vaddr) + continue; + + if (i != 0) { + (void) fprintf(stderr, "%s: identity mapped PT_LOAD" + " wasn't 1st\n", pname); + exit(1); + } + + /* + * Patch the multiboot header fields to get entire + * file loaded, with entry aligned at extra. + */ + if (eh->e_entry != phdr->p_paddr) { + (void) fprintf(stderr, "%s: entry != paddr\n", pname); + exit(1); + } + + /* + * Grub uses the MB header for 64 bit loading. + */ + mbh->load_addr = phdr->p_paddr - phdr->p_offset; + mbh->entry_addr = phdr->p_paddr; + mbh->header_addr = mbh->load_addr + m; +#ifdef VERBOSE + (void) printf("%s ELF64 MB header patched by 0x%0x " + "bytes:\n", fname, extra); + (void) printf("\tload_addr now 0x%x\n", mbh->load_addr); + (void) printf("\tentry_addr now 0x%x\n", mbh->entry_addr); + (void) printf("\theader_addr now 0x%x\n", mbh->header_addr); +#endif + exit(0); + } + + (void) fprintf(stderr, "%s: Didn't find 1:1 mapped PT_LOAD section\n", + pname); + exit(1); +} + + +int +main(int argc, char **argv) +{ + int fd; + uchar_t *ident; + void *hdr = NULL; + + /* + * we expect one argument -- the elf file + */ + if (argc != 2) { + (void) fprintf(stderr, "usage: %s <unix-elf-file>\n", argv[0]); + exit(1); + } + + pname = strrchr(argv[0], '/'); + if (pname == NULL) + pname = argv[0]; + else + ++pname; + + fname = argv[1]; + fd = open(fname, O_RDWR); + if (fd < 0) { + (void) fprintf(stderr, "%s: open(%s, O_RDWR) failed\n", + pname, fname); + exit(1); + } + + /* + * mmap just the 1st 8K -- since that's where the GRUB + * multiboot header must be located. + */ + image = mmap(NULL, 8192, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (image == MAP_FAILED) { + (void) fprintf(stderr, "%s: mmap() of %s failed\n", + pname, fname); + exit(1); + } + + ident = ELFSEEK(0); + if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 || + ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) { + (void) fprintf(stderr, "%s: not an ELF file!\n", pname); + exit(1); + } + + if (ident[EI_CLASS] == ELFCLASS64) { + hdr = ELFSEEK(0); + patch64(hdr); + } else if (ident[EI_CLASS] != ELFCLASS32) { + (void) fprintf(stderr, "%s: Unknown ELF class 0x%x\n", pname, + ident[EI_CLASS]); + exit(1); + } + return (0); +} diff --git a/usr/src/tools/protocmp/arch.c b/usr/src/tools/protocmp/arch.c index 36ca0fb0aa..5d78c3b019 100644 --- a/usr/src/tools/protocmp/arch.c +++ b/usr/src/tools/protocmp/arch.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -37,7 +36,7 @@ assign_arch(const char *architecture) { int arch = 0; -#if defined(sparc) +#if defined(__sparc) if (strcmp(architecture, "sparc") == 0) arch = P_SPARC; else if (strcmp(architecture, "ISA") == 0) @@ -58,7 +57,7 @@ assign_arch(const char *architecture) arch = P_SUN4m; else if (strcmp(architecture, "sparc.sun4v") == 0) arch = P_SUN4v; -#elif defined(i386) +#elif defined(__i386) if (strcmp(architecture, "i386") == 0) arch = P_I386; else if (strcmp(architecture, "ISA") == 0) diff --git a/usr/src/tools/protocmp/list.h b/usr/src/tools/protocmp/list.h index 0cbab88f61..497fd43650 100644 --- a/usr/src/tools/protocmp/list.h +++ b/usr/src/tools/protocmp/list.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,13 +19,18 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +#ifndef _LIST_H +#define _LIST_H +#pragma ident "%Z%%M% %I% %E% SMI" +#ifdef __cplusplus +extern "C" { +#endif /* * Constants @@ -155,3 +159,9 @@ extern void print_type_list(elem_list *list, char file_type); /* Global statistics */ extern int max_list_depth; + +#ifdef __cplusplus +} +#endif + +#endif /* _LIST_H */ diff --git a/usr/src/tools/protocmp/proto_list.c b/usr/src/tools/protocmp/proto_list.c index a4d995ff88..e09a8c03b7 100644 --- a/usr/src/tools/protocmp/proto_list.c +++ b/usr/src/tools/protocmp/proto_list.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -195,7 +194,7 @@ parse_line(char **v, elem *e) e->symsrc = malloc(strlen(v[SYM]) + 1); (void) strcpy(e->symsrc, v[SYM]); if (e->file_type != SYM_LINK_T) -#if defined(sparc) +#if defined(__sparc) if (strncmp(e->symsrc, "sun4/", 5) == 0) e->arch = P_SUN4; else if (strncmp(e->symsrc, "sun4c/", 6) == 0) @@ -210,7 +209,7 @@ parse_line(char **v, elem *e) e->arch = P_SUN4m; else if (strncmp(e->symsrc, "sun4v/", 6) == 0) e->arch = P_SUN4v; -#elif defined(i386) +#elif defined(__i386) if (strncmp(e->symsrc, "i86pc/", 6) == 0) e->arch = P_I86PC; #elif defined(__ppc) diff --git a/usr/src/tools/scripts/Install.sh b/usr/src/tools/scripts/Install.sh index 9d8f99a715..f491412c46 100644 --- a/usr/src/tools/scripts/Install.sh +++ b/usr/src/tools/scripts/Install.sh @@ -20,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #From: "@(#)Install 1.56 96/10/11 SMI" @@ -391,7 +391,7 @@ copy_kernel() { case $KARCH in sun4*) ISA=sparc; MACH=sparc ;; - i86pc) ISA=intel; MACH=i386 ;; + i86*) ISA=intel; MACH=i386 ;; *) fail "${KARCH}: invalid kernel architecture";; esac export MACH @@ -491,7 +491,8 @@ copy_kernel() { # # on x86, add the glommed kernel name to the root archive # - if [[ $KARCH = "i86pc" && $GLOM == "yes" ]]; then + if [[ $MACH = "i386" && $GLOM == "yes" ]]; + then filelist="$INSTALL_FILES/etc/boot/solaris/filelist.ramdisk" mkdir -p `dirname $filelist` echo "platform/$KARCH/$GLOMNAME" >$filelist diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh index 5712e4f5a6..08ba1a27b5 100644 --- a/usr/src/tools/scripts/bfu.sh +++ b/usr/src/tools/scripts/bfu.sh @@ -437,7 +437,6 @@ fail() { print "$*" >& 2 print "bfu aborting" >& 2 rm -f "$local_zone_info_file" - prun 1 exit 1 } @@ -1394,6 +1393,54 @@ smf_bkbfu_repair_sysconfig() { EOF } +# +# Return true if $file exists in $archive. $file may also be a pattern. +# +archive_file_exists() +{ + archive=$1 + file=$2 + + $ZCAT $cpiodir/${archive}${ZFIX} | cpio -it 2>/dev/null | \ + egrep -s "$file" +} + +# +# If we're no longer delivering the eeprom service, remove it from the system, +# as eeprom -I is removed as well. +# +smf_fix_i86pc_profile () { + mfst="var/svc/manifest/platform/i86pc/eeprom.xml" + profile="var/svc/profile/platform_i86pc.xml" + + if [ ! "$karch" = "i86pc" ]; then + return + fi + + if ! archive_file_exists generic.root "^$profile"; then + rm -f $rootprefix/$profile + fi + + if [ ! -f $rootprefix/$mfst ]; then + return + fi + + if archive_file_exists generic.root "^$mfst"; then + return + fi + + rm -f $rootprefix/$mfst + + # + # we must disable via svccfg directly, as manifest-import runs after + # this service tries to run + # + [[ -n "$rootprefix" ]] && + export SVCCFG_REPOSITORY=$rootprefix/etc/svc/repository.db + /tmp/bfubin/svccfg delete -f platform/i86pc/eeprom + [[ -n "$rootprefix" ]] && unset SVCCFG_REPOSITORY +} + smf_apply_conf () { # # Go thru the original manifests and move any that were unchanged @@ -1854,6 +1901,7 @@ EOF esac EOF + smf_fix_i86pc_profile } EXTRACT_LOG=/tmp/bfu-extract-log.$$ @@ -1907,14 +1955,27 @@ while [ $# -gt 0 ]; do shift done +# Variables for x86 platforms boot_is_pcfs=no have_realmode=no -multiboot_archives=no -dca_to_multi=no is_pcfs_boot=no need_datalink=no new_dladm=no +# Set when moving to either directboot or multiboot +multi_or_direct=no + +# +# Shows which type of archives we have, which type of system we are +# running on (before the bfu), and what the failsafe archives are +# (again, before the bfu). failsafe_type is only needed on diskful +# bfu's, so it's not set in the diskless case. +# Possible values: unknown, dca, multiboot, directboot +# +archive_type=unknown +system_type=unknown +failsafe_type=unknown + test $# -ge 1 || usage if [ -x /usr/bin/ppriv ]; then @@ -1952,6 +2013,27 @@ case `echo generic.root*` in *) fail "generic.root missing or in unknown compression format";; esac +# +# Determine what kind of archives we're installing, using the following rules: +# +# 1. If strap.com is present, the archives are pre-multiboot +# 2. If symdef is present, the archives are directboot +# 3. Otherwise, the archives are multiboot +# +if [ $target_isa = i386 ]; then + if [ -f $cpiodir/i86pc.boot$ZFIX ] && \ + archive_file_exists i86pc.boot "strap.com"; then + archive_type=dca + elif [ -f $cpiodir/i86pc.root$ZFIX ] && \ + archive_file_exists i86pc.boot symdef; then + archive_type=directboot + multi_or_direct=yes + else + archive_type=multiboot + multi_or_direct=yes + fi +fi + if [ $diskless = no ]; then root=${2:-/} [[ "$root" = /* ]] || fail "root-dir must be an absolute path" @@ -1962,6 +2044,12 @@ if [ $diskless = no ]; then [[ -f $root/etc/system ]] || \ fail "$root/etc/system not found; local zone target not allowed" + if [ -f $root/boot/platform/i86pc/kernel/unix ]; then + failsafe_type=directboot + elif [ -f $root/boot/multiboot ]; then + failsafe_type=multiboot + fi + # Make sure we extract the sun4u-us3 libc_psr.so.1 if [ -d $root/platform/sun4u -a \ ! -d $root/platform/sun4u-us3 ] @@ -2116,10 +2204,12 @@ if [ ! -x $usr/lib/dbus-daemon ]; then fail "Run $update_script to update D-Bus." fi -if [[ $target_isa = i386 && -f $cpiodir/i86pc.root$ZFIX ]] && \ - $ZCAT $cpiodir/i86pc.root$ZFIX | cpio -it 2>/dev/null | \ - grep multiboot >/dev/null 2>&1 ; then - multiboot_archives=yes +# +# We need biosdev if we're moving from pre-multiboot to multiboot or directboot +# kernels. +# +if [ $target_isa = i386 ] && [ $multi_or_direct = yes ] && [ $diskless = no ] +then prtconf -v | grep biosdev >/dev/null 2>&1 if [ $? -ne 0 ] && [ ! -f $rootprefix/platform/i86pc/multiboot ]; then echo "biosdev cannot be run on this machine." @@ -2199,9 +2289,7 @@ bfucmd=" /usr/bin/pkginfo /usr/bin/pkill /usr/bin/printf - /usr/bin/prun /usr/bin/ps - /usr/bin/pstop /usr/bin/ptree /usr/bin/rm /usr/bin/rmdir @@ -2319,24 +2407,101 @@ do done # -# set up installgrub and friends if transitioning to multiboot +# set up installgrub and friends if transitioning to multiboot or directboot # do this now so ldd can determine library dependencies # +# We split the binaries into two groups: the type where we want to make any +# effort to get the newest version (like symdef and bootadm), and the type +# where any old version will do (like installgrub and biosdev). +# +# If we're bfu'ing across the directboot/multiboot boundary, we need the new +# bootadm and symdef to properly handle menu.lst changes. If the system is +# directboot, we can use the local copies. If the system is multiboot but +# the archives are directboot, we extract the binaries early. Otherwise, +# we're not crossing the boundary, and which one we use doesn't matter. +# +# NB - if bootadm or symdef is ever changed to require a new library, the +# early extraction will blow up horribly. +# +# For testing purposes, a user can set DIRECTBOOT_BIN_DIR in the environment, +# and we'll use that instead. +# MULTIBOOT_BIN_DIR=${MULTIBOOT_BIN_DIR:=${GATE}/public/multiboot} +have_new_bootadm=unknown + +if [ -x $root/boot/solaris/bin/symdef ] && \ + $root/boot/solaris/bin/symdef $root/platform/i86pc/kernel/unix dboot_image +then + root_is_directboot=yes +else + root_is_directboot=no +fi + +# +# A comma-separated list of the command and the archive it's in +# +multiboot_new_cmds=" + sbin/bootadm,generic.sbin + boot/solaris/bin/symdef,i86pc.boot +" + +if [ $multi_or_direct = yes ]; then + for line in $multiboot_new_cmds + do + cmd=${line%,*} + file=${cmd##*/} + archive=${line#*,} + if [ -n "$DIRECTBOOT_BIN_DIR" ] && \ + [ -f $DIRECTBOOT_BIN_DIR/$file ]; then + cp $DIRECTBOOT_BIN_DIR/$file /tmp/bfubin/ + else + if [ $root_is_directboot = yes ]; then + cp $root/$cmd /tmp/bfubin/ + have_new_bootadm=yes + elif [ $archive_type = directboot ]; then + DBOOT_TMPDIR=/tmp/dboot.$$ + trap "rm -rf $DBOOT_TMPDIR" EXIT + OLD_PWD=$(pwd) + rm -rf $DBOOT_TMPDIR + mkdir $DBOOT_TMPDIR + cd $DBOOT_TMPDIR + $ZCAT $cpiodir/${archive}$ZFIX | \ + cpio -id "$cmd" 2>/dev/null + if [ -x $cmd ]; then + cp $cmd /tmp/bfubin/ + have_new_bootadm=yes + fi + cd $OLD_PWD + rm -rf $DBOOT_TMPDIR + trap - EXIT + fi + fi + + # + # If all else fails, grab the local version + # + if [ ! -x /tmp/bfubin/$file ]; then + [ -x /$cmd ] && cp /$cmd /tmp/bfubin + fi + done +fi multiboot_cmds=" /sbin/biosdev /sbin/installgrub - /sbin/bootadm " copying_mboot_cmds=no -if [ $multiboot_archives = yes ]; then +if [ $multi_or_direct = yes ]; then for cmd in $multiboot_cmds do + file=`basename $cmd` if [ -f $cmd ]; then cp $cmd /tmp/bfubin + elif [ -n "$DIRECTBOOT_BIN_DIR" ] && + [ -d $DIRECTBOOT_BIN_DIR ] && + [ -x $DIRECTBOOT_BIN_DIR/$file ]; then + cp $DIRECTBOOT_BIN_DIR/$file /tmp/bfubin/ else - file=`basename $cmd` if [ ! -d $MULTIBOOT_BIN_DIR ]; then echo "$MULTIBOOT_BIN_DIR: not found" elif [ ! -f $MULTIBOOT_BIN_DIR/$file ]; then @@ -2452,9 +2617,10 @@ multiboot_scr=" /boot/solaris/bin/root_archive " -if [ $multiboot_archives = yes ]; then +if [ $multi_or_direct = yes ]; then for cmd in $multiboot_scr do + file=`basename $cmd` if [ -f $cmd ]; then cp $cmd /tmp/bfubin else @@ -2463,7 +2629,6 @@ if [ $multiboot_archives = yes ]; then fail "" fi - file=`basename $cmd` if [ ! -f $MULTIBOOT_BIN_DIR/$file ]; then echo "$MULTIBOOT_BIN_DIR/$file: not found" fail "" @@ -2472,9 +2637,13 @@ if [ $multiboot_archives = yes ]; then cp $MULTIBOOT_BIN_DIR/$file /tmp/bfubin fi - file=`basename $cmd` + # + # We do two substitutions here to replace references to + # both /usr/bin/ and /bin/ with /tmp/bfubin/ + # mv /tmp/bfubin/${file} /tmp/bfubin/${file}- - sed 's/\/usr\/bin\//\/tmp\/bfubin\//g' \ + sed -e 's/\/usr\/bin\//\/tmp\/bfubin\//g' \ + -e 's/\/bin\//\/tmp\/bfubin\//g' \ < /tmp/bfubin/${file}- > /tmp/bfubin/${file} chmod +x /tmp/bfubin/${file} done @@ -3702,7 +3871,7 @@ do smf_check_repository done -MINIMUM_OS_REV=9 +MINIMUM_OS_REV=10 # # Perform additional sanity checks if we are upgrading the live system. @@ -3716,6 +3885,10 @@ then if [ $os_rev -lt $MINIMUM_OS_REV -a "$force_override" = "no" ]; then fail "Cannot bfu from pre-Solaris $MINIMUM_OS_REV" fi + if [ ! -x /usr/sbin/svcadm ]; then + fail "This version of bfu cannot run on pre-Greenline " \ + "(s10_64) systems" + fi # # Filesystem space checks @@ -3748,12 +3921,6 @@ then modload -p exec/intpexec >/dev/null 2>&1 modload -p sys/kaio >/dev/null 2>&1 - # - # Stop init(1M) so extraction/manipulation of inittab is safe. - # - print "Quiescing init ..." - pstop 1 - # umount /lib/libc.so.1 if necessary if [ -n "`mount | grep '^/lib/libc.so.1'`" ] then @@ -3929,6 +4096,10 @@ else if [ $os_rev -lt $MINIMUM_OS_REV -a "$force_override" = "no" ]; then fail "Cannot bfu from pre-Solaris $MINIMUM_OS_REV" fi + if [ ! -x /usr/sbin/svcadm ]; then + fail "This version of bfu cannot run on pre-Greenline " \ + "(s10_64) systems" + fi fi export PATH=/tmp/bfubin:$PATH @@ -4163,6 +4334,15 @@ check_multi_to_dca_boot() check_dca_to_multiboot() { + bootdev=`grep p0:boot $rootprefix/etc/vfstab | \ + grep pcfs | nawk '{print $1}'` + if [ "$bootdev" != "" ]; then + is_pcfs_boot=yes + fi + if [ $system_type != dca ]; then + return + fi + # ensure bootpath is in $rootprefix/boot/solaris/bootenv.rc # It's ok to put a meta device path in there bootenvrc=$rootprefix/boot/solaris/bootenv.rc @@ -4175,36 +4355,52 @@ check_dca_to_multiboot() echo "setprop bootpath '$bootpath'" >> $bootenvrc fi - bootdev=`grep p0:boot $rootprefix/etc/vfstab | \ - grep pcfs | nawk '{print $1}'` - if [ "$bootdev" != "" ]; then - is_pcfs_boot=yes - fi - if [ ! -f $rootprefix/boot/mdboot ]; then - return - fi - dca_to_multi=yes rm -f $rootprefix/boot/mdboot } # +# Figure out the boot architecture of the current system: +# 1. If dboot_image is in unix, it's a dboot system +# 2. Otherwise, if multiboot is present, it's a multiboot system +# 3. Otherwise, it's a pre-multiboot system +# +# This is called before we lay down the new archives. +# +check_system_type() +{ + if [ -x $root/boot/solaris/bin/symdef ] && \ + $root/boot/solaris/bin/symdef $root/platform/i86pc/kernel/unix \ + dboot_image; then + system_type=directboot + elif [ -x $root/platform/i86pc/multiboot ]; then + system_type=multiboot + else + system_type=dca + fi +} + +# # Detect SVM root and return the list of raw devices under the mirror # get_rootdev_list() { - metadev=`grep -v "^#" $rootprefix/etc/vfstab | \ - grep "[ ]/[ ]" | nawk '{print $2}'` - if [[ $metadev = /dev/rdsk/* ]]; then - rootdevlist=`echo "$metadev" | sed -e "s#/dev/rdsk/##"` - elif [[ $metadev = /dev/md/rdsk/* ]]; then - metavol=`echo "$metadev" | sed -e "s#/dev/md/rdsk/##"` - rootdevlist=`metastat -p $metavol |\ - grep -v "^$metavol[ ]" | nawk '{print $4}'` - fi - for rootdev in $rootdevlist - do - echo /dev/rdsk/$rootdev - done + if [ -f $rootprefix/etc/lu/GRUB_slice ]; then + grep '^PHYS_SLICE' $rootprefix/etc/lu/GRUB_slice | cut -d= -f2 + else + metadev=`grep -v "^#" $rootprefix/etc/vfstab | \ + grep "[ ]/[ ]" | nawk '{print $2}'` + if [[ $metadev = /dev/rdsk/* ]]; then + rootdevlist=`echo "$metadev" | sed -e "s#/dev/rdsk/##"` + elif [[ $metadev = /dev/md/rdsk/* ]]; then + metavol=`echo "$metadev" | sed -e "s#/dev/md/rdsk/##"` + rootdevlist=`metastat -p $metavol |\ + grep -v "^$metavol[ ]" | nawk '{print $4}'` + fi + for rootdev in $rootdevlist + do + echo /dev/rdsk/$rootdev + done + fi } # @@ -4256,10 +4452,13 @@ setup_stubboot() # install_grub() { - STAGE1=$root/boot/grub/stage1 - STAGE2=$root/boot/grub/stage2 + STAGE1=$rootprefix/boot/grub/stage1 + STAGE2=$rootprefix/boot/grub/stage2 - if [ $is_pcfs_boot = no ]; then + if [ -x $rootprefix/boot/solaris/bin/update_grub ]; then + /tmp/bfubin/ksh $rootprefix/boot/solaris/bin/update_grub \ + -R $root + elif [ $is_pcfs_boot = no ]; then get_rootdev_list | while read rootdev do print "Install grub on $rootdev" @@ -4291,6 +4490,79 @@ install_grub() fi } +# +# We check for several possibilites of a bootenv.rc line: +# +# 1. setprop name 'value' +# 2. setprop name "value" +# 3. setprop name value +# +parse_bootenv_line() +{ + line=$1 + value=`echo $line | grep "'" | cut -d\' -f2` + if [ -z "$value" ]; then + value=`echo $line | grep "\"" | cut -d\" -f2` + if [ -z "$value" ]; then + value=`echo $line | cut -d' ' -f3-` + fi + fi + echo $value +} + +update_bootenv() +{ + bootenvrc=$rootprefix/boot/solaris/bootenv.rc + bootenvrc_updated=0 + + # Note: the big space below is actually a space and tab + boot_file=`grep '^setprop[ ]\{1,\}boot-file\>' $bootenvrc` + if [ -n "$boot_file" ]; then + file=`parse_bootenv_line "$boot_file"` + if [ -n "$file" ]; then + PATH=/tmp/bfubin /tmp/bfubin/bootadm set-menu kernel="$file" + bootenvrc_updated=1 + fi + fi + + console=`grep '^setprop[ ]\{1,\}console\>' $bootenvrc` + if [ -z "$console" ]; then + console=`grep '^setprop[ ]\{1,\}input-device\>' \ + $bootenvrc` + fi + if [ -n "$console" ]; then + cons=`parse_bootenv_line "$console"` + fi + boot_args=`grep '^setprop[ ]\{1,\}boot-args\>' $bootenvrc` + if [ -n "boot_args" ]; then + args=`parse_bootenv_line "$boot_args"` + fi + if [ -n "$cons" ] && [ -n "$args" ]; then + # If args starts with a -B, remove it and add a comma instead + if echo $args | grep '^-B ' >/dev/null; then + new_args=`echo $args | sed 's/^-B //'` + args_line="-B console=$cons,$new_args" + else + args_line="-B console=$cons $args" + fi + elif [ -n "$cons" ]; then + args_line="-B console=$cons" + elif [ -n "$args" ]; then + args_line="$args" + else + args_line="" + fi + if [ -n "$args_line" ]; then + PATH=/tmp/bfubin /tmp/bfubin/bootadm set-menu args="$args_line" + bootenvrc_updated=1 + fi + + if [ $bootenvrc_updated = 1 ]; then + egrep -v '^setprop[ ]+(console|boot-file|boot-args|input-device)[ ]' $bootenvrc > ${bootenvrc}.new + [ -s ${bootenvrc}.new ] && mv ${bootenvrc}.new $bootenvrc + fi +} + get_biosdisk() { rootdev=$1 @@ -4310,12 +4582,32 @@ get_biosdisk() # update_grub_menu() { - BOOT_PROG=/platform/i86pc/multiboot - BOOT_ARCHIVE=/platform/i86pc/boot_archive MENU=$rootprefix/boot/grub/menu.lst grubhd=$1 + if [ $archive_type = multiboot ]; then + BOOT_PROG="kernel /platform/i86pc/multiboot" + BOOT_ARCHIVE="module /platform/i86pc/boot_archive" + else + # + # directboot archives + # + BOOT_PROG="kernel\$ /platform/i86pc/kernel/\$ISADIR/unix" + BOOT_ARCHIVE="module\$ /platform/i86pc/\$ISADIR/boot_archive" + fi + + # + # The failsafe archives may be different than the boot archives + # + if [ -x /boot/platform/i86pc/kernel/unix ]; then + BOOT_FAILSAFE_FILE="/boot/platform/i86pc/kernel/unix" + BOOT_FAILSAFE_SUFFIX="" + else + BOOT_FAILSAFE_FILE="/boot/multiboot" + BOOT_FAILSAFE_SUFFIX="kernel/unix" + fi + # # Append some useful entries to the existing menu # @@ -4331,12 +4623,12 @@ update_grub_menu() echo "#splashimage=$grubhd/boot/grub/splash.xpm.gz" >> $MENU echo "title Solaris" >> $MENU echo " root $grubhd" >> $MENU - echo " kernel ${BOOT_PROG}" >> $MENU - echo " module ${BOOT_ARCHIVE}" >> $MENU + echo " ${BOOT_PROG}" >> $MENU + echo " ${BOOT_ARCHIVE}" >> $MENU echo "GRUB menu entry 'Solaris' boots to eeprom(1m) settings" - if [ -f ${rootprefix}/boot/multiboot ] && + if [ -f ${rootprefix}/$BOOT_FAILSAFE_FILE ] && [ -f ${rootprefix}/boot/x86.miniroot-safe ] ; then TTY=`grep "^setprop input-device" \ @@ -4351,27 +4643,42 @@ update_grub_menu() FS_CONSOLE="-B console=${TTY}" fi - echo "title Solaris failsafe" >> $MENU - echo " root $grubhd" >> $MENU - echo " kernel /boot/multiboot kernel/unix $FS_CONSOLE -s" \ - >> $MENU - echo " module /boot/x86.miniroot-safe" >> $MENU +cat >>$MENU <<EOF +title Solaris failsafe + root $grubhd + kernel $BOOT_FAILSAFE_FILE $BOOT_FAILSAFE_SUFFIX $FS_CONSOLE -s + module /boot/x86.miniroot-safe +EOF fi } +bootadm_f_flag="" + install_failsafe() { - if [ ! -f /boot/multiboot -o ! -f /boot/x86.miniroot-safe ] && \ - [ -x ${GATEPATH}/public/bin/update_failsafe ] ; then - echo Updating boot/multiboot and boot/x86.miniroot-safe + if [ "$root" != "/" ] || \ + [ -f /boot/x86.miniroot-safe ] || \ + [ -x ${GATEPATH}/public/bin/update_failsafe ]; then + # + # Either we're not bfu'ing /, or the failsafe archives were + # already installed, or update_failsafe is not available. + # If the old failsafe archives were multiboot, clear out the + # directboot kernel. + # + if [ $failsafe_type = multiboot ]; then + rm -f $rootprefix/boot/platform/i86pc/kernel/unix + fi + else + echo "Updating failsafe archives" ${GATEPATH}/public/bin/update_failsafe + + # Force bootadm to update the failsafe entry + bootadm_f_flag="-f" fi } setup_grub_menu() { - BOOT_PROG=/platform/i86pc/multiboot - BOOT_ARCHIVE=/platform/i86pc/boot_archive MENU=$rootprefix/boot/grub/menu.lst get_rootdev_list | while read rootdev @@ -4420,8 +4727,6 @@ setup_grub_menu() # build_boot_archive() { - echo "Create ${rootprefix}/platform/i86pc/boot_archive" - # # We should be able to run bootadm here but that's a # little more complicated than one would think @@ -4430,7 +4735,7 @@ build_boot_archive() cr_args=${rootprefix:+ -R $rootprefix} LD_LIBRARY_PATH=/tmp/bfulib PATH=/tmp/bfubin \ - /tmp/bfubin/ksh /tmp/bfubin/create_ramdisk $cr_args + /tmp/bfubin/ksh $rootprefix/boot/solaris/bin/create_ramdisk $cr_args # # Disable the boot-archive service on the first boot @@ -4484,6 +4789,58 @@ dir_is_inherited() { [ "$3" = "/$dir" ] && return 0 || return 1 } +check_boot_env() +{ + if [ $multi_or_direct = yes ]; then + if [ $archive_type != $system_type ]; then + install_failsafe + [ $system_type = dca ] && setup_grub_menu + + if [ $have_new_bootadm = yes ] || \ + [ -x /tmp/bfubin/symdef ] && \ + [ -x /tmp/bfubin/bootadm ] && \ + /tmp/bfubin/symdef /tmp/bfubin/bootadm \ + dboot_or_multiboot; then + if [[ -z $rootprefix ]]; then + PATH=/tmp/bfubin /tmp/bfubin/bootadm \ + -m upgrade $bootadm_f_flag + else + PATH=/tmp/bfubin /tmp/bfubin/bootadm \ + -m upgrade -R $rootprefix \ + $bootadm_f_flag + fi + install_grub + [ $archive_type = directboot ] && update_bootenv + else + install_grub + cat >&2 <<EOF + +WARNING: Cannot find new bootadm. If bfu'ing across the multiboot/directboot +boundary, you will need to manually change menu.lst. See +http://www.sun.com/msg/SUNOS-8000-CF for details. + +EOF + fi + + # + # If we're going backwards, we need to remove the + # symdef binary. + # + if [ -f $rootprefix/boot/solaris/bin/symdef ] && \ + [ $archive_type = multiboot ] + then + rm -f $rootprefix/boot/solaris/bin/symdef \ + $rootprefix/boot/solaris/bin/update_grub + fi + elif [ $failsafe_type = multiboot ]; then + rm -f $rootprefix/boot/platform/i86pc/kernel/unix + fi + build_boot_archive + else + disable_boot_service + fi +} + mondo_loop() { typeset pkgroot typeset pkg @@ -4512,16 +4869,15 @@ mondo_loop() { if [ "$karch" = "i86pc" -a "$diskless" = "no" -a "$zone" = "global" ] then remove_properties + check_system_type if boot_is_upgradeable $root && \ - [ -f $cpiodir/i86pc.boot$ZFIX ] && \ - $ZCAT $cpiodir/i86pc.boot$ZFIX | cpio -it | \ - grep strap.com >/dev/null 2>&1 ; then + [ $archive_type = dca ]; then check_multi_to_dca_boot print "\nUpdating realmode boot loaders\n" update_realmode_booters $root setup_pboot fi - if [ $multiboot_archives = yes ]; then + if [ $multi_or_direct = yes ]; then check_dca_to_multiboot if [ $is_pcfs_boot = yes ]; then setup_stubboot @@ -6343,7 +6699,7 @@ mondo_loop() { print "Restoring configuration files ... \c" >> $EXTRACT_LOG filelist $zone | cpio -pdmu bfu.parent 2>>$EXTRACT_LOG || \ extraction_error "restoring configuration files" - if [ $multiboot_archives = no ]; then + if [ $multi_or_direct = no ]; then if [ $have_realmode = yes ]; then if [ -d bfu.realmode ]; then ( cd bfu.realmode ; realmode_filelist | \ @@ -6508,16 +6864,7 @@ mondo_loop() { if [ $target_isa = i386 ] && [[ $rootslice = /dev/rdsk/* || \ $rootslice = /dev/md/rdsk/* ]]; then - if [ $multiboot_archives = yes ]; then - if [ $dca_to_multi = yes ]; then - install_failsafe - setup_grub_menu - install_grub - fi - build_boot_archive - else - disable_boot_service - fi + check_boot_env fi # Check for damage due to CR 6379341. This was actually fixed @@ -6575,7 +6922,7 @@ mondo_loop() { print "\nFor each file in conflict, your version has been restored." print "The new versions are under $rootprefix/bfu.conflicts." print "\nMAKE SURE YOU RESOLVE ALL CONFLICTS BEFORE REBOOTING.\n" - if [ $multiboot_archives = yes ]; then + if [ $multi_or_direct = yes ]; then print "To install resolved changes required for reboot in the boot" print "archive, invoke 'bootadm update-archive${cr_args}'\n" fi @@ -6707,8 +7054,4 @@ print "Exiting post-bfu protected environment. To reenter, type:" print LD_NOAUXFLTR=1 LD_LIBRARY_PATH=/tmp/bfulib $ldlib64 PATH=/tmp/bfubin \ /tmp/bfubin/ksh -# Allow init(1M) to continue, if we're leaving. -print "Reactivating init ..." -prun 1 - exit 0 diff --git a/usr/src/uts/Makefile.targ b/usr/src/uts/Makefile.targ index 5f898515f8..65efe774de 100644 --- a/usr/src/uts/Makefile.targ +++ b/usr/src/uts/Makefile.targ @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -76,8 +76,8 @@ MOD_LINT_LIB = $(LINT_LIB_DIR)/llib-l$(LINT_MODULE).ln $(MOD_LINT_LIB): $(LINT_LIB_DIR) $(LINTS) @-$(ECHO) "\n$(OBJS_DIR)/$(MODULE): (library construction):" - @$(LINT) -o $(LINT_MODULE) $(LINTFLAGS) $(LINTS) - @$(MV) $(@F) $@ + @$(LINT) -o $(LINT_MODULE)-$(OBJS_DIR) $(LINTFLAGS) $(LINTS) + @$(MV) llib-l$(LINT_MODULE)-$(OBJS_DIR).ln $@ $(LINT_MODULE).lint: $(MOD_LINT_LIB) $(LINT_LIB) $(GEN_LINT_LIB) @-$(ECHO) "\n$(OBJS_DIR)/$(LINT_MODULE): global crosschecks:" @@ -109,7 +109,7 @@ $(LINTS_DIR)/modstubs.ln: $(MODSTUBS) # # release: contents of $(RELEASE) (Spaces replaced by '_') # version: contents of $(PATCHID) (Spaces replaced by '_') -# machine: contents of $(PLATFORM) +# machine: contents of $(UNAME_M) # # Build environment information is only contained in the comment section. # @@ -123,7 +123,7 @@ $(INTERNAL_RELEASE_BUILD)VERSION_STRING = $(ECHO) $(PATCHID) $(OBJS_DIR)/vers.o: $(OBJECTS) $(COMPILE.c) -DUTS_RELEASE=\"`$(ECHO) $(RELEASE) | sed -e 's/ /_/g'`\" \ -DUTS_VERSION=\"`$(VERSION_STRING) | sed -e 's/ /_/g'`\" \ - -DUTS_PLATFORM=\"$(PLATFORM)\" -o $@ $(SRC)/uts/common/os/vers.c + -DUTS_PLATFORM=\"$(UNAME_M)\" -o $@ $(SRC)/uts/common/os/vers.c $(CTFCONVERT_O) $(POST_PROCESS_O) @@ -444,4 +444,5 @@ lint32: @for file in $(LINT32_FILES); do \ if [ ! -f $$file ]; then touch $$file; fi \ done + FRC: diff --git a/usr/src/uts/Makefile.uts b/usr/src/uts/Makefile.uts index 508560c90e..af2765ac4d 100644 --- a/usr/src/uts/Makefile.uts +++ b/usr/src/uts/Makefile.uts @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -213,6 +213,8 @@ AS_CPPFLAGS = $(ALWAYS_DEFS) $(ALL_DEFS) $(CONFIG_DEFS) $(AS_DEFS) \ # Override the default, the kernel is squeaky clean CERRWARN = -errtags=yes -errwarn=%all +C99MODE = $(C99_ENABLE) + CFLAGS_uts = CFLAGS_uts += $(STAND_FLAGS_$(CLASS)) CFLAGS_uts += $(CCVERBOSE) @@ -220,7 +222,6 @@ CFLAGS_uts += $(ILDOFF) CFLAGS_uts += $(XAOPT) CFLAGS_uts += $(CTF_FLAGS) CFLAGS_uts += $(CERRWARN) -CFLAGS_uts += $(C99_ENABLE) CFLAGS_uts += $(CGLOBALSTATIC) CFLAGS_uts += $(EXTRA_CFLAGS) @@ -373,29 +374,12 @@ CTFMERGE_GENUNIX_MERGE = \ $$cmd $(OBJECTS) $(CTFEXTRAOBJS) $(IPCTF_TARGET) # -# Used to copy CTF data from the sun4u genunix to the sun4m genunix. While -# we may lose some genunix-specific sun4m-only data, there really isn't any -# other way, since individual ctfmerges on the sun4u and sun4m genunix -# modules will result in differing type indices for the same types, and we -# can't uniquify a given non-genunix module against two genunix modules. -# -CTFMERGE_COPY_CTF_DATA = \ - @if [ -f $(CTFMERGE_GENUNIX) ] ; then \ - cmd="$(CTFMERGE) $(CTFMRGFLAGS) -c $(CTFMERGE_GENUNIX) $@" ; \ - echo $$cmd ; \ - $$cmd ; \ - else \ - echo "WARNING: $(CTFMERGE_GENUNIX) not built. " \ - "CTF data will be incomplete" ; \ - fi - -# # We ctfmerge the ip objects into genunix to maximize the number of common types # found there, thus maximizing the effectiveness of uniquification. We don't # want the genunix build to have to know about the individual ip objects, so we # put them in an archive. The genunix ctfmerge then includes this archive. # -IPCTF = $(IPDRV_DIR)/$(OBJS_DIR)/ipctf.a +IPCTF = $(IPDRV_DIR)/$(OBJS_DIR)/ipctf.a # # Rule for building fake shared libraries used for symbol resolution @@ -578,15 +562,28 @@ USR_PLAT_LINKS = $(PLAT_LINKS:%=$(USR_PLAT_DIR)/%) USR_PLAT_LINKS_2 = $(PLAT_LINKS_2:%=$(USR_PLAT_DIR)/%) # -# Collection of all relevant, delivered kernel modules. +# Collection of all relevant, delivered kernel modules. +# +# Note that we insist on building genunix first, because everything else +# uniquifies against it. When doing a 'make' from usr/src/uts/, we'll enter +# the platform directories first. These will cd into the corresponding genunix +# directory and build it. So genunix /shouldn't/ get rebuilt when we get to +# building all the kernel modules. However, due to an as-yet-unexplained +# problem with dependencies, sometimes it does get rebuilt, which then messes +# up the other modules. So we always force the issue here rather than try to +# build genunix in parallel with everything else. # -KMODS = $(DRV_KMODS) $(EXEC_KMODS) $(FS_KMODS) $(SCHED_KMODS) $(TOD_KMODS) \ - $(STRMOD_KMODS) $(SYS_KMODS) $(MISC_KMODS) $(NLMISC_KMODS) \ - $(MACH_KMODS) $(CPU_KMODS) $(GENUNIX_KMODS) \ - $(GSS_KMODS) $(MMU_KMODS) $(DACF_KMODS) $(EXPORT_KMODS) \ - $(IPP_KMODS) $(CRYPTO_KMODS) $(CRYPTO_EK_KMODS) $(PCBE_KMODS) \ - $(DRV_KMODS_$(CLASS)) $(MISC_KMODS_$(CLASS)) $(MAC_KMODS) \ - $(DEVNAME_KMODS) +PARALLEL_KMODS = $(DRV_KMODS) $(EXEC_KMODS) $(FS_KMODS) $(SCHED_KMODS) \ + $(TOD_KMODS) $(STRMOD_KMODS) $(SYS_KMODS) $(MISC_KMODS) \ + $(NLMISC_KMODS) $(MACH_KMODS) $(CPU_KMODS) $(GSS_KMODS) \ + $(MMU_KMODS) $(DACF_KMODS) $(EXPORT_KMODS) $(IPP_KMODS) \ + $(CRYPTO_KMODS) $(CRYPTO_EK_KMODS) $(PCBE_KMODS) \ + $(DRV_KMODS_$(CLASS)) $(MISC_KMODS_$(CLASS)) $(MAC_KMODS) \ + $(DEVNAME_KMODS) + +KMODS = $(GENUNIX_KMODS) $(PARALLEL_KMODS) + +$(PARALLEL_KMODS): $(GENUNIX_KMODS) $(CLOSED_BUILD)CLOSED_KMODS = $(CLOSED_DRV_KMODS) $(CLOSED_TOD_KMODS) \ $(CLOSED_MISC_KMODS) \ @@ -596,8 +593,7 @@ LINT_KMODS = $(DRV_KMODS) $(EXEC_KMODS) $(FS_KMODS) $(SCHED_KMODS) \ $(TOD_KMODS) $(STRMOD_KMODS) $(SYS_KMODS) $(MISC_KMODS) \ $(MACH_KMODS) $(GSS_KMODS) $(DACF_KMODS) $(IPP_KMODS) \ $(CRYPTO_KMODS) $(PCBE_KMODS) $(DEVNAME_KMODS) \ - $(DRV_KMODS_$(CLASS)) $(MISC_KMODS_$(CLASS)) $(MAC_KMODS) \ - $(DEVNAME_KMODS) + $(DRV_KMODS_$(CLASS)) $(MISC_KMODS_$(CLASS)) $(MAC_KMODS) $(CLOSED_BUILD)CLOSED_LINT_KMODS = $(CLOSED_DRV_KMODS) $(CLOSED_TOD_KMODS) \ $(CLOSED_MISC_KMODS) $(CLOSED_DRV_KMODS_$(CLASS)) diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index 946fececfa..927ded787f 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -31,10 +31,7 @@ i386_CORE_OBJS += \ avintr.o \ - pit.o \ - pic.o \ - hardclk.o \ - i8254.o + pic.o sparc_CORE_OBJS += @@ -63,6 +60,7 @@ COMMON_CORE_OBJS += \ rctl_proc.o \ rwlock.o \ seg_kmem.o \ + string.o \ thread_intr.o \ vm_page.o \ vm_pagelist.o @@ -272,6 +270,7 @@ GENUNIX_OBJS += \ sleepq.o \ softint.o \ space.o \ + sscanf.o \ ssig.o \ stat.o \ statfs.o \ @@ -281,7 +280,6 @@ GENUNIX_OBJS += \ stream.o \ streamio.o \ strext.o \ - string.o \ strsubr.o \ strsun.o \ subr.o \ @@ -356,7 +354,14 @@ GENUNIX_OBJS += \ # # Stubs for the stand-alone linker/loader # -GENSTUBS_OBJS += kobj_stubs.o +sparc_GENSTUBS_OBJS = \ + kobj_stubs.o + +i386_GENSTUBS_OBJS = + +COMMON_GENSTUBS_OBJS = + +GENSTUBS_OBJS += $(COMMON_GENSTUBS_OBJS) $($(MACH)_GENSTUBS_OBJS) # # DTrace and DTrace Providers @@ -1203,14 +1208,20 @@ DES_OBJS += des_crypt.o des_cbc_crypt.o des_impl.o des_ks.o des_soft.o DLBOOT_OBJS += bootparam_xdr.o nfs_dlinet.o scan.o -KRTLD_OBJS += \ - kobj_bootflags.o \ - getoptstr.o \ - kobj.o \ - kobj_kdi.o \ - kobj_lm.o \ +sparc_KRTLD_OBJS = \ kobj_subr.o +i386_KRTLD_OBJS = + +COMMON_KRTLD_OBJS = \ + kobj_bootflags.o \ + getoptstr.o \ + kobj.o \ + kobj_kdi.o \ + kobj_lm.o + +KRTLD_OBJS += $(COMMON_KRTLD_OBJS) $($(MACH)_KRTLD_OBJS) + MOD_OBJS += modctl.o modsubr.o modsysfile.o modconf.o modhash.o STRPLUMB_OBJS += strplumb.o octet.o diff --git a/usr/src/uts/common/cpr/cpr_driver.c b/usr/src/uts/common/cpr/cpr_driver.c index deb6241319..a23a9cbf7c 100644 --- a/usr/src/uts/common/cpr/cpr_driver.c +++ b/usr/src/uts/common/cpr/cpr_driver.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -67,7 +66,8 @@ cpr_suspend_devices(dev_info_t *dip) return (ENXIO); if (!cpr_is_real_device(dip)) continue; - DEBUG2(errp("Suspending device %s\n", devi_string(dip, buf))); + CPR_DEBUG(CPR_DEBUG2, "Suspending device %s\n", + devi_string(dip, buf)); ASSERT((DEVI(dip)->devi_cpr_flags & DCF_CPR_SUSPENDED) == 0); if (!i_ddi_devi_attached(dip)) @@ -78,8 +78,9 @@ cpr_suspend_devices(dev_info_t *dip) if (error == DDI_SUCCESS) DEVI(dip)->devi_cpr_flags |= DCF_CPR_SUSPENDED; else { - DEBUG2(errp("WARNING: Unable to suspend device %s\n", - devi_string(dip, buf))); + CPR_DEBUG(CPR_DEBUG2, + "WARNING: Unable to suspend device %s\n", + devi_string(dip, buf)); cpr_err(CE_WARN, "Unable to suspend device %s.", devi_string(dip, buf)); cpr_err(CE_WARN, "Device is busy or does not " @@ -130,8 +131,8 @@ cpr_resume_devices(dev_info_t *start, int resume_failed) * the entire tree to clear the suspend flag. */ if (did_suspend && !error) { - DEBUG2(errp("Resuming device %s\n", - devi_string(dip, buf))); + CPR_DEBUG(CPR_DEBUG2, "Resuming device %s\n", + devi_string(dip, buf)); /* * If a device suspended by cpr gets detached during * the resume process (for example, due to hotplugging) @@ -139,17 +140,17 @@ cpr_resume_devices(dev_info_t *start, int resume_failed) * we'll have problems. */ if (!i_ddi_devi_attached(dip)) { - DEBUG2(errp("WARNING: Skipping %s, device " - "not ready for resume\n", - devi_string(dip, buf))); + CPR_DEBUG(CPR_DEBUG2, "WARNING: Skipping " + "%s, device not ready for resume\n", + devi_string(dip, buf)); cpr_err(CE_WARN, "Skipping %s, device " "not ready for resume", devi_string(dip, buf)); } else if (devi_attach(dip, DDI_RESUME) != DDI_SUCCESS) { - DEBUG2(errp( + CPR_DEBUG(CPR_DEBUG2, "WARNING: Unable to resume device %s\n", - devi_string(dip, buf))); + devi_string(dip, buf)); cpr_err(CE_WARN, "Unable to resume device %s", devi_string(dip, buf)); error = ENXIO; @@ -243,6 +244,11 @@ cpr_is_real_device(dev_info_t *dip) void cpr_power_down(void) { +#if defined(__sparc) + /* + * XXX This platform firmware implementation dependency + * doesn't belong in common code! + */ int is_defined = 0; char *wordexists = "p\" power-off\" find nip swap l! "; char *req = "power-off"; @@ -252,7 +258,8 @@ cpr_power_down(void) */ prom_interpret(wordexists, (uintptr_t)&is_defined, 0, 0, 0, 0); if (is_defined) { - DEBUG1(errp("\ncpr: %s...\n", req)); + CPR_DEBUG(CPR_DEBUG1, "\ncpr: %s...\n", req); prom_interpret(req, 0, 0, 0, 0, 0); } +#endif } diff --git a/usr/src/uts/common/cpr/cpr_dump.c b/usr/src/uts/common/cpr/cpr_dump.c index 46269c4955..99f5cea43d 100644 --- a/usr/src/uts/common/cpr/cpr_dump.c +++ b/usr/src/uts/common/cpr/cpr_dump.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -214,9 +214,9 @@ cpr_write_header(vnode_t *vp) upages = cpr_count_upages(REGULAR_BITMAP, cpr_setbit); cdump.cdd_dumppgsize = kpages - vpages + upages; cpr_pages_tobe_dumped = cdump.cdd_dumppgsize; - DEBUG7(errp( + CPR_DEBUG(CPR_DEBUG7, "\ncpr_write_header: kpages %ld - vpages %ld + upages %ld = %d\n", - kpages, vpages, upages, cdump.cdd_dumppgsize)); + kpages, vpages, upages, cdump.cdd_dumppgsize); /* * Some pages contain volatile data (cpr_buf and storage area for @@ -247,8 +247,8 @@ cpr_write_header(vnode_t *vp) */ if (!(CPR->c_flags & C_COMPRESSING) && (STAT->cs_nocomp_statefsz > STAT->cs_est_statefsz)) { - if (cpr_debug & (LEVEL1 | LEVEL7)) - errp("cpr_write_header: STAT->cs_nocomp_statefsz > " + if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG7)) + prom_printf("cpr_write_header: STAT->cs_nocomp_statefsz > " "STAT->cs_est_statefsz\n"); return (ENOSPC); } @@ -274,8 +274,8 @@ cpr_write_terminator(vnode_t *vp) cpr_term.real_statef_size = STAT->cs_real_statefsz + btod(cpr_wptr - cpr_buf) * DEV_BSIZE; - DEBUG9(errp("cpr_dump: Real Statefile Size: %ld\n", - STAT->cs_real_statefsz)); + CPR_DEBUG(CPR_DEBUG9, "cpr_dump: Real Statefile Size: %ld\n", + STAT->cs_real_statefsz); cpr_tod_get(&cpr_term.tm_shutdown); @@ -338,7 +338,7 @@ cpr_write_statefile(vnode_t *vp) */ str = "cpr_write_statefile:"; spages = i_cpr_count_sensitive_kpages(REGULAR_BITMAP, cpr_clrbit); - DEBUG7(errp("%s untag %ld sens pages\n", str, spages)); + CPR_DEBUG(CPR_DEBUG7, "%s untag %ld sens pages\n", str, spages); /* * now it's OK to call a driver that makes allocations @@ -351,7 +351,8 @@ cpr_write_statefile(vnode_t *vp) */ error = i_cpr_dump_sensitive_kpages(vp); if (error) { - DEBUG7(errp("%s cpr_dump_sensitive_kpages() failed!\n", str)); + CPR_DEBUG(CPR_DEBUG7, + "%s cpr_dump_sensitive_kpages() failed!\n", str); return (error); } @@ -360,7 +361,8 @@ cpr_write_statefile(vnode_t *vp) */ error = cpr_dump_regular_pages(vp); if (error) { - DEBUG7(errp("%s cpr_dump_regular_pages() failed!\n", str)); + CPR_DEBUG(CPR_DEBUG7, + "%s cpr_dump_regular_pages() failed!\n", str); return (error); } @@ -371,7 +373,7 @@ cpr_write_statefile(vnode_t *vp) cpr_regular_pgs_dumped); if (error) { - errp("\n%s page count mismatch!\n", str); + prom_printf("\n%s page count mismatch!\n", str); #ifdef DEBUG if (cpr_test_mode) debug_enter(NULL); @@ -443,7 +445,8 @@ cpr_dump(vnode_t *vp) * compressed before they are saved into the storage area. */ if (error = i_cpr_save_sensitive_kpages()) { - DEBUG7(errp("cpr_dump: save_sensitive_kpages failed!\n")); + CPR_DEBUG(CPR_DEBUG7, + "cpr_dump: save_sensitive_kpages failed!\n"); return (error); } @@ -453,7 +456,8 @@ cpr_dump(vnode_t *vp) * count regular and sensitive kpages. */ if (error = cpr_write_header(vp)) { - DEBUG7(errp("cpr_dump: cpr_write_header() failed!\n")); + CPR_DEBUG(CPR_DEBUG7, + "cpr_dump: cpr_write_header() failed!\n"); return (error); } @@ -467,7 +471,8 @@ cpr_dump(vnode_t *vp) return (error); if (error = cpr_write_statefile(vp)) { - DEBUG7(errp("cpr_dump: cpr_write_statefile() failed!\n")); + CPR_DEBUG(CPR_DEBUG7, + "cpr_dump: cpr_write_statefile() failed!\n"); return (error); } @@ -539,8 +544,8 @@ cpr_scan_kvseg(int mapflag, bitfunc_t bitfunc, struct seg *seg) vmem_walk(heap_arena, VMEM_ALLOC, cpr_walk, &cwinfo); - if (cpr_debug & LEVEL7) { - errp("walked %d sub-ranges, total pages %ld\n", + if (cpr_debug & CPR_DEBUG7) { + prom_printf("walked %d sub-ranges, total pages %ld\n", cwinfo.ranges, mmu_btop(cwinfo.size)); cpr_show_range(seg->s_base, seg->s_size, mapflag, bitfunc, cwinfo.pages); @@ -584,8 +589,8 @@ cpr_scan_segkpm(int mapflag, bitfunc_t bitfunc, struct seg *seg) cwinfo.bitfunc = bitfunc; hat_kpm_walk(cpr_walk_kpm, &cwinfo); - if (cpr_debug & LEVEL7) { - errp("walked %d sub-ranges, total pages %ld\n", + if (cpr_debug & CPR_DEBUG7) { + prom_printf("walked %d sub-ranges, total pages %ld\n", cwinfo.ranges, mmu_btop(cwinfo.size)); cpr_show_range(segkpm->s_base, segkpm->s_size, mapflag, bitfunc, cwinfo.pages); @@ -683,9 +688,9 @@ cpr_count_kpages(int mapflag, bitfunc_t bitfunc) kas_cnt = i_cpr_count_special_kpages(mapflag, bitfunc); kas_cnt += cpr_count_seg_pages(mapflag, bitfunc); - DEBUG9(errp("cpr_count_kpages: kas_cnt=%ld\n", kas_cnt)); - DEBUG7(errp("\ncpr_count_kpages: %ld pages, 0x%lx bytes\n", - kas_cnt, mmu_ptob(kas_cnt))); + CPR_DEBUG(CPR_DEBUG9, "cpr_count_kpages: kas_cnt=%ld\n", kas_cnt); + CPR_DEBUG(CPR_DEBUG7, "\ncpr_count_kpages: %ld pages, 0x%lx bytes\n", + kas_cnt, mmu_ptob(kas_cnt)); return (kas_cnt); } @@ -807,10 +812,10 @@ cpr_count_upages(int mapflag, bitfunc_t bitfunc) } while ((pp = page_next(pp)) != page0); STAT->cs_upage2statef = dcnt; - DEBUG9(errp("cpr_count_upages: dirty=%ld total=%ld\n", - dcnt, tcnt)); - DEBUG7(errp("cpr_count_upages: %ld pages, 0x%lx bytes\n", - dcnt, mmu_ptob(dcnt))); + CPR_DEBUG(CPR_DEBUG9, "cpr_count_upages: dirty=%ld total=%ld\n", + dcnt, tcnt); + CPR_DEBUG(CPR_DEBUG7, "cpr_count_upages: %ld pages, 0x%lx bytes\n", + dcnt, mmu_ptob(dcnt)); return (dcnt); } @@ -901,8 +906,8 @@ cpr_compress_and_write(vnode_t *vp, uint_t va, pfn_t pfn, pgcnt_t npg) i_cpr_mapin(CPR->c_mapping_area, npg, pfn); - DEBUG3(errp("mapped-in %ld pages, vaddr 0x%p, pfn 0x%lx\n", - npg, CPR->c_mapping_area, pfn)); + CPR_DEBUG(CPR_DEBUG3, "mapped-in %ld pages, vaddr 0x%p, pfn 0x%lx\n", + npg, CPR->c_mapping_area, pfn); /* * Fill cpr page descriptor. @@ -927,10 +932,10 @@ cpr_compress_and_write(vnode_t *vp, uint_t va, pfn_t pfn, pgcnt_t npg) i_cpr_mapout(CPR->c_mapping_area, npg); if (error) { - DEBUG1(errp("cpr_compress_and_write: vp 0x%p va 0x%x ", - vp, va)); - DEBUG1(errp("pfn 0x%lx blk %d err %d\n", - pfn, cpr_file_bn, error)); + CPR_DEBUG(CPR_DEBUG1, + "cpr_compress_and_write: vp 0x%p va 0x%x ", vp, va); + CPR_DEBUG(CPR_DEBUG1, "pfn 0x%lx blk %d err %d\n", + pfn, cpr_file_bn, error); } else { cpr_regular_pgs_dumped += npg; } @@ -978,20 +983,21 @@ cpr_write(vnode_t *vp, caddr_t buffer, size_t size) return (ENOSPC); } - DEBUG3(errp("cpr_write: frmp=%p wptr=%p cnt=%lx...", - fromp, cpr_wptr, bytes)); + CPR_DEBUG(CPR_DEBUG3, + "cpr_write: frmp=%p wptr=%p cnt=%lx...", + fromp, cpr_wptr, bytes); /* * cross check, this should not happen! */ if (cpr_disk_writes_ok == 0) { - errp("cpr_write: disk write too early!\n"); + prom_printf("cpr_write: disk write too early!\n"); return (EINVAL); } do_polled_io = 1; error = VOP_DUMP(vp, cpr_buf, cpr_file_bn, cpr_buf_blocks); do_polled_io = 0; - DEBUG3(errp("done\n")); + CPR_DEBUG(CPR_DEBUG3, "done\n"); STAT->cs_real_statefsz += cpr_buf_size; @@ -1024,7 +1030,8 @@ cpr_flush_write(vnode_t *vp) cpr_file_bn += nblk; if (error) - DEBUG2(errp("cpr_flush_write: error (%d)\n", error)); + CPR_DEBUG(CPR_DEBUG2, "cpr_flush_write: error (%d)\n", + error); return (error); } @@ -1037,7 +1044,7 @@ cpr_clear_bitmaps(void) bzero((void *)dp->cbd_reg_bitmap, (size_t)dp->cbd_size * 2); } - DEBUG7(errp("\ncleared reg and vlt bitmaps\n")); + CPR_DEBUG(CPR_DEBUG7, "\ncleared reg and vlt bitmaps\n"); } int @@ -1113,7 +1120,7 @@ cpr_show_range(caddr_t vaddr, size_t size, action = "untag"; else action = "none"; - errp("range (0x%p, 0x%p), %s bitmap, %s %ld\n", + prom_printf("range (0x%p, 0x%p), %s bitmap, %s %ld\n", vaddr, vaddr + size, bname, action, count); } @@ -1135,7 +1142,7 @@ cpr_count_pages(caddr_t sva, size_t size, } } - if ((cpr_debug & LEVEL7) && showrange == DBG_SHOWRANGE) + if ((cpr_debug & CPR_DEBUG7) && showrange == DBG_SHOWRANGE) cpr_show_range(sva, size, mapflag, bitfunc, count); return (count); @@ -1157,8 +1164,8 @@ cpr_count_volatile_pages(int mapflag, bitfunc_t bitfunc) } count += i_cpr_count_storage_pages(mapflag, bitfunc); - DEBUG7(errp("cpr_count_vpages: %ld pages, 0x%lx bytes\n", - count, mmu_ptob(count))); + CPR_DEBUG(CPR_DEBUG7, "cpr_count_vpages: %ld pages, 0x%lx bytes\n", + count, mmu_ptob(count)); return (count); } @@ -1171,6 +1178,6 @@ cpr_dump_regular_pages(vnode_t *vp) cpr_regular_pgs_dumped = 0; error = cpr_contig_pages(vp, WRITE_TO_STATEFILE); if (!error) - DEBUG7(errp("cpr_dump_regular_pages() done.\n")); + CPR_DEBUG(CPR_DEBUG7, "cpr_dump_regular_pages() done.\n"); return (error); } diff --git a/usr/src/uts/common/cpr/cpr_main.c b/usr/src/uts/common/cpr/cpr_main.c index cd14998bee..6669469681 100644 --- a/usr/src/uts/common/cpr/cpr_main.c +++ b/usr/src/uts/common/cpr/cpr_main.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -172,19 +171,20 @@ cpr_log_status(int enable, int *svstat, vnode_t *vp) if (error = VOP_IOCTL(vp, _FIOISLOG, (uintptr_t)&status, FKIOCTL, CRED(), NULL)) { mntpt = vfs_getmntpoint(vp->v_vfsp); - errp("%s: \"%s\", cant get logging status, error %d\n", - str, refstr_value(mntpt), error); + prom_printf("%s: \"%s\", cant get logging " + "status, error %d\n", str, refstr_value(mntpt), + error); refstr_rele(mntpt); return; } *svstat = status; - DEBUG5( - { + if (cpr_debug & CPR_DEBUG5) { mntpt = vfs_getmntpoint(vp->v_vfsp); - errp("%s: \"%s\", logging status = %d\n", + CPR_DEBUG(CPR_DEBUG5, + "%s: \"%s\", logging status = %d\n", str, refstr_value(mntpt), status); refstr_rele(mntpt); - }); + }; able = "disable"; cmd = _FIOLOGDISABLE; @@ -201,17 +201,17 @@ cpr_log_status(int enable, int *svstat, vnode_t *vp) FKIOCTL, CRED(), NULL); if (error) { mntpt = vfs_getmntpoint(vp->v_vfsp); - errp("%s: \"%s\", cant %s logging, error %d\n", + prom_printf("%s: \"%s\", cant %s logging, error %d\n", str, refstr_value(mntpt), able, error); refstr_rele(mntpt); } else { - DEBUG5( - { + if (cpr_debug & CPR_DEBUG5) { mntpt = vfs_getmntpoint(vp->v_vfsp); - errp("%s: \"%s\", logging is now %sd\n", + CPR_DEBUG(CPR_DEBUG5, + "%s: \"%s\", logging is now %sd\n", str, refstr_value(mntpt), able); refstr_rele(mntpt); - }); + } } } @@ -258,8 +258,8 @@ cpr_ufs_logging(int enable) return (ENOENT); if (error = vn_open(fname, UIO_SYSSPACE, FCREAT|FWRITE, 0600, &vp, CRCREAT, 0)) { - errp("cpr_ufs_logging: cant open/create \"%s\", error %d\n", - fname, error); + prom_printf("cpr_ufs_logging: cant open/create \"%s\", " + "error %d\n", fname, error); return (error); } @@ -343,13 +343,13 @@ cpr_suspend(void) * The 3 retry is not a random number because 2 is possible if * a thread has been forked before the parent thread is stopped. */ - DEBUG1(errp("\nstopping user threads...")); + CPR_DEBUG(CPR_DEBUG1, "\nstopping user threads..."); CPR_STAT_EVENT_START(" stop users"); cpr_set_substate(C_ST_STOP_USER_THREADS); if (rc = cpr_stop_user_threads()) return (rc); CPR_STAT_EVENT_END(" stop users"); - DEBUG1(errp("done\n")); + CPR_DEBUG(CPR_DEBUG1, "done\n"); pm_save_direct_levels(); @@ -362,7 +362,7 @@ cpr_suspend(void) cpr_send_notice(); if (cpr_debug) - errp("\n"); + prom_printf("\n"); (void) callb_execute_class(CB_CL_CPR_POST_USER, CB_CODE_CPR_CHKPT); @@ -407,7 +407,7 @@ alloc_statefile: cpr_set_substate(C_ST_STATEF_ALLOC); if (rc = cpr_alloc_statefile(sf_realloc)) { if (sf_realloc) - errp("realloc failed\n"); + prom_printf("realloc failed\n"); return (rc); } CPR_STAT_EVENT_END(" alloc statefile"); @@ -425,9 +425,9 @@ alloc_statefile: * destroy all clean file mapped kernel pages */ CPR_STAT_EVENT_START(" clean pages"); - DEBUG1(errp("cleaning up mapped pages...")); + CPR_DEBUG(CPR_DEBUG1, "cleaning up mapped pages..."); (void) callb_execute_class(CB_CL_CPR_VM, CB_CODE_CPR_CHKPT); - DEBUG1(errp("done\n")); + CPR_DEBUG(CPR_DEBUG1, "done\n"); CPR_STAT_EVENT_END(" clean pages"); @@ -441,14 +441,14 @@ alloc_statefile: * Now suspend all the devices */ CPR_STAT_EVENT_START(" stop drivers"); - DEBUG1(errp("suspending drivers...")); + CPR_DEBUG(CPR_DEBUG1, "suspending drivers..."); cpr_set_substate(C_ST_SUSPEND_DEVICES); pm_powering_down = 1; rc = cpr_suspend_devices(ddi_root_node()); pm_powering_down = 0; if (rc) return (rc); - DEBUG1(errp("done\n")); + CPR_DEBUG(CPR_DEBUG1, "done\n"); CPR_STAT_EVENT_END(" stop drivers"); /* @@ -486,7 +486,7 @@ alloc_statefile: mon_clock_start(); i_cpr_stop_intr(); - DEBUG1(errp("interrupt is stopped\n")); + CPR_DEBUG(CPR_DEBUG1, "interrupt is stopped\n"); /* * Since we will now disable the mechanism that causes prom_printfs @@ -569,7 +569,7 @@ cpr_resume(void) * The following switch is used to resume the system * that was suspended to a different level. */ - DEBUG1(errp("\nEntering cpr_resume...\n")); + CPR_DEBUG(CPR_DEBUG1, "\nEntering cpr_resume...\n"); /* * Note: @@ -730,7 +730,7 @@ rb_stop_kernel_threads: cpr_start_kernel_threads(); rb_suspend_devices: - DEBUG1(errp("resuming devices...")); + CPR_DEBUG(CPR_DEBUG1, "resuming devices..."); CPR_STAT_EVENT_START(" start drivers"); /* @@ -748,7 +748,7 @@ rb_suspend_devices: else if (rc) cpr_err(CE_WARN, str); CPR_STAT_EVENT_END(" start drivers"); - DEBUG1(errp("done\n")); + CPR_DEBUG(CPR_DEBUG1, "done\n"); /* * If we had disabled modunloading in this cpr resume cycle (i.e. we @@ -804,9 +804,9 @@ rb_pm_reattach_noinvol: pm_restore_direct_levels(); rb_stop_user_threads: - DEBUG1(errp("starting user threads...")); + CPR_DEBUG(CPR_DEBUG1, "starting user threads..."); cpr_start_user_threads(); - DEBUG1(errp("done\n")); + CPR_DEBUG(CPR_DEBUG1, "done\n"); rb_mp_offline: if (cpr_mp_online()) @@ -832,16 +832,17 @@ rb_others: if (!cpr_reusable_mode) cpr_clear_definfo(); - DEBUG1(errp("Sending SIGTHAW...")); + CPR_DEBUG(CPR_DEBUG1, "Sending SIGTHAW..."); cpr_signal_user(SIGTHAW); - DEBUG1(errp("done\n")); + CPR_DEBUG(CPR_DEBUG1, "done\n"); CPR_STAT_EVENT_END("Resume Total"); CPR_STAT_EVENT_START_TMZ("WHOLE CYCLE", &wholecycle_tv); CPR_STAT_EVENT_END("WHOLE CYCLE"); - DEBUG1(cmn_err(CE_CONT, "\nThe system is back where you left!\n")); + if (cpr_debug & CPR_DEBUG1) + cmn_err(CE_CONT, "\nThe system is back where you left!\n"); CPR_STAT_EVENT_START("POST CPR DELAY"); diff --git a/usr/src/uts/common/cpr/cpr_misc.c b/usr/src/uts/common/cpr/cpr_misc.c index 043219e77b..1632beb072 100644 --- a/usr/src/uts/common/cpr/cpr_misc.c +++ b/usr/src/uts/common/cpr/cpr_misc.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -123,8 +123,9 @@ cpr_init(int fcn) mutex_exit(&cpr_slock); return (EAGAIN); } - DEBUG3(cpr_err(CE_CONT, "Reserved virtual range from 0x%p for writing " - "kas\n", (void *)CPR->c_mapping_area)); + if (cpr_debug & CPR_DEBUG3) + cpr_err(CE_CONT, "Reserved virtual range from 0x%p for writing " + "kas\n", (void *)CPR->c_mapping_area); return (0); } @@ -441,8 +442,8 @@ cpr_alloc_statefile(int alloc_retry) */ if (alloc_retry) { str = "\n-->Retrying statefile allocation..."; - if (cpr_debug & (LEVEL1 | LEVEL7)) - errp(str); + if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG7)) + prom_printf(str); if (C_VP->v_type != VBLK) (void) VOP_DUMPCTL(C_VP, DUMP_FREE, NULL); } else { @@ -598,13 +599,13 @@ cpr_statefile_ok(vnode_t *vp, int alloc_retry) str = "cpr_statefile_ok:"; - DEBUG9(errp("Phys swap: max=%lu resv=%lu\n", - k_anoninfo.ani_max, k_anoninfo.ani_phys_resv)); - DEBUG9(errp("Mem swap: max=%ld resv=%lu\n", + CPR_DEBUG(CPR_DEBUG9, "Phys swap: max=%lu resv=%lu\n", + k_anoninfo.ani_max, k_anoninfo.ani_phys_resv); + CPR_DEBUG(CPR_DEBUG9, "Mem swap: max=%ld resv=%lu\n", MAX(availrmem - swapfs_minfree, 0), - k_anoninfo.ani_mem_resv)); - DEBUG9(errp("Total available swap: %ld\n", - CURRENT_TOTAL_AVAILABLE_SWAP)); + k_anoninfo.ani_mem_resv); + CPR_DEBUG(CPR_DEBUG9, "Total available swap: %ld\n", + CURRENT_TOTAL_AVAILABLE_SWAP); /* * try increasing filesize by 15% @@ -614,16 +615,17 @@ cpr_statefile_ok(vnode_t *vp, int alloc_retry) * block device doesn't get any bigger */ if (vp->v_type == VBLK) { - if (cpr_debug & (LEVEL1 | LEVEL6)) - errp("Retry statefile on special file\n"); + if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG6)) + prom_printf( + "Retry statefile on special file\n"); return (ENOMEM); } else { rw_enter(&ip->i_contents, RW_READER); size = (ip->i_size * SIZE_RATE) / INTEGRAL; rw_exit(&ip->i_contents); } - if (cpr_debug & (LEVEL1 | LEVEL6)) - errp("Retry statefile size = %lld\n", size); + if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG6)) + prom_printf("Retry statefile size = %lld\n", size); } else { u_longlong_t cpd_size; pgcnt_t npages, nback; @@ -632,8 +634,8 @@ cpr_statefile_ok(vnode_t *vp, int alloc_retry) ndvram = 0; (void) callb_execute_class(CB_CL_CPR_FB, (int)(uintptr_t)&ndvram); - if (cpr_debug & (LEVEL1 | LEVEL6)) - errp("ndvram size = %d\n", ndvram); + if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG6)) + prom_printf("ndvram size = %d\n", ndvram); /* * estimate 1 cpd_t for every (CPR_MAXCONTIG / 2) pages @@ -649,10 +651,11 @@ cpr_statefile_ok(vnode_t *vp, int alloc_retry) if (CPR->c_flags & C_COMPRESSING) { size = ((ksize * COMPRESS_PERCENT) / INTEGRAL) + raw_data + ((nback * 10) / UCOMP_RATE); - DEBUG1(errp(est_fmt, str, "", size, ksize)); + CPR_DEBUG(CPR_DEBUG1, est_fmt, str, "", size, ksize); } else { size = ksize + raw_data + nback; - DEBUG1(errp(est_fmt, str, "no ", size, ksize)); + CPR_DEBUG(CPR_DEBUG1, est_fmt, str, "no ", + size, ksize); } } @@ -661,8 +664,8 @@ cpr_statefile_ok(vnode_t *vp, int alloc_retry) */ if (vp->v_type == VBLK) { space = cpr_get_devsize(vp->v_rdev); - if (cpr_debug & (LEVEL1 | LEVEL6)) - errp("statefile dev size %lu\n", space); + if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG6)) + prom_printf("statefile dev size %lu\n", space); /* * Export the estimated filesize info, this value will be @@ -670,9 +673,9 @@ cpr_statefile_ok(vnode_t *vp, int alloc_retry) * no compression. */ STAT->cs_est_statefsz = size; - if (cpr_debug & (LEVEL1 | LEVEL6)) - errp("%s Estimated statefile size %llu, space %lu\n", - str, size, space); + if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG6)) + prom_printf("%s Estimated statefile size %llu, " + "space %lu\n", str, size, space); if (size > space) { cpr_err(CE_CONT, "Statefile partition too small."); return (ENOMEM); @@ -701,12 +704,12 @@ cpr_statefile_ok(vnode_t *vp, int alloc_retry) */ STAT->cs_est_statefsz = size; error = cpr_grow_statefile(vp, size); - if (cpr_debug & (LEVEL1 | LEVEL6)) { + if (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG6)) { rw_enter(&ip->i_contents, RW_READER); isize = ip->i_size; rw_exit(&ip->i_contents); - errp("%s Estimated statefile size %lld, i_size %lld\n", - str, size, isize); + prom_printf("%s Estimated statefile size %lld, " + "i_size %lld\n", str, size, isize); } return (error); @@ -896,8 +899,9 @@ cpr_mp_offline(void) return (rc); } } while ((cp = cp->cpu_next) != cpu_list); - if (brought_up_boot && (cpr_debug & (LEVEL1 | LEVEL6))) - errp("changed cpu %p to state %d\n", bootcpu, CPU_CPR_ONLINE); + if (brought_up_boot && (cpr_debug & (CPR_DEBUG1 | CPR_DEBUG6))) + prom_printf("changed cpu %p to state %d\n", + bootcpu, CPU_CPR_ONLINE); mutex_exit(&cpu_lock); return (rc); diff --git a/usr/src/uts/common/cpr/cpr_mod.c b/usr/src/uts/common/cpr/cpr_mod.c index 1cc09d48e1..365f102a2b 100644 --- a/usr/src/uts/common/cpr/cpr_mod.c +++ b/usr/src/uts/common/cpr/cpr_mod.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -213,7 +212,7 @@ cpr(int fcn) return (0); case AD_CPR_DEBUG9: - cpr_debug |= LEVEL6; + cpr_debug |= CPR_DEBUG6; return (0); default: @@ -308,7 +307,7 @@ cpr(int fcn) if (fcn != AD_CPR_TESTHALT) cpr_power_down(); - errp("(Done. Please Switch Off)\n"); + CPR_DEBUG(CPR_DEBUG1, "(Done. Please Switch Off)\n"); halt(NULL); /* NOTREACHED */ } diff --git a/usr/src/uts/common/cpr/cpr_stat.c b/usr/src/uts/common/cpr/cpr_stat.c index e427a59c09..264bb4c9c7 100644 --- a/usr/src/uts/common/cpr/cpr_stat.c +++ b/usr/src/uts/common/cpr/cpr_stat.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,8 +19,8 @@ * CDDL HEADER END */ /* - * Copyright (c) 1993-2001 by Sun Microsystems, Inc. - * All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -92,7 +91,7 @@ cpr_stat_event_end(char *name, cpr_time_t *ctp) if ((cep = cpr_find_event(name, 0)) == NULL) { #ifdef CPR_STAT - errp("cpr_stat: event \"%s\" is not monitored\n", name); + prom_printf("cpr_stat: event \"%s\" is not monitored\n", name); #endif /* CPR_STAT */ return; } diff --git a/usr/src/uts/common/cpr/cpr_uthread.c b/usr/src/uts/common/cpr/cpr_uthread.c index a58b31c728..00d5e0e80b 100644 --- a/usr/src/uts/common/cpr/cpr_uthread.c +++ b/usr/src/uts/common/cpr/cpr_uthread.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -193,8 +192,8 @@ cpr_check_user_threads() mutex_exit(&pidlock); if (count == CPR_UTSTOP_RETRY) { - DEBUG1(errp("Suspend failed: cannt stop " - "uthread\n")); + CPR_DEBUG(CPR_DEBUG1, "Suspend failed: " + "cannot stop uthread\n"); cpr_err(CE_WARN, "Suspend cannot stop " "process %s (%p:%x).", ttoproc(tp)->p_user.u_psargs, (void *)tp, @@ -203,11 +202,12 @@ cpr_check_user_threads() " network request, please try again."); } - DEBUG2(errp("cant stop t=%p state=%x pfg=%x sched=%x\n", - tp, tp->t_state, tp->t_proc_flag, tp->t_schedflag)); - DEBUG2(errp("proc %p state=%x pid=%d\n", - ttoproc(tp), ttoproc(tp)->p_stat, - ttoproc(tp)->p_pidp->pid_id)); + CPR_DEBUG(CPR_DEBUG2, "cant stop t=%p state=%x pfg=%x " + "sched=%x\n", tp, tp->t_state, tp->t_proc_flag, + tp->t_schedflag); + CPR_DEBUG(CPR_DEBUG2, "proc %p state=%x pid=%d\n", + ttoproc(tp), ttoproc(tp)->p_stat, + ttoproc(tp)->p_pidp->pid_id); return (1); } thread_unlock(tp); @@ -268,9 +268,9 @@ cpr_start_user_threads() void cpr_start_kernel_threads(void) { - DEBUG1(errp("starting kernel daemons...")); + CPR_DEBUG(CPR_DEBUG1, "starting kernel daemons..."); (void) callb_execute_class(CB_CL_CPR_DAEMON, CB_CODE_CPR_RESUME); - DEBUG1(errp("done\n")); + CPR_DEBUG(CPR_DEBUG1, "done\n"); /* see table lock below */ callb_unlock_table(); @@ -290,7 +290,7 @@ cpr_stop_kernel_threads(void) callb_lock_table(); /* Note: we unlock the table in resume. */ - DEBUG1(errp("stopping kernel daemons...")); + CPR_DEBUG(CPR_DEBUG1, "stopping kernel daemons..."); if ((name = callb_execute_class(CB_CL_CPR_DAEMON, CB_CODE_CPR_CHKPT)) != (caddr_t)NULL) { cpr_err(CE_WARN, @@ -323,6 +323,6 @@ cpr_stop_kernel_threads(void) } while ((tp = tp->t_next) != curthread); mutex_exit(&pidlock); - DEBUG1(errp("done\n")); + CPR_DEBUG(CPR_DEBUG1, "done\n"); return (0); } diff --git a/usr/src/uts/common/crypto/io/swrand.c b/usr/src/uts/common/crypto/io/swrand.c index 63f30aa628..11b6778c21 100644 --- a/usr/src/uts/common/crypto/io/swrand.c +++ b/usr/src/uts/common/crypto/io/swrand.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -55,6 +55,7 @@ #include <sys/sha1.h> #include <sys/sunddi.h> #include <sys/modctl.h> +#include <sys/hold_page.h> #define RNDPOOLSIZE 1024 /* Pool size in bytes */ #define HASHBUFSIZE 64 /* Buffer size used for pool mixing */ @@ -635,6 +636,7 @@ physmem_ent_gen(physmem_entsrc_t *entsrc) hrtime_t ts1, ts2, diff, delta, delta2, delta3; uint8_t digest[HASHSIZE]; HASH_CTX ctx; + page_t *pp; /* * Use each 32-bit quantity in the pool to pick a memory @@ -678,6 +680,15 @@ physmem_ent_gen(physmem_entsrc_t *entsrc) } /* + * Do an initial check to see if the address is safe + */ + if (plat_hold_page(offset >> PAGESHIFT, PLAT_HOLD_NO_LOCK, NULL) + == PLAT_HOLD_FAIL) { + memlist_read_unlock(); + continue; + } + + /* * Figure out which page to load to read the * memory block. Load the page and compute the * hash of the memory block. @@ -691,6 +702,15 @@ physmem_ent_gen(physmem_entsrc_t *entsrc) nbytes = PAGESIZE - poffset < len ? PAGESIZE - poffset : len; + /* + * Re-check the offset, and lock the frame. If the + * page was given away after the above check, we'll + * just bail out. + */ + if (plat_hold_page(pfn, PLAT_HOLD_LOCK, &pp) == + PLAT_HOLD_FAIL) + break; + hat_devload(kas.a_hat, entsrc->pmbuf, PAGESIZE, pfn, PROT_READ, HAT_LOAD_NOCONSIST | HAT_LOAD_LOCK); @@ -701,12 +721,18 @@ physmem_ent_gen(physmem_entsrc_t *entsrc) hat_unload(kas.a_hat, entsrc->pmbuf, PAGESIZE, HAT_UNLOAD_UNLOCK); + plat_release_page(pp); + len -= nbytes; offset += nbytes; } /* We got our pages. Let the DR roll */ memlist_read_unlock(); + /* See if we had to bail out due to a page being given away */ + if (len) + continue; + HashFinal(digest, &ctx); ts2 = gethrtime(); diff --git a/usr/src/uts/common/dtrace/profile.c b/usr/src/uts/common/dtrace/profile.c index 8452f03640..8de919a851 100644 --- a/usr/src/uts/common/dtrace/profile.c +++ b/usr/src/uts/common/dtrace/profile.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -43,20 +43,18 @@ static dev_info_t *profile_devi; static dtrace_provider_id_t profile_id; /* - * Regardless of platform, there are five artificial frames in the case of the + * Regardless of platform, the stack frames look like this in the case of the * profile provider: * * profile_fire * cyclic_expire * cyclic_fire * [ cbe ] - * [ locore ] + * [ interrupt code ] * - * On amd64, there are two frames associated with locore: one in locore, and - * another in common interrupt dispatch code. (i386 has not been modified to - * use this common layer.) Further, on i386, the interrupted instruction - * appears as its own stack frame. All of this means that we need to add one - * frame for amd64, and then take one away for both amd64 and i386. + * On x86, there are five frames from the generic interrupt code; further, the + * interrupted instruction appears as its own stack frame, giving us a total of + * 10. * * On SPARC, the picture is further complicated because the compiler * optimizes away tail-calls -- so the following frames are optimized away: @@ -68,16 +66,13 @@ static dtrace_provider_id_t profile_id; * frame cannot be tail-call eliminated, yielding four frames in this case. * * All of the above constraints lead to the mess below. Yes, the profile - * provider should ideally figure this out on-the-fly by hiting one of its own + * provider should ideally figure this out on-the-fly by hitting one of its own * probes and then walking its own stack trace. This is complicated, however, * and the static definition doesn't seem to be overly brittle. Still, we * allow for a manual override in case we get it completely wrong. */ -#ifdef __amd64 -#define PROF_ARTIFICIAL_FRAMES 7 -#else -#ifdef __i386 -#define PROF_ARTIFICIAL_FRAMES 6 +#ifdef __x86 +#define PROF_ARTIFICIAL_FRAMES 10 #else #ifdef __sparc #ifdef DEBUG @@ -87,7 +82,6 @@ static dtrace_provider_id_t profile_id; #endif #endif #endif -#endif #define PROF_NAMELEN 15 @@ -164,6 +158,10 @@ static void profile_create(hrtime_t interval, const char *name, int kind) { profile_probe_t *prof; + int nr_frames = PROF_ARTIFICIAL_FRAMES + dtrace_mach_aframes(); + + if (profile_aframes) + nr_frames = profile_aframes; if (interval < profile_interval_min) return; @@ -183,8 +181,7 @@ profile_create(hrtime_t interval, const char *name, int kind) prof->prof_cyclic = CYCLIC_NONE; prof->prof_kind = kind; prof->prof_id = dtrace_probe_create(profile_id, - NULL, NULL, name, - profile_aframes ? profile_aframes : PROF_ARTIFICIAL_FRAMES, prof); + NULL, NULL, name, nr_frames, prof); } /*ARGSUSED*/ diff --git a/usr/src/uts/common/fs/fsflush.c b/usr/src/uts/common/fs/fsflush.c index 24b5ff8bbc..d7b3ae1071 100644 --- a/usr/src/uts/common/fs/fsflush.c +++ b/usr/src/uts/common/fs/fsflush.c @@ -23,7 +23,7 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -352,8 +352,8 @@ fsflush() proc_fsflush->p_stime = 0; proc_fsflush->p_cutime = 0; proc_fsflush->p_utime = 0; - bcopy("fsflush", u.u_psargs, 8); - bcopy("fsflush", u.u_comm, 7); + bcopy("fsflush", curproc->p_user.u_psargs, 8); + bcopy("fsflush", curproc->p_user.u_comm, 7); mutex_init(&fsflush_lock, NULL, MUTEX_DEFAULT, NULL); sema_init(&fsflush_sema, 0, NULL, SEMA_DEFAULT, NULL); diff --git a/usr/src/uts/common/fs/sockfs/socktpi.c b/usr/src/uts/common/fs/sockfs/socktpi.c index 0e35cb7a46..fb862614e3 100644 --- a/usr/src/uts/common/fs/sockfs/socktpi.c +++ b/usr/src/uts/common/fs/sockfs/socktpi.c @@ -696,7 +696,7 @@ sotpi_bindlisten(struct sonode *so, struct sockaddr *name, goto done; } vattr.va_type = VSOCK; - vattr.va_mode = 0777 & ~u.u_cmask; + vattr.va_mode = 0777 & ~PTOU(curproc)->u_cmask; vattr.va_mask = AT_TYPE|AT_MODE; /* NOTE: holding so_lock */ error = vn_create(soun->sun_path, UIO_SYSSPACE, &vattr, diff --git a/usr/src/uts/common/fs/specfs/specvnops.c b/usr/src/uts/common/fs/specfs/specvnops.c index 24c7ffedab..1a6c40517a 100644 --- a/usr/src/uts/common/fs/specfs/specvnops.c +++ b/usr/src/uts/common/fs/specfs/specvnops.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2179,7 +2179,7 @@ spec_map( cvp = sp->s_commonvp; ASSERT(cvp != NULL); - if (off < 0 || (off + len) < 0) + if (off < 0 || ((offset_t)(off + len) < 0)) return (ENXIO); as_rangelock(as); diff --git a/usr/src/uts/common/fs/tmpfs/tmp_vnops.c b/usr/src/uts/common/fs/tmpfs/tmp_vnops.c index aa870b124a..2f1e94a7c7 100644 --- a/usr/src/uts/common/fs/tmpfs/tmp_vnops.c +++ b/usr/src/uts/common/fs/tmpfs/tmp_vnops.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2078,7 +2078,7 @@ tmp_map( if (vp->v_flag & VNOMAP) return (ENOSYS); - if (off < 0 || (off + len) < 0 || + if (off < 0 || (offset_t)(off + len) < 0 || off > MAXOFF_T || (off + len) > MAXOFF_T) return (ENXIO); diff --git a/usr/src/uts/common/fs/vfs.c b/usr/src/uts/common/fs/vfs.c index 4cfe749214..b473706b8b 100644 --- a/usr/src/uts/common/fs/vfs.c +++ b/usr/src/uts/common/fs/vfs.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -618,7 +618,7 @@ vfs_mountdevices(void) * _init devfs module to fill in the vfssw */ if (modload("fs", "devfs") == -1) - cmn_err(CE_PANIC, "Cannot _init devfs module\n"); + panic("Cannot _init devfs module"); /* * Hold vfs @@ -632,13 +632,13 @@ vfs_mountdevices(void) * Locate mount point */ if (lookupname("/devices", UIO_SYSSPACE, FOLLOW, NULLVPP, &mvp)) - cmn_err(CE_PANIC, "Cannot find /devices\n"); + panic("Cannot find /devices"); /* * Perform the mount of /devices */ if (VFS_MOUNT(&devices, mvp, &mounta, CRED())) - cmn_err(CE_PANIC, "Cannot mount /devices\n"); + panic("Cannot mount /devices"); RUNLOCK_VFSSW(); @@ -652,7 +652,7 @@ vfs_mountdevices(void) * Hold the root of /devices so it won't go away */ if (VFS_ROOT(&devices, &devicesdir)) - cmn_err(CE_PANIC, "vfs_mountdevices: not devices root"); + panic("vfs_mountdevices: not devices root"); if (vfs_lock(&devices) != 0) { VN_RELE(devicesdir); @@ -766,11 +766,11 @@ vfs_mountfs(char *module, char *spec, char *path) mounta.spec = spec; mounta.dir = path; if (lookupname(path, UIO_SYSSPACE, FOLLOW, NULLVPP, &mvp)) { - cmn_err(CE_WARN, "Cannot find %s\n", path); + cmn_err(CE_WARN, "Cannot find %s", path); return; } if (domount(NULL, &mounta, mvp, CRED(), &vfsp)) - cmn_err(CE_WARN, "Cannot mount %s\n", path); + cmn_err(CE_WARN, "Cannot mount %s", path); else VFS_RELE(vfsp); VN_RELE(mvp); @@ -800,7 +800,7 @@ vfs_mountroot(void) * file system type. */ if (rootconf()) - cmn_err(CE_PANIC, "vfs_mountroot: cannot mount root"); + panic("vfs_mountroot: cannot mount root"); /* * Get vnode for '/'. Set up rootdir, u.u_rdir and u.u_cdir * to point to it. These are used by lookuppn() so that it @@ -808,10 +808,10 @@ vfs_mountroot(void) */ vfs_setmntpoint(rootvfs, "/"); if (VFS_ROOT(rootvfs, &rootdir)) - cmn_err(CE_PANIC, "vfs_mountroot: no root vnode"); - u.u_cdir = rootdir; - VN_HOLD(u.u_cdir); - u.u_rdir = NULL; + panic("vfs_mountroot: no root vnode"); + PTOU(curproc)->u_cdir = rootdir; + VN_HOLD(PTOU(curproc)->u_cdir); + PTOU(curproc)->u_rdir = NULL; /* * Setup the global zone's rootvp, now that it exists. @@ -874,7 +874,7 @@ vfs_mountroot(void) */ if (root_is_svm) { if (svm_rootconf()) { - cmn_err(CE_PANIC, "vfs_mountroot: cannot remount root"); + panic("vfs_mountroot: cannot remount root"); } /* @@ -1325,7 +1325,7 @@ domount(char *fsname, struct mounta *uap, vnode_t *vp, struct cred *credp, if ((sema_tryp(&vfsp->vfs_reflock) == 0) && !(vfsp->vfs_flag & VFS_REMOUNT)) cmn_err(CE_WARN, - "mount type %s couldn't get vfs_reflock\n", vswp->vsw_name); + "mount type %s couldn't get vfs_reflock", vswp->vsw_name); /* * Lock the vfs. If this is a remount we want to avoid spurious umount @@ -2860,7 +2860,7 @@ vfs_remove(struct vfs *vfsp) * be busy. */ if (vfsp == rootvfs) - cmn_err(CE_PANIC, "vfs_remove: unmounting root"); + panic("vfs_remove: unmounting root"); vfs_list_remove(vfsp); @@ -4105,7 +4105,7 @@ rootconf() return (error); if (modload("fs", fstyp) == -1) - cmn_err(CE_PANIC, "Cannot _init %s module\n", fstyp); + panic("Cannot _init %s module", fstyp); RLOCK_VFSSW(); vsw = vfs_getvfsswbyname(fstyp); @@ -4126,7 +4126,7 @@ rootconf() rootdev = rootvfs->vfs_dev; if (error) - cmn_err(CE_PANIC, "cannot mount root path %s", svm_bootpath); + panic("cannot mount root path %s", rootfs.bo_name); return (error); } @@ -4177,8 +4177,7 @@ getrootfs(void) /* attempt to determine netdev_path via boot_mac address */ netdev_path = strplumb_get_netdev_path(); if (netdev_path == NULL) - cmn_err(CE_PANIC, - "Cannot find boot network interface\n"); + panic("cannot find boot network interface"); (void) strncpy(rootfs.bo_name, netdev_path, BO_MAXOBJNAME); } return ("nfs"); diff --git a/usr/src/uts/common/io/audio/inc.flg b/usr/src/uts/common/io/audio/inc.flg index a8e830ddc5..c05ee0f88d 100644 --- a/usr/src/uts/common/io/audio/inc.flg +++ b/usr/src/uts/common/io/audio/inc.flg @@ -21,7 +21,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -81,8 +81,8 @@ find_files "s.*" \ usr/src/uts/sparc/mixer \ usr/src/uts/sparc/amsrc2 \ usr/src/uts/sparc/diaudio \ - usr/src/uts/i86pc/audio810 \ - usr/src/uts/i86pc/audiohd \ + usr/src/uts/intel/audio810 \ + usr/src/uts/intel/audiohd \ usr/src/uts/intel/audiosup \ usr/src/uts/intel/mixer \ usr/src/uts/intel/diaudio @@ -128,5 +128,3 @@ echo_file usr/src/uts/intel/Makefile.intel echo_file usr/src/uts/intel/Makefile.intel.shared echo_file usr/src/uts/intel/Makefile.targ echo_file usr/src/uts/intel/Makefile.targ.shared -echo_file usr/src/uts/intel/ia32/Makefile.rules -echo_file usr/src/uts/intel/amd64/Makefile.rules diff --git a/usr/src/uts/common/io/avintr.c b/usr/src/uts/common/io/avintr.c index 9236b3f4f2..cd5d474731 100644 --- a/usr/src/uts/common/io/avintr.c +++ b/usr/src/uts/common/io/avintr.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -570,7 +569,6 @@ av_dispatch_autovect(uint_t vec) caddr_t arg2 = av->av_intarg2; dev_info_t *dip = av->av_dip; - numcalled++; if (intr == NULL) break; @@ -579,6 +577,7 @@ av_dispatch_autovect(uint_t vec) r = (*intr)(arg1, arg2); DTRACE_PROBE4(interrupt__complete, dev_info_t *, dip, void *, intr, caddr_t, arg1, uint_t, r); + numcalled++; claimed |= r; if (av->av_ticksp && av->av_prilevel <= LOCK_LEVEL) atomic_add_64(av->av_ticksp, intr_get_time()); diff --git a/usr/src/uts/common/io/busra.c b/usr/src/uts/common/io/busra.c index 9d0062f48e..1a3c49c666 100644 --- a/usr/src/uts/common/io/busra.c +++ b/usr/src/uts/common/io/busra.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -141,7 +140,7 @@ static int ra_map_exist(dev_info_t *dip, char *type); static struct modlmisc modlmisc = { &mod_miscops, /* Type of module. This one is a module */ - "Bus Resource Allocator (BUSRA) 1.36", /* Name of the module. */ + "Bus Resource Allocator (BUSRA) %I%", /* Name of the module. */ }; static struct modlinkage modlinkage = { @@ -1022,7 +1021,7 @@ pci_resource_setup(dev_info_t *dip) break; } } - kmem_free((caddr_t)regs, rlen); + kmem_free(regs, rlen); } /* diff --git a/usr/src/uts/common/io/consconfig_dacf.c b/usr/src/uts/common/io/consconfig_dacf.c index f53ce5dbb6..99a43972de 100644 --- a/usr/src/uts/common/io/consconfig_dacf.c +++ b/usr/src/uts/common/io/consconfig_dacf.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -209,12 +209,13 @@ static char *consconfig_usb_ms_path = NULL; * Internal variables */ static dev_t stdoutdev; +static cons_state_t *consconfig_sp; /* * consconfig_errlevel: debug verbosity; smaller numbers are more * verbose. */ -static int consconfig_errlevel = DPRINT_L3; +int consconfig_errlevel = DPRINT_L3; /* * Baud rate table @@ -733,18 +734,20 @@ cons_build_upper_layer(cons_state_t *sp) */ /* open the console keyboard device. will never be closed */ - if (ldi_open_by_name(CONSKBD_PATH, FREAD|FWRITE|FNOCTTY, kcred, - &sp->conskbd_lh, sp->cons_li) != 0) - cmn_err(CE_PANIC, "consconfig: " - "unable to open conskbd device"); + if (ldi_open_by_name(CONSKBD_PATH, FREAD|FWRITE|FNOCTTY, + kcred, &sp->conskbd_lh, sp->cons_li) != 0) { + panic("consconfig: unable to open conskbd device"); + /*NOTREACHED*/ + } DPRINTF(DPRINT_L0, "conskbd_lh = %p\n", sp->conskbd_lh); /* open the console mouse device. will never be closed */ - if (ldi_open_by_name(CONSMS_PATH, FREAD|FWRITE|FNOCTTY, kcred, - &sp->consms_lh, sp->cons_li) != 0) - cmn_err(CE_PANIC, "consconfig: " - "unable to open consms device"); + if (ldi_open_by_name(CONSMS_PATH, FREAD|FWRITE|FNOCTTY, + kcred, &sp->consms_lh, sp->cons_li) != 0) { + panic("consconfig: unable to open consms device"); + /*NOTREACHED*/ + } DPRINTF(DPRINT_L0, "consms_lh = %p\n", sp->consms_lh); @@ -789,17 +792,19 @@ cons_build_upper_layer(cons_state_t *sp) * here.) */ wsconsvp = i_consconfig_createvp(IWSCN_PATH); - if (wsconsvp == NULL) - cmn_err(CE_PANIC, "consconfig: " - "unable to find iwscn device"); + if (wsconsvp == NULL) { + panic("consconfig: unable to find iwscn device"); + /*NOTREACHED*/ + } if (cons_tem_disable) return; if (sp->cons_fb_path == NULL) { -#if defined(i386) || defined(__i386) || defined(__ia64) - cmn_err(CE_WARN, "consconfig: no screen found"); -#endif /* defined(i386) || defined(__i386) || defined(__ia64) */ +#if defined(__x86) + if (plat_stdout_is_framebuffer()) + cmn_err(CE_WARN, "consconfig: no screen found"); +#endif return; } @@ -897,6 +902,17 @@ consconfig_load_drivers(cons_state_t *sp) kbddev = ddi_pathname_to_dev_t(sp->cons_keyboard_path); if (sp->cons_mouse_path != NULL) mousedev = ddi_pathname_to_dev_t(sp->cons_mouse_path); + + /* + * On x86, make sure the fb driver is loaded even if we don't use it + * for the console. This will ensure that we create a /dev/fb link + * which is required to start Xorg. + */ +#if defined(__x86) + if (sp->cons_fb_path != NULL) + fbdev = ddi_pathname_to_dev_t(sp->cons_fb_path); +#endif + DPRINTF(DPRINT_L0, "stdindev %lx, stdoutdev %lx, kbddev %lx, " "mousedev %lx\n", stdindev, stdoutdev, kbddev, mousedev); } @@ -1221,10 +1237,12 @@ consconfig_init_input(cons_state_t *sp) * after being closed. */ rconsvp = i_consconfig_createvp(sp->cons_stdin_path); - if (rconsvp == NULL) - cmn_err(CE_PANIC, "consconfig_init_input: " + if (rconsvp == NULL) { + panic("consconfig_init_input: " "unable to find stdin device (%s)", sp->cons_stdin_path); + /*NOTREACHED*/ + } rconsdev = rconsvp->v_rdev; ASSERT(rconsdev == stdindev); @@ -1349,8 +1367,6 @@ consconfig_init_input(cons_state_t *sp) void dynamic_console_config(void) { - cons_state_t *sp; - /* initialize space.c globals */ stdindev = NODEV; mousedev = NODEV; @@ -1365,11 +1381,11 @@ dynamic_console_config(void) rconsdev = NODEV; /* Initialize cons_state_t structure and console device paths */ - sp = consconfig_state_init(); - ASSERT(sp); + consconfig_sp = consconfig_state_init(); + ASSERT(consconfig_sp); /* Build upper layer of console stream */ - cons_build_upper_layer(sp); + cons_build_upper_layer(consconfig_sp); /* * Load keyboard/mouse drivers. The dacf routines will @@ -1379,16 +1395,16 @@ dynamic_console_config(void) * and mouse drivers are linked into their respective console * streams if the pathnames are valid. */ - consconfig_load_drivers(sp); - sp->cons_input_type = cons_get_input_type(); + consconfig_load_drivers(consconfig_sp); + consconfig_sp->cons_input_type = cons_get_input_type(); /* * This is legacy special case code for the "cool" virtual console * for the Starfire project. Starfire has a dummy "ssp-serial" * node in the OBP device tree and cvc is a pseudo driver. */ - if (sp->cons_stdout_path != NULL && stdindev == NODEV && - strstr(sp->cons_stdout_path, "ssp-serial")) { + if (consconfig_sp->cons_stdout_path != NULL && stdindev == NODEV && + strstr(consconfig_sp->cons_stdout_path, "ssp-serial")) { /* * Setup the virtual console driver for Starfire * Note that console I/O will still go through prom for now @@ -1405,13 +1421,13 @@ dynamic_console_config(void) return; } - rwsconsvp = sp->cons_wc_vp; - rwsconsdev = sp->cons_wc_vp->v_rdev; + rwsconsvp = consconfig_sp->cons_wc_vp; + rwsconsdev = consconfig_sp->cons_wc_vp->v_rdev; /* initialize framebuffer, console input, and redirection device */ - consconfig_init_framebuffer(sp); - consconfig_init_input(sp); + consconfig_init_framebuffer(consconfig_sp); + consconfig_init_input(consconfig_sp); DPRINTF(DPRINT_L0, "mousedev %lx, kbddev %lx, fbdev %lx, rconsdev %lx\n", diff --git a/usr/src/uts/common/io/mem.c b/usr/src/uts/common/io/mem.c index 1b0c925ff4..08d2ffba85 100644 --- a/usr/src/uts/common/io/mem.c +++ b/usr/src/uts/common/io/mem.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -74,7 +74,7 @@ extern int cpu_get_mem_info(uint64_t, uint64_t, uint64_t *, uint64_t *, extern size_t cpu_get_name_bufsize(void); extern int cpu_get_mem_sid(char *, char *, int, int *); extern int cpu_get_mem_addr(char *, char *, uint64_t, uint64_t *); -#elif defined(__i386) || defined(__amd64) +#elif defined(__x86) #include <sys/cpu_module.h> #endif /* __sparc */ @@ -262,6 +262,24 @@ mmio(struct uio *uio, enum uio_rw rw, pfn_t pfn, off_t pageoff, int allowio) return (error); } +/* + * Some platforms have permanently-mapped areas without PFNs, so we check + * specially here. + */ +static int +mmplatio(struct uio *uio, enum uio_rw rw) +{ + uintptr_t pageaddr = (uintptr_t)uio->uio_loffset & PAGEMASK; + off_t pageoff = uio->uio_loffset & PAGEOFFSET; + size_t nbytes = MIN((size_t)(PAGESIZE - pageoff), + (size_t)uio->uio_iov->iov_len); + + if (!plat_mem_valid_page(pageaddr, rw)) + return (ENOTSUP); + + return (uiomove((void *)(pageaddr + pageoff), nbytes, rw, uio)); +} + #ifdef __sparc static int @@ -331,6 +349,9 @@ mmrw(dev_t dev, struct uio *uio, enum uio_rw rw, cred_t *cred) int try_lock = NEED_LOCK_KVADDR(vaddr); int locked = 0; + if ((error = mmplatio(uio, rw)) != ENOTSUP) + break; + /* * If vaddr does not map a valid page, as_pagelock() * will return failure. Hence we can't check the @@ -1179,7 +1200,7 @@ mm_get_paddr(nvlist_t *nvl, uint64_t *paddr) return (err); } } -#elif defined(__i386) || defined(__amd64) +#elif defined(__x86) if (cmi_mc_unumtopa(NULL, nvl, &pa) == 0) return (EINVAL); #else diff --git a/usr/src/uts/common/io/power.c b/usr/src/uts/common/io/power.c index 83a0211102..e87922ce84 100644 --- a/usr/src/uts/common/io/power.c +++ b/usr/src/uts/common/io/power.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -54,12 +54,15 @@ #include <sys/cmn_err.h> #include <sys/errno.h> #include <sys/modctl.h> -#include <sys/machsystm.h> #include <sys/open.h> #include <sys/stat.h> #include <sys/poll.h> #include <sys/pbio.h> +#if defined(__sparc) +#include <sys/machsystm.h> +#endif + #ifdef ACPI_POWER_BUTTON #include <sys/acpi/acpi.h> diff --git a/usr/src/uts/common/kmdb/kdrv.c b/usr/src/uts/common/kmdb/kdrv.c index a2c5797371..2b8e4857b4 100644 --- a/usr/src/uts/common/kmdb/kdrv.c +++ b/usr/src/uts/common/kmdb/kdrv.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -90,7 +90,7 @@ kdrv_activate(intptr_t arg) size_t got; int i, rc; -#if defined(__i386) || defined(__amd64) +#if defined(__x86) if (cons_polledio == NULL) { cmn_err(CE_NOTE, "kmdb not supported: no console polled I/O"); return (ENOTSUP); diff --git a/usr/src/uts/common/krtld/bootrd.c b/usr/src/uts/common/krtld/bootrd.c index 576b429c99..4d48f71673 100644 --- a/usr/src/uts/common/krtld/bootrd.c +++ b/usr/src/uts/common/krtld/bootrd.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -45,9 +44,7 @@ static uint64_t rd_start, rd_end; struct boot_fs_ops *bfs_ops; struct boot_fs_ops *bfs_tab[] = {&bufs_ops, &bhsfs_ops, NULL}; -#ifdef DEBUG -static uint64_t scratch_max; -#endif +static uintptr_t scratch_max; #define _kmem_ready get_weakish_int(&kmem_ready) @@ -115,12 +112,17 @@ kobj_boot_unmountroot() { #ifdef DEBUG if (boothowto & RB_VERBOSE) - _kobj_printf(ops, "boot scratch memory used: 0x%llx\n", + _kobj_printf(ops, "boot scratch memory used: 0x%lx\n", scratch_max); #endif (void) BRD_UNMOUNTROOT(bfs_ops); } +/* + * Boot time wrappers for memory allocators. Called for both permanent + * and temporary boot memory allocations. We have to track which allocator + * (boot or kmem) was used so that we know how to free. + */ void * bkmem_alloc(size_t size) { @@ -130,11 +132,13 @@ bkmem_alloc(size_t size) if (_kmem_ready) return (kobj_alloc(size, 0)); + /* + * Remember the highest BOP_ALLOC allocated address and don't free + * anything below it. + */ addr = BOP_ALLOC(ops, 0, size, 0); -#ifdef DEBUG if (scratch_max < (uintptr_t)addr + size) scratch_max = (uintptr_t)addr + size; -#endif return (addr); } @@ -143,12 +147,9 @@ void bkmem_free(void *p, size_t size) { /* - * Don't bother freeing scratch memory - * Note that in amd64, BOP_ALLOC returns address - * prepended with 0xffffffff, so we cast to 32-bit - * before comparing. + * Free only if it's not boot scratch memory. */ - if ((uint32_t)(uintptr_t)p > MAGIC_PHYS) + if ((uintptr_t)p >= scratch_max) kobj_free(p, size); } diff --git a/usr/src/uts/common/krtld/kobj.c b/usr/src/uts/common/krtld/kobj.c index 01032117ec..87c66363c8 100644 --- a/usr/src/uts/common/krtld/kobj.c +++ b/usr/src/uts/common/krtld/kobj.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -80,9 +80,10 @@ #define DOSYM_UNDEF -1 /* undefined symbol */ #define DOSYM_UNSAFE -2 /* MT-unsafe driver symbol */ -static struct module *load_exec(val_t *); +static void synthetic_bootaux(char *, val_t *); +static struct module *load_exec(val_t *, char *); static void load_linker(val_t *); -static struct modctl *add_primary(char *filename, int); +static struct modctl *add_primary(const char *filename, int); static int bind_primary(val_t *, int); static int load_primary(struct module *, int); static int load_kmdb(val_t *); @@ -97,7 +98,7 @@ static int do_symbols(struct module *, Elf64_Addr); static void module_assign(struct modctl *, struct module *); static void free_module_data(struct module *); static char *depends_on(struct module *); -static char *getmodpath(void); +static char *getmodpath(const char *); static char *basename(char *); static void attr_val(val_t *); static char *find_libmacro(char *); @@ -143,6 +144,11 @@ extern int last_module_id; * is loaded. */ int kobj_debug = 0; + +#define KOBJ_MARK(s) if (kobj_debug & D_DEBUG) \ + (_kobj_printf(ops, "%d", __LINE__), _kobj_printf(ops, ": %s\n", s)) +#else +#define KOBJ_MARK(s) /* discard */ #endif #define MODPATH_PROPNAME "module-path" @@ -197,11 +203,11 @@ void sas_prisyms(struct modctl_list *); void sas_syms(struct module *); #endif +char *kobj_module_path; /* module search path */ vmem_t *text_arena; /* module text arena */ static vmem_t *data_arena; /* module data & bss arena */ static vmem_t *ctf_arena; /* CTF debug data arena */ static struct modctl *kobj_modules = NULL; /* modules loaded */ -static char *module_path; /* module search path */ int kobj_mmu_pagesize; /* system pagesize */ static int lg_pagesize; /* "large" pagesize */ static int kobj_last_module_id = 0; /* id assignment */ @@ -262,12 +268,18 @@ const char *ultra_2 = "SUNW,UltraSPARC-II"; #endif /* - * Beginning and end of the kernel's - * dynamic text/data segments. + * Beginning and end of the kernel's dynamic text/data segments. */ static caddr_t _text; static caddr_t _etext; -static caddr_t _data; +static caddr_t _data; + +/* + * XXX Hmm. The sparc linker fails to define this symbol. + */ +#if !defined(__sparc) +extern +#endif caddr_t _edata; static Addr dynseg = 0; /* load address of "dynamic" segment */ @@ -337,6 +349,7 @@ kobj_init( struct module *mp; struct modctl *modp; Addr entry; + char filename[MAXPATHLEN]; /* * Save these to pass on to @@ -351,6 +364,7 @@ kobj_init( #else _kobj_printf = (void (*)(void *, const char *, ...))bop_putsarg; #endif + KOBJ_MARK("Entered kobj_init()"); #if defined(__sparc) /* XXXQ should suppress this test on sun4v */ @@ -360,11 +374,6 @@ kobj_init( } } #endif - /* - * Save the interesting attribute-values - * (scanned by kobj_boot). - */ - attr_val(bootaux); /* * Check bootops version. @@ -374,6 +383,17 @@ kobj_init( BOP_GETVERSION(ops)); _kobj_printf(ops, "expected %d\n", BO_VERSION); } +#ifdef KOBJ_DEBUG + else if (kobj_debug & D_DEBUG) { + /* + * Say -something- so we know we got this far .. + */ + _kobj_printf(ops, "krtld: Using boot version %d.\n", + BOP_GETVERSION(ops)); + } +#endif + + (void) BOP_GETPROP(ops, "whoami", filename); /* * We don't support standalone debuggers anymore. The use of kadb @@ -395,13 +415,40 @@ kobj_init( /* on x86, we always boot with a ramdisk */ extern int kobj_boot_mountroot(void); (void) kobj_boot_mountroot(); + + /* + * Now that the ramdisk is mounted, finish boot property + * initialization. + */ + boot_prop_finish(); } #endif +#if !defined(_UNIX_KRTLD) + /* + * If 'unix' is linked together with 'krtld' into one executable, + * the early boot code does -not- hand us any of the dynamic metadata + * about the executable. In particular, it does not read in, map or + * otherwise look at the program headers. We fake all that up now. + * + * We do this early as DTrace static probes and tnf probes both call + * undefined references. We have to process those relocations before + * calling any of them. + */ + if (bootaux[BA_PHDR].ba_ptr == NULL) + synthetic_bootaux(filename, bootaux); +#endif + + /* + * Save the interesting attribute-values + * (scanned by kobj_boot). + */ + attr_val(bootaux); + /* * Set the module search path. */ - module_path = getmodpath(); + kobj_module_path = getmodpath(filename); boot_cpu_compatible_list = find_libmacro("CPU"); @@ -412,7 +459,7 @@ kobj_init( * loadable modules. */ - mp = load_exec(bootaux); + mp = load_exec(bootaux, filename); load_linker(bootaux); /* @@ -503,6 +550,72 @@ fail: _kobj_printf(ops, "krtld: error during initial load/link phase\n"); } +#if !defined(_UNIX_KRTLD) +/* + * Synthesize additional metadata that describes the executable. + * + * (When the dynamic executable has an interpreter, the boot program + * does all this for us. Where we don't have an interpreter, (or a + * even a boot program, perhaps) we have to do this for ourselves.) + */ +static void +synthetic_bootaux(char *filename, val_t *bootaux) +{ + Ehdr ehdr; + caddr_t phdrbase; + struct _buf *file; + int i, n; + + /* + * Elf header + */ + KOBJ_MARK("synthetic_bootaux()"); + KOBJ_MARK(filename); + file = kobj_open_file(filename); + if (file == (struct _buf *)-1) { + _kobj_printf(ops, "krtld: failed to open '%s'\n", filename); + return; + } + KOBJ_MARK("reading program headers"); + if (kobj_read_file(file, (char *)&ehdr, sizeof (ehdr), 0) < 0) { + _kobj_printf(ops, "krtld: %s: failed to read ehder\n", + filename); + return; + } + + /* + * Program headers + */ + bootaux[BA_PHNUM].ba_val = ehdr.e_phnum; + bootaux[BA_PHENT].ba_val = ehdr.e_phentsize; + n = ehdr.e_phentsize * ehdr.e_phnum; + + phdrbase = kobj_alloc(n, KM_WAIT | KM_TMP); + + if (kobj_read_file(file, phdrbase, n, ehdr.e_phoff) < 0) { + _kobj_printf(ops, "krtld: %s: failed to read phdrs\n", + filename); + return; + } + bootaux[BA_PHDR].ba_ptr = phdrbase; + kobj_close_file(file); + KOBJ_MARK("closed file"); + + /* + * Find the dynamic section address + */ + for (i = 0; i < ehdr.e_phnum; i++) { + Phdr *phdr = (Phdr *)(phdrbase + ehdr.e_phentsize * i); + + if (phdr->p_type == PT_DYNAMIC) { + bootaux[BA_DYNAMIC].ba_ptr = (void *)phdr->p_vaddr; + break; + } + } + KOBJ_MARK("synthetic_bootaux() done"); +} +#endif + /* * Set up any global information derived * from attribute/values in the boot or @@ -515,6 +628,7 @@ attr_val(val_t *bootaux) int phnum, phsize; int i; + KOBJ_MARK("attr_val()"); kobj_mmu_pagesize = bootaux[BA_PAGESZ].ba_val; lg_pagesize = bootaux[BA_LPAGESZ].ba_val; use_iflush = bootaux[BA_IFLUSH].ba_val; @@ -531,11 +645,15 @@ attr_val(val_t *bootaux) * Bounds of the various segments. */ if (!(phdr->p_flags & PF_X)) { +#if defined(_UNIX_KRTLD) dynseg = phdr->p_vaddr; +#else + ASSERT(phdr->p_vaddr == 0); +#endif } else { if (phdr->p_flags & PF_W) { - _data = (caddr_t)phdr->p_vaddr; - _edata = _data + phdr->p_memsz; + _data = (caddr_t)phdr->p_vaddr; + _edata = _data + phdr->p_memsz; } else { _text = (caddr_t)phdr->p_vaddr; _etext = _text + phdr->p_memsz; @@ -560,9 +678,8 @@ attr_val(val_t *bootaux) * Set up the booted executable. */ static struct module * -load_exec(val_t *bootaux) +load_exec(val_t *bootaux, char *filename) { - char filename[MAXPATHLEN]; struct modctl *cp; struct module *mp; Dyn *dyn; @@ -570,10 +687,20 @@ load_exec(val_t *bootaux) int i, lsize, osize, nsize, allocsize; char *libname, *tmp; - (void) BOP_GETPROP(ops, "whoami", filename); + /* + * Set the module search path. + */ + kobj_module_path = getmodpath(filename); +#ifdef KOBJ_DEBUG + if (kobj_debug & D_DEBUG) + _kobj_printf(ops, "module path '%s'\n", kobj_module_path); +#endif + + KOBJ_MARK("add_primary"); cp = add_primary(filename, KOBJ_LM_PRIMARY); + KOBJ_MARK("struct module"); mp = kobj_zalloc(sizeof (struct module), KM_WAIT); cp->mod_mp = mp; @@ -590,7 +717,10 @@ load_exec(val_t *bootaux) * Since this module is the only exception, * we cons up some section headers. */ + KOBJ_MARK("symhdr"); mp->symhdr = kobj_zalloc(sizeof (Shdr), KM_WAIT); + + KOBJ_MARK("strhdr"); mp->strhdr = kobj_zalloc(sizeof (Shdr), KM_WAIT); mp->symhdr->sh_type = SHT_SYMTAB; @@ -631,6 +761,7 @@ load_exec(val_t *bootaux) nsize = osize = 0; allocsize = MAXPATHLEN; + KOBJ_MARK("depends_on"); mp->depends_on = kobj_alloc(allocsize, KM_WAIT); for (dyn = (Dyn *) bootaux[BA_DYNAMIC].ba_ptr; @@ -651,6 +782,7 @@ load_exec(val_t *bootaux) lsize = strlen(libname); nsize += lsize; if (nsize + 1 > allocsize) { + KOBJ_MARK("grow depends_on"); tmp = kobj_alloc(allocsize + MAXPATHLEN, KM_WAIT); bcopy(mp->depends_on, tmp, osize); @@ -668,6 +800,7 @@ load_exec(val_t *bootaux) /* * alloc with exact size and copy whatever it got over */ + KOBJ_MARK("realloc depends_on"); tmp = kobj_alloc(nsize, KM_WAIT); bcopy(mp->depends_on, tmp, nsize); kobj_free(mp->depends_on, allocsize); @@ -683,11 +816,17 @@ load_exec(val_t *bootaux) * We allocate our own table since we don't * hash undefined references. */ + KOBJ_MARK("chains"); mp->chains = kobj_zalloc(mp->nsyms * sizeof (symid_t), KM_WAIT); + KOBJ_MARK("buckets"); mp->buckets = kobj_zalloc(mp->hashsize * sizeof (symid_t), KM_WAIT); mp->text = _text; mp->data = _data; + + mp->text_size = _etext - _text; + mp->data_size = _edata - _data; + cp->mod_text = mp->text; cp->mod_text_size = mp->text_size; @@ -722,11 +861,12 @@ load_exec(val_t *bootaux) sym_insert(mp, mp->strings + sp->st_name, i); } + KOBJ_MARK("load_exec done"); return (mp); } /* - * Set up the linker module. + * Set up the linker module (if it's compiled in, LDNAME is NULL) */ static void load_linker(val_t *bootaux) @@ -740,6 +880,12 @@ load_linker(val_t *bootaux) int shsize; char *dlname = (char *)bootaux[BA_LDNAME].ba_ptr; + /* + * On some architectures, krtld is compiled into the kernel. + */ + if (dlname == NULL) + return; + cp = add_primary(dlname, KOBJ_LM_PRIMARY); mp = kobj_zalloc(sizeof (struct module), KM_WAIT); @@ -906,12 +1052,19 @@ kobj_notify(int type, struct modctl *modp) /* * Ask boot for the module path. */ +/*ARGSUSED*/ static char * -getmodpath(void) +getmodpath(const char *filename) { char *path; int len; +#if defined(_UNIX_KRTLD) + /* + * The boot program provides the module name when it detects + * that the executable has an interpreter, thus we can ask + * it directly in this case. + */ if ((len = BOP_GETPROPLEN(ops, MODPATH_PROPNAME)) == -1) return (MOD_DEFPATH); @@ -920,10 +1073,48 @@ getmodpath(void) (void) BOP_GETPROP(ops, MODPATH_PROPNAME, path); return (*path ? path : MOD_DEFPATH); + +#else + + /* + * Construct the directory path from the filename. + */ + + char *p; + const char isastr[] = "/amd64"; + size_t isalen = strlen(isastr); + + if ((p = strrchr(filename, '/')) == NULL) + return (MOD_DEFPATH); + + while (p > filename && *(p - 1) == '/') + p--; /* remove trailing '/' characters */ + if (p == filename) + p++; /* so "/" -is- the modpath in this case */ + + /* + * Remove optional isa-dependent directory name - the module + * subsystem will put this back again (!) + */ + len = p - filename; + if (len > isalen && + strncmp(&filename[len - isalen], isastr, isalen) == 0) + p -= isalen; + + /* + * "/platform/mumblefrotz" + " " + MOD_DEFPATH + */ + len += (p - filename) + 1 + strlen(MOD_DEFPATH) + 1; + + path = kobj_zalloc(len, KM_WAIT); + (void) strncpy(path, filename, p - filename); + (void) strcat(path, " "); + return (strcat(path, MOD_DEFPATH)); +#endif } static struct modctl * -add_primary(char *filename, int lmid) +add_primary(const char *filename, int lmid) { struct modctl *cp; @@ -973,10 +1164,6 @@ bind_primary(val_t *bootaux, int lmid) struct modctl_list *linkmap = kobj_lm_lookup(lmid); struct modctl_list *lp; struct module *mp; - Dyn *dyn; - Word relasz; - Word relaent; - char *rela; /* * Do common symbols. @@ -1012,11 +1199,10 @@ bind_primary(val_t *bootaux, int lmid) mp = mod(lp); if (mp->flags & KOBJ_EXEC) { - Word shtype; - - relasz = 0; - relaent = 0; - rela = NULL; + Dyn *dyn; + Word relasz = 0, relaent = 0; + Word shtype; + char *rela = NULL; for (dyn = (Dyn *)bootaux[BA_DYNAMIC].ba_ptr; dyn->d_tag != DT_NULL; dyn++) { @@ -1048,7 +1234,6 @@ bind_primary(val_t *bootaux, int lmid) "module %s\n", mp->filename); return (-1); } - #ifdef KOBJ_DEBUG if (kobj_debug & D_RELOCATIONS) _kobj_printf(ops, "krtld: relocating: file=%s " @@ -1062,7 +1247,6 @@ bind_primary(val_t *bootaux, int lmid) return (-1); } - /* sync_instruction_memory */ kobj_sync_instruction_memory(mp->text, mp->text_size); } @@ -1259,6 +1443,15 @@ load_kmdb(val_t *bootaux) if ((sym = lookup_one(mctl->mod_mp, "kctl_boot_activate")) == NULL) return (-1); +#ifdef KOBJ_DEBUG + if (kobj_debug & D_DEBUG) { + _kobj_printf(ops, "calling kctl_boot_activate() @ 0x%lx\n", + sym->st_value); + _kobj_printf(ops, "\tops 0x%p\n", ops); + _kobj_printf(ops, "\tromp 0x%p\n", romp); + } +#endif + if (((kctl_boot_activate_f *)sym->st_value)(ops, romp, 0, (const char **)kobj_kmdb_argv) < 0) return (-1); @@ -2104,8 +2297,13 @@ get_progbits(struct module *mp, struct _buf *file) mp->data_size = dp->size; if (standalone) { + caddr_t limit = _data; + + if (lg_pagesize && _text + lg_pagesize < limit) + limit = _text + lg_pagesize; + mp->text = kobj_segbrk(&_etext, mp->text_size, - tp->align, _data); + tp->align, limit); /* * If we can't grow the text segment, try the * data segment before failing. @@ -2422,6 +2620,7 @@ get_syms(struct module *mp, struct _buf *file) } } } + sym_insert(mp, symname, i); } @@ -3258,7 +3457,8 @@ kobj_open_path(char *name, int use_path, int use_moddir_suffix) if (!use_path) pathp = ""; /* use name as specified */ else - pathp = module_path; /* use configured default path */ + pathp = kobj_module_path; + /* use configured default path */ pathpsave = pathp; /* keep this for error reporting */ @@ -3701,7 +3901,7 @@ kobj_alloc(size_t size, int flag) #ifdef KOBJ_DEBUG if (kobj_debug & D_DEBUG) { _kobj_printf(ops, "krtld: failed scratch alloc " - "of %u bytes -- falling back\n", size); + "of %lu bytes -- falling back\n", size); } #endif } @@ -3730,15 +3930,13 @@ kobj_sync(void) { struct modctl_list *lp, **lpp; - extern char *default_path; - /* - * module_path can be set in /etc/system + * The module path can be set in /etc/system via 'moddir' commands */ if (default_path != NULL) - module_path = default_path; + kobj_module_path = default_path; else - default_path = module_path; + default_path = kobj_module_path; ksyms_arena = vmem_create("ksyms", NULL, 0, sizeof (uint64_t), segkmem_alloc, segkmem_free, heap_arena, 0, VM_SLEEP); @@ -3778,19 +3976,25 @@ kobj_segbrk(caddr_t *spp, size_t size, size_t align, caddr_t limit) * Need more pages? */ if (va + size > pva) { + uintptr_t npva; + alloc_size = P2ROUNDUP(size - (pva - va), alloc_pgsz); /* * Check for overlapping segments. */ - if (limit && limit <= *spp + alloc_size) + if (limit && limit <= *spp + alloc_size) { return ((caddr_t)0); + } - pva = (uintptr_t)BOP_ALLOC(ops, (caddr_t)pva, + npva = (uintptr_t)BOP_ALLOC(ops, (caddr_t)pva, alloc_size, alloc_align); - if (pva == NULL) { - _kobj_printf(ops, "BOP_ALLOC refused, 0x%x bytes ", + + if (npva == NULL) { + _kobj_printf(ops, "BOP_ALLOC failed, 0x%lx bytes", alloc_size); + _kobj_printf(ops, " aligned %lx", alloc_align); _kobj_printf(ops, " at 0x%lx\n", pva); + return (NULL); } } *spp = (caddr_t)(va + size); diff --git a/usr/src/uts/common/krtld/kobj_kdi.c b/usr/src/uts/common/krtld/kobj_kdi.c index 25d38e75b1..c094e30d06 100644 --- a/usr/src/uts/common/krtld/kobj_kdi.c +++ b/usr/src/uts/common/krtld/kobj_kdi.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -239,6 +238,7 @@ kdi_t kobj_kdi = { * plat_kdi_init. */ NULL, /* kdi_plat_call */ + NULL, /* kdi_kmdb_enter */ { NULL }, /* kdi_arch */ { NULL } /* kdi_plat */ }; diff --git a/usr/src/uts/common/os/acct.c b/usr/src/uts/common/os/acct.c index f442a30ae3..c596ce45f3 100644 --- a/usr/src/uts/common/os/acct.c +++ b/usr/src/uts/common/os/acct.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -380,6 +379,7 @@ acct(char st) struct vnode *vp; struct cred *cr; struct proc *p; + user_t *ua; struct vattr va; ssize_t resid = 0; int error; @@ -398,13 +398,14 @@ acct(char st) * cred locking is needed. */ p = curproc; - bcopy(u.u_comm, ag->acctbuf.ac_comm, sizeof (ag->acctbuf.ac_comm)); - ag->acctbuf.ac_btime = u.u_start.tv_sec; + ua = PTOU(p); + bcopy(ua->u_comm, ag->acctbuf.ac_comm, sizeof (ag->acctbuf.ac_comm)); + ag->acctbuf.ac_btime = ua->u_start.tv_sec; ag->acctbuf.ac_utime = acct_compress(NSEC_TO_TICK(p->p_acct[LMS_USER])); ag->acctbuf.ac_stime = acct_compress( NSEC_TO_TICK(p->p_acct[LMS_SYSTEM] + p->p_acct[LMS_TRAP])); - ag->acctbuf.ac_etime = acct_compress(lbolt - u.u_ticks); - ag->acctbuf.ac_mem = acct_compress((ulong_t)u.u_mem); + ag->acctbuf.ac_etime = acct_compress(lbolt - ua->u_ticks); + ag->acctbuf.ac_mem = acct_compress((ulong_t)ua->u_mem); ag->acctbuf.ac_io = acct_compress((ulong_t)p->p_ru.ioch); ag->acctbuf.ac_rw = acct_compress((ulong_t)(p->p_ru.inblock + p->p_ru.oublock)); @@ -413,7 +414,7 @@ acct(char st) ag->acctbuf.ac_gid = crgetrgid(cr); (void) cmpldev(&ag->acctbuf.ac_tty, cttydev(p)); ag->acctbuf.ac_stat = st; - ag->acctbuf.ac_flag = (u.u_acflag | AEXPND); + ag->acctbuf.ac_flag = (ua->u_acflag | AEXPND); /* * Save the size. If the write fails, reset the size to avoid diff --git a/usr/src/uts/common/os/clock.c b/usr/src/uts/common/os/clock.c index a1040f1270..4eff816e48 100644 --- a/usr/src/uts/common/os/clock.c +++ b/usr/src/uts/common/os/clock.c @@ -450,8 +450,17 @@ clock(void) nrunnable += cpu_nrunnable; cpupart = cp->cpu_part; cpupart->cp_nrunnable_cum += cpu_nrunnable; - if (one_sec) + if (one_sec) { cpupart->cp_nrunnable += cpu_nrunnable; + /* + * w_io is used to update sysinfo.waiting during + * one_second processing below. Only gather w_io + * information when we walk the list of cpus if we're + * going to perform one_second processing. + */ + w_io += CPU_STATS(cp, sys.iowait); + + } if (do_lgrp_load && (cp->cpu_flags & CPU_EXISTS)) { /* diff --git a/usr/src/uts/common/os/core.c b/usr/src/uts/common/os/core.c index 5e64bdda97..e833022e2b 100644 --- a/usr/src/uts/common/os/core.c +++ b/usr/src/uts/common/os/core.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -256,7 +255,7 @@ create_core_file(char *fp, enum core_types core_type, vnode_t **vpp) file = pn.pn_path; } error = vn_openat(file, UIO_SYSSPACE, FWRITE | FTRUNC | FEXCL | - FCREAT | FOFFMAX, perms, &vp, CRCREAT, u.u_cmask, dvp); + FCREAT | FOFFMAX, perms, &vp, CRCREAT, PTOU(curproc)->u_cmask, dvp); if (core_type != CORE_PROC) { VN_RELE(dvp); pn_free(&pn); @@ -438,9 +437,9 @@ do_core(char *fp, int sig, enum core_types core_type, struct core_globals *cg) (void) flush_user_windows_to_stack(NULL); #endif #ifdef SUN_SRC_COMPAT - u.u_acflag |= ACORE; + PTOU(curproc)->u_acflag |= ACORE; #endif - if ((eswp = u.u_execsw) == NULL || + if ((eswp = PTOU(curproc)->u_execsw) == NULL || (eswp = findexec_by_magic(eswp->exec_magic)) == NULL) { error = ENOSYS; } else { diff --git a/usr/src/uts/common/os/cpu.c b/usr/src/uts/common/os/cpu.c index 9237517a69..849cdabc49 100644 --- a/usr/src/uts/common/os/cpu.c +++ b/usr/src/uts/common/os/cpu.c @@ -58,7 +58,7 @@ #include <sys/msacct.h> #include <sys/time.h> #include <sys/archsystm.h> -#if defined(__i386) || defined(__amd64) +#if defined(__x86) #include <sys/x86_archext.h> #endif @@ -145,15 +145,6 @@ cpu_t *cpu_inmotion; int weakbindingbarrier; /* - * values for safe_list. Pause state that CPUs are in. - */ -#define PAUSE_IDLE 0 /* normal state */ -#define PAUSE_READY 1 /* paused thread ready to spl */ -#define PAUSE_WAIT 2 /* paused thread is spl-ed high */ -#define PAUSE_DIE 3 /* tell pause thread to leave */ -#define PAUSE_DEAD 4 /* pause thread has left */ - -/* * Variables used in pause_cpus(). */ static volatile char safe_list[NCPU]; @@ -770,18 +761,8 @@ cpu_pause(volatile char *safe) * setbackdq/setfrontdq. */ s = splhigh(); - /* - * This cpu is now safe. - */ - *safe = PAUSE_WAIT; - membar_enter(); /* make sure stores are flushed */ - /* - * Now we wait. When we are allowed to continue, safe will - * be set to PAUSE_IDLE. - */ - while (*safe != PAUSE_IDLE) - ; + mach_cpu_pause(safe); splx(s); /* @@ -1198,6 +1179,7 @@ cpu_online(cpu_t *cp) lgrp_kstat_create(cp); cpu_state_change_notify(cp->cpu_id, CPU_ON); cpu_intr_enable(cp); /* arch-dep hook */ + cpu_set_state(cp); cyclic_online(cp); poke_cpu(cp->cpu_id); } @@ -2093,7 +2075,7 @@ static struct { kstat_named_t ci_device_ID; kstat_named_t ci_cpu_fru; #endif -#if defined(__i386) || defined(__amd64) +#if defined(__x86) kstat_named_t ci_vendorstr; kstat_named_t ci_family; kstat_named_t ci_model; @@ -2114,7 +2096,7 @@ static struct { { "device_ID", KSTAT_DATA_UINT64 }, { "cpu_fru", KSTAT_DATA_STRING }, #endif -#if defined(__i386) || defined(__amd64) +#if defined(__x86) { "vendor_id", KSTAT_DATA_STRING }, { "family", KSTAT_DATA_INT32 }, { "model", KSTAT_DATA_INT32 }, @@ -2175,7 +2157,7 @@ cpu_info_kstat_update(kstat_t *ksp, int rw) cpunodes[cp->cpu_id].device_id; kstat_named_setstr(&cpu_info_template.ci_cpu_fru, cpu_fru_fmri(cp)); #endif -#if defined(__i386) || defined(__amd64) +#if defined(__x86) kstat_named_setstr(&cpu_info_template.ci_vendorstr, cpuid_getvendorstr(cp)); cpu_info_template.ci_family.value.l = cpuid_getfamily(cp); @@ -2207,7 +2189,7 @@ cpu_info_kstat_create(cpu_t *cp) cp->cpu_info_kstat->ks_data_size += strlen(cpu_fru_fmri(cp)) + 1; #endif -#if defined(__i386) || defined(__amd64) +#if defined(__x86) cp->cpu_info_kstat->ks_data_size += X86_VENDOR_STRLEN; #endif cp->cpu_info_kstat->ks_lock = &cpu_info_template_lock; @@ -3020,7 +3002,7 @@ cpu_sys_stats_ks_update(kstat_t *ksp, int rw) csskd->modload.value.ui64 = css->modload; csskd->modunload.value.ui64 = css->modunload; csskd->bawrite.value.ui64 = css->bawrite; - csskd->iowait.value.ui64 = 0; + csskd->iowait.value.ui64 = css->iowait; return (0); } @@ -3166,7 +3148,7 @@ cpu_stat_ks_update(kstat_t *ksp, int rw) cso->cpu_sysinfo.win_su_cnt = 0; cso->cpu_sysinfo.win_suo_cnt = 0; - cso->cpu_syswait.iowait = 0; + cso->cpu_syswait.iowait = CPU_STATS(cp, sys.iowait); cso->cpu_syswait.swap = 0; cso->cpu_syswait.physio = 0; diff --git a/usr/src/uts/common/os/dumpsubr.c b/usr/src/uts/common/os/dumpsubr.c index d5b55a8842..9a6aca6965 100644 --- a/usr/src/uts/common/os/dumpsubr.c +++ b/usr/src/uts/common/os/dumpsubr.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -637,6 +636,7 @@ dumpsys(void) */ dumphdr->dump_map = dumpvp_flush(); dump_as(&kas); + dumphdr->dump_nvtop += dump_plat_addr(); /* * call into hat, which may have unmapped pages that also need to @@ -704,6 +704,7 @@ dumpsys(void) ASSERT(pfn != PFN_INVALID); dumpvp_write(&pfn, sizeof (pfn_t)); } + dump_plat_pfn(); /* * Write out all the pages. @@ -741,6 +742,7 @@ dumpsys(void) delay(1); /* let the output be sent */ } } + dumphdr->dump_npages += dump_plat_data(dump_cbuf); (void) dumpvp_flush(); diff --git a/usr/src/uts/common/os/fork.c b/usr/src/uts/common/os/fork.c index 177c28316b..76c11663fd 100644 --- a/usr/src/uts/common/os/fork.c +++ b/usr/src/uts/common/os/fork.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -687,15 +687,15 @@ fork_fail(proc_t *cp) kmem_free(fip->fi_list, fip->fi_nfiles * sizeof (uf_entry_t)); - VN_RELE(u.u_cdir); - if (u.u_rdir) - VN_RELE(u.u_rdir); + VN_RELE(PTOU(curproc)->u_cdir); + if (PTOU(curproc)->u_rdir) + VN_RELE(PTOU(curproc)->u_rdir); if (cp->p_exec) VN_RELE(cp->p_exec); if (cp->p_execdir) VN_RELE(cp->p_execdir); - if (u.u_cwd) - refstr_rele(u.u_cwd); + if (PTOU(curproc)->u_cwd) + refstr_rele(PTOU(curproc)->u_cwd); } /* @@ -1086,17 +1086,17 @@ getproc(proc_t **cpp, int kernel) */ fcnt_add(P_FINFO(pp), 1); - VN_HOLD(u.u_cdir); - if (u.u_rdir) - VN_HOLD(u.u_rdir); - if (u.u_cwd) - refstr_hold(u.u_cwd); + VN_HOLD(PTOU(pp)->u_cdir); + if (PTOU(pp)->u_rdir) + VN_HOLD(PTOU(pp)->u_rdir); + if (PTOU(pp)->u_cwd) + refstr_hold(PTOU(pp)->u_cwd); /* * copy the parent's uarea. */ uarea = PTOU(cp); - bcopy(PTOU(pp), uarea, sizeof (user_t)); + bcopy(PTOU(pp), uarea, sizeof (*uarea)); flist_fork(P_FINFO(pp), P_FINFO(cp)); gethrestime(&uarea->u_start); diff --git a/usr/src/uts/common/os/grow.c b/usr/src/uts/common/os/grow.c index 115a1312fa..e463b97004 100644 --- a/usr/src/uts/common/os/grow.c +++ b/usr/src/uts/common/os/grow.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -480,7 +480,7 @@ grow_internal(caddr_t sp, uint_t growszc) segvn_create, &crargs)) != 0) { if (error == EAGAIN) { cmn_err(CE_WARN, "Sorry, no swap space to grow stack " - "for pid %d (%s)", p->p_pid, u.u_comm); + "for pid %d (%s)", p->p_pid, PTOU(p)->u_comm); } return (error); } diff --git a/usr/src/uts/common/os/kdi.c b/usr/src/uts/common/os/kdi.c index ef548e38d0..20eed5a16f 100644 --- a/usr/src/uts/common/os/kdi.c +++ b/usr/src/uts/common/os/kdi.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -39,30 +38,6 @@ struct modctl *kdi_dmods; static kdi_dtrace_state_t kdi_dtrace_state = KDI_DTSTATE_IDLE; void -kdi_dvec_enter(void) -{ - kdi_dvec->dv_enter(); -} - -/* - * Called on the CPU being initialized - */ -void -kdi_dvec_cpu_init(struct cpu *cp) -{ - kdi_dvec->dv_kctl_cpu_init(); - kdi_dvec->dv_cpu_init(cp); -} - -#if defined(__i386) || defined(__amd64) -void -kdi_dvec_idt_sync(gate_desc_t *idt) -{ - kdi_dvec->dv_idt_sync(idt); -} -#endif /* __i386 || __amd64 */ - -void kdi_dvec_vmready(void) { kdi_dvec->dv_kctl_vmready(); @@ -79,7 +54,25 @@ kdi_dvec_memavail(void) kdi_dvec->dv_kctl_memavail(); } +#if defined(__x86) +void +kdi_dvec_handle_fault(greg_t trapno, greg_t pc, greg_t sp, int cpuid) +{ + kdi_dvec->dv_handle_fault(trapno, pc, sp, cpuid); +} +#endif + #if defined(__sparc) +/* + * Called on the CPU being initialized + */ +void +kdi_dvec_cpu_init(struct cpu *cp) +{ + kdi_dvec->dv_kctl_cpu_init(); + kdi_dvec->dv_cpu_init(cp); +} + void kdi_dvec_cpr_restart(void) { diff --git a/usr/src/uts/common/os/main.c b/usr/src/uts/common/os/main.c index 1f4fbbf877..85882b45c6 100644 --- a/usr/src/uts/common/os/main.c +++ b/usr/src/uts/common/os/main.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -394,6 +394,15 @@ main(void) clock_init(); /* + * On some platforms, clkinitf() changes the timing source that + * gethrtime_unscaled() uses to generate timestamps. cbe_init() calls + * clkinitf(), so re-initialize the microstate counters after the + * timesource has been chosen. + */ + init_mstate(&t0, LMS_SYSTEM); + init_cpu_mstate(CPU, CMS_SYSTEM); + + /* * May need to probe to determine latencies from CPU 0 after * gethrtime() comes alive in cbe_init() and before enabling interrupts */ @@ -447,8 +456,8 @@ main(void) if (netboot == 0) (void) strplumb(); - gethrestime(&u.u_start); - curthread->t_start = u.u_start.tv_sec; + gethrestime(&PTOU(curproc)->u_start); + curthread->t_start = PTOU(curproc)->u_start.tv_sec; p->p_mstart = gethrtime(); /* @@ -577,8 +586,8 @@ main(void) pid_setmin(); - bcopy("sched", u.u_psargs, 6); - bcopy("sched", u.u_comm, 5); + bcopy("sched", PTOU(curproc)->u_psargs, 6); + bcopy("sched", PTOU(curproc)->u_comm, 5); sched(); /* NOTREACHED */ } diff --git a/usr/src/uts/common/os/mem_config.c b/usr/src/uts/common/os/mem_config.c index 8d8b978513..64bbc4b5ad 100644 --- a/usr/src/uts/common/os/mem_config.c +++ b/usr/src/uts/common/os/mem_config.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -59,11 +59,6 @@ #include <sys/ddi.h> #include <sys/modctl.h> -extern void memlist_read_lock(void); -extern void memlist_read_unlock(void); -extern void memlist_write_lock(void); -extern void memlist_write_unlock(void); - extern struct memlist *phys_avail; extern void mem_node_add(pfn_t, pfn_t); @@ -3128,60 +3123,6 @@ kphysm_split_memseg( } /* - * The memsegs lock is only taken when modifying the memsegs list - * and rebuilding the pfn hash table (after boot). - * No lock is needed for read as memseg structure are never de-allocated - * and the pointer linkage is never updated until the memseg is ready. - */ -krwlock_t memsegslock; - -void -memsegs_lock(int writer) -{ - rw_enter(&memsegslock, writer ? RW_WRITER : RW_READER); -} - -/*ARGSUSED*/ -void -memsegs_unlock(int writer) -{ - rw_exit(&memsegslock); -} - -/* - * memlist (phys_install, phys_avail) locking. - */ - -/* - * A read/write lock might be better here. - */ -static kmutex_t memlists_mutex; - -void -memlist_read_lock() -{ - mutex_enter(&memlists_mutex); -} - -void -memlist_read_unlock() -{ - mutex_exit(&memlists_mutex); -} - -void -memlist_write_lock() -{ - mutex_enter(&memlists_mutex); -} - -void -memlist_write_unlock() -{ - mutex_exit(&memlists_mutex); -} - -/* * The sfmmu hat layer (e.g.) accesses some parts of the memseg * structure using physical addresses. Therefore a kmem_cache is * used with KMC_NOHASH to avoid page crossings within a memseg diff --git a/usr/src/uts/common/os/mem_config_stubs.c b/usr/src/uts/common/os/mem_config_stubs.c index 7129b4e62b..d3226ff633 100644 --- a/usr/src/uts/common/os/mem_config_stubs.c +++ b/usr/src/uts/common/os/mem_config_stubs.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -65,18 +64,6 @@ kcage_create_throttle(pgcnt_t npages, int flags) return (0); } -/*ARGSUSED*/ -void -memsegs_lock(int x) -{ -} - -/*ARGSUSED*/ -void -memsegs_unlock(int x) -{ -} - void kcage_cageout_init(void) { @@ -86,15 +73,6 @@ void kcage_cageout_wakeup() { } -void -memlist_read_lock() -{ -} - -void -memlist_read_unlock() -{ -} void kcage_tick() diff --git a/usr/src/uts/common/os/policy.c b/usr/src/uts/common/os/policy.c index 59795156bf..8ea071b09b 100644 --- a/usr/src/uts/common/os/policy.c +++ b/usr/src/uts/common/os/policy.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -342,7 +342,7 @@ priv_policy(const cred_t *cr, int priv, boolean_t allzone, int err, if ((allzone || priv == PRIV_ALL || !PRIV_ISASSERT(priv_basic, priv)) && !servicing_interrupt()) { - u.u_acflag |= ASU; /* Needed for SVVS */ + PTOU(curproc)->u_acflag |= ASU; /* Needed for SVVS */ #ifdef C2_AUDIT if (audit_active) audit_priv(priv, diff --git a/usr/src/uts/common/os/shm.c b/usr/src/uts/common/os/shm.c index 49da2f5757..687759018f 100644 --- a/usr/src/uts/common/os/shm.c +++ b/usr/src/uts/common/os/shm.c @@ -317,18 +317,11 @@ shmat(int shmid, caddr_t uaddr, int uflags, uintptr_t *rvp) /* * Handle ISM */ - uint_t n, share_szc; + uint_t share_szc; size_t share_size; struct shm_data ssd; uintptr_t align_hint; - n = page_num_pagesizes(); - if (n < 2) { /* large pages aren't supported */ - as_rangeunlock(as); - error = EINVAL; - goto errret; - } - /* * Pick a share pagesize to use, if (!isspt(sp)). * Otherwise use the already chosen page size. @@ -357,15 +350,22 @@ shmat(int shmid, caddr_t uaddr, int uflags, uintptr_t *rvp) align_hint = share_size; #if defined(__i386) || defined(__amd64) /* - * For 64 bit amd64, we want to share an entire page table - * if possible. We know (ugh) that there are 512 entries in - * in a page table. The number for 32 bit non-PAE should be - * 1024, but I'm not going to special case that. Note using 512 - * won't cause a failure below. It retries with align_hint set - * to share_size + * For x86, we want to share as much of the page table tree + * as possible. We use a large align_hint at first, but + * if that fails, then the code below retries with align_hint + * set to share_size. + * + * The explicit extern here is due to the difficulties + * of getting to platform dependent includes. When/if the + * platform dependent bits of this function are cleaned up, + * another way of doing this should found. */ - while (size >= 512 * (uint64_t)align_hint) - align_hint *= 512; + { + extern uint_t ptes_per_table; + + while (size >= ptes_per_table * (uint64_t)align_hint) + align_hint *= ptes_per_table; + } #endif /* __i386 || __amd64 */ #if defined(__sparcv9) diff --git a/usr/src/uts/common/os/sig.c b/usr/src/uts/common/os/sig.c index 8d46a3405f..808e5d2095 100644 --- a/usr/src/uts/common/os/sig.c +++ b/usr/src/uts/common/os/sig.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -346,7 +346,8 @@ isjobstop(int sig) ASSERT(MUTEX_HELD(&p->p_lock)); - if (u.u_signal[sig-1] == SIG_DFL && sigismember(&stopdefault, sig)) { + if (PTOU(curproc)->u_signal[sig-1] == SIG_DFL && + sigismember(&stopdefault, sig)) { /* * If SIGCONT has been posted since we promoted this signal * from pending to current, then don't do a jobcontrol stop. @@ -476,7 +477,7 @@ issig_justlooking(void) * the process when lwp_nostop is set. */ if (!lwp->lwp_nostop || - u.u_signal[sig-1] != SIG_DFL || + PTOU(curproc)->u_signal[sig-1] != SIG_DFL || !sigismember(&stopdefault, sig)) return (1); } @@ -768,7 +769,8 @@ issig_forreal(void) * signal() interface for setting the signal handler. */ if (sigcld_found && - (sig != SIGCLD || !sigismember(&u.u_sigresethand, SIGCLD))) + (sig != SIGCLD || !sigismember(&PTOU(curproc)->u_sigresethand, + SIGCLD))) sigcld_repost(); if (sig != 0) @@ -1295,7 +1297,7 @@ psig(void) mutex_exit(&p->p_lock); return; } - func = u.u_signal[sig-1]; + func = PTOU(curproc)->u_signal[sig-1]; /* * The signal disposition could have changed since we promoted @@ -1386,10 +1388,10 @@ psig(void) t->t_flag &= ~T_TOMASK; else lwp->lwp_sigoldmask = t->t_hold; - sigorset(&t->t_hold, &u.u_sigmask[sig-1]); - if (!sigismember(&u.u_signodefer, sig)) + sigorset(&t->t_hold, &PTOU(curproc)->u_sigmask[sig-1]); + if (!sigismember(&PTOU(curproc)->u_signodefer, sig)) sigaddset(&t->t_hold, sig); - if (sigismember(&u.u_sigresethand, sig)) + if (sigismember(&PTOU(curproc)->u_sigresethand, sig)) setsigact(sig, SIG_DFL, nullsmask, 0); DTRACE_PROC3(signal__handle, int, sig, k_siginfo_t *, @@ -1526,7 +1528,7 @@ setsigact(int sig, void (*disp)(), k_sigset_t mask, int flags) ASSERT(MUTEX_HELD(&p->p_lock)); - u.u_signal[sig - 1] = disp; + PTOU(curproc)->u_signal[sig - 1] = disp; /* * Honor the SA_SIGINFO flag if the signal is being caught. @@ -1542,25 +1544,25 @@ setsigact(int sig, void (*disp)(), k_sigset_t mask, int flags) if (disp != SIG_DFL && disp != SIG_IGN) { sigdelset(&p->p_ignore, sig); - u.u_sigmask[sig - 1] = mask; + PTOU(curproc)->u_sigmask[sig - 1] = mask; if (!sigismember(&cantreset, sig)) { if (flags & SA_RESETHAND) - sigaddset(&u.u_sigresethand, sig); + sigaddset(&PTOU(curproc)->u_sigresethand, sig); else - sigdelset(&u.u_sigresethand, sig); + sigdelset(&PTOU(curproc)->u_sigresethand, sig); } if (flags & SA_NODEFER) - sigaddset(&u.u_signodefer, sig); + sigaddset(&PTOU(curproc)->u_signodefer, sig); else - sigdelset(&u.u_signodefer, sig); + sigdelset(&PTOU(curproc)->u_signodefer, sig); if (flags & SA_RESTART) - sigaddset(&u.u_sigrestart, sig); + sigaddset(&PTOU(curproc)->u_sigrestart, sig); else - sigdelset(&u.u_sigrestart, sig); + sigdelset(&PTOU(curproc)->u_sigrestart, sig); if (flags & SA_ONSTACK) - sigaddset(&u.u_sigonstack, sig); + sigaddset(&PTOU(curproc)->u_sigonstack, sig); else - sigdelset(&u.u_sigonstack, sig); + sigdelset(&PTOU(curproc)->u_sigonstack, sig); } else if (disp == SIG_IGN || (disp == SIG_DFL && sigismember(&ignoredefault, sig))) { diff --git a/usr/src/uts/common/os/vm_pageout.c b/usr/src/uts/common/os/vm_pageout.c index 53676cbaeb..6a514e0174 100644 --- a/usr/src/uts/common/os/vm_pageout.c +++ b/usr/src/uts/common/os/vm_pageout.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -652,8 +652,8 @@ pageout() proc_pageout->p_stime = 0; proc_pageout->p_cutime = 0; proc_pageout->p_utime = 0; - bcopy("pageout", u.u_psargs, 8); - bcopy("pageout", u.u_comm, 7); + bcopy("pageout", PTOU(curproc)->u_psargs, 8); + bcopy("pageout", PTOU(curproc)->u_comm, 7); /* * Create pageout scanner thread diff --git a/usr/src/uts/common/os/zone.c b/usr/src/uts/common/os/zone.c index 19ea8b31f1..da658c8a48 100644 --- a/usr/src/uts/common/os/zone.c +++ b/usr/src/uts/common/os/zone.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2661,11 +2661,11 @@ zsched(void *arg) nvlist_t *nvl = za->nvlist; nvpair_t *nvp = NULL; - bcopy("zsched", u.u_psargs, sizeof ("zsched")); - bcopy("zsched", u.u_comm, sizeof ("zsched")); - u.u_argc = 0; - u.u_argv = NULL; - u.u_envp = NULL; + bcopy("zsched", PTOU(pp)->u_psargs, sizeof ("zsched")); + bcopy("zsched", PTOU(pp)->u_comm, sizeof ("zsched")); + PTOU(pp)->u_argc = 0; + PTOU(pp)->u_argv = NULL; + PTOU(pp)->u_envp = NULL; closeall(P_FINFO(pp)); /* diff --git a/usr/src/uts/common/sys/auxv_386.h b/usr/src/uts/common/sys/auxv_386.h index 85d4dc5f86..88fe720e8c 100644 --- a/usr/src/uts/common/sys/auxv_386.h +++ b/usr/src/uts/common/sys/auxv_386.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -60,10 +59,12 @@ extern "C" { #define AV_386_SSE3 0x04000 /* SSE3 insns and regs */ #define AV_386_MON 0x08000 /* monitor/mwait insns */ #define AV_386_CX16 0x10000 /* cmpxchg16b insn */ +#define AV_386_AHF 0x20000 /* lahf/sahf insns */ +#define AV_386_TSCP 0x40000 /* rdtscp instruction */ #define FMT_AV_386 \ "\20" \ - "\21cx16" \ + "\23tscp\22ahf\21cx16" \ "\20mon\17sse3\16pause\15sse2\14sse\13fxsr\12amd3dx\11amd3d" \ "\10amdmmx\7mmx\6cmov\5amdsysc\4sep\3cx8\2tsc\1fpu" diff --git a/usr/src/uts/common/sys/bootprops.h b/usr/src/uts/common/sys/bootprops.h index 2f7360ec52..f337777172 100644 --- a/usr/src/uts/common/sys/bootprops.h +++ b/usr/src/uts/common/sys/bootprops.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,6 +46,7 @@ extern "C" { #define BP_SERVER_PATH "server-path" #define BP_SERVER_ROOTOPTS "server-rootopts" #define BP_BOOTP_RESPONSE "bootp-response" +#define BP_NETWORK_INTERFACE "network-interface" #ifdef __cplusplus } diff --git a/usr/src/uts/common/sys/cpr.h b/usr/src/uts/common/sys/cpr.h index bfdd868e14..337cbf9986 100644 --- a/usr/src/uts/common/sys/cpr.h +++ b/usr/src/uts/common/sys/cpr.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,6 +37,7 @@ extern "C" { #include <sys/mutex.h> #include <sys/uadmin.h> #include <sys/compress.h> +#include <sys/archsystm.h> /* * definitions for kernel, cprboot, pmconfig @@ -178,36 +178,27 @@ struct cprconfig { extern int cpr_debug; -#define errp prom_printf -#define DPRINT - /* - * DEBUG1 displays the main flow of CPR. Use it to identify which sub-module - * of CPR causes problems. - * DEBUG2 displays minor stuff that normally won't matter. - * DEBUG3 displays some big loops (cpr_dump); requires much longer runtime. - * DEBUG4 displays lots of cprboot output, cpr_read and page handling. - * DEBUG5 various, mostly unique stuff - * DEBUG9 displays statistical data for CPR on console (by using printf), + * CPR_DEBUG1 displays the main flow of CPR. Use it to identify which + * sub-module of CPR causes problems. + * CPR_DEBUG2 displays minor stuff that normally won't matter. + * CPR_DEBUG3 displays some big loops (cpr_dump); requires much longer runtime. + * CPR_DEBUG4 displays lots of cprboot output, cpr_read and page handling. + * CPR_DEBUG5 various, mostly unique stuff + * CPR_DEBUG9 displays statistical data for CPR on console (by using printf), * such as num page invalidated, etc. */ -#define LEVEL1 0x1 -#define LEVEL2 0x2 -#define LEVEL3 0x4 -#define LEVEL4 0x8 -#define LEVEL5 0x10 -#define LEVEL6 0x20 -#define LEVEL7 0x40 -#define LEVEL8 0x80 - -#define DEBUG1(p) {if (cpr_debug & LEVEL1) p; } -#define DEBUG2(p) {if (cpr_debug & LEVEL2) p; } -#define DEBUG3(p) {if (cpr_debug & LEVEL3) p; } -#define DEBUG4(p) {if (cpr_debug & LEVEL4) p; } -#define DEBUG5(p) {if (cpr_debug & LEVEL5) p; } -#define DEBUG7(p) {if (cpr_debug & LEVEL7) p; } -#define DEBUG8(p) {if (cpr_debug & LEVEL8) p; } -#define DEBUG9(p) {if (cpr_debug & LEVEL6) p; } +#define CPR_DEBUG1 0x1 +#define CPR_DEBUG2 0x2 +#define CPR_DEBUG3 0x4 +#define CPR_DEBUG4 0x8 +#define CPR_DEBUG5 0x10 +#define CPR_DEBUG6 0x20 +#define CPR_DEBUG7 0x40 +#define CPR_DEBUG8 0x80 +#define CPR_DEBUG9 CPR_DEBUG6 + +#define CPR_DEBUG(level, ...) if (cpr_debug & level) cpr_dprintf(__VA_ARGS__) #define CPR_DEBUG_BIT(dval) (1 << (dval - AD_CPR_DEBUG0 - 1)) #define DBG_DONTSHOWRANGE 0 diff --git a/usr/src/uts/common/sys/cpuvar.h b/usr/src/uts/common/sys/cpuvar.h index 1e467e4b64..0af0d086a9 100644 --- a/usr/src/uts/common/sys/cpuvar.h +++ b/usr/src/uts/common/sys/cpuvar.h @@ -301,6 +301,10 @@ extern cpu_core_t cpu_core[]; #define CPU_SPARE 0x100 /* CPU offline available for use */ #define CPU_FAULTED 0x200 /* CPU offline diagnosed faulty */ +#define FMT_CPU_FLAGS \ + "\20\12fault\11spare\10frozen" \ + "\7poweroff\6offline\5enable\4exist\3quiesced\2ready\1run" + #define CPU_ACTIVE(cpu) (((cpu)->cpu_flags & CPU_OFFLINE) == 0) /* @@ -575,6 +579,17 @@ void mbox_lock_init(void); /* initialize cross-call locks */ void mbox_init(int cpun); /* initialize cross-calls */ void poke_cpu(int cpun); /* interrupt another CPU (to preempt) */ +/* + * values for safe_list. Pause state that CPUs are in. + */ +#define PAUSE_IDLE 0 /* normal state */ +#define PAUSE_READY 1 /* paused thread ready to spl */ +#define PAUSE_WAIT 2 /* paused thread is spl-ed high */ +#define PAUSE_DIE 3 /* tell pause thread to leave */ +#define PAUSE_DEAD 4 /* pause thread has left */ + +void mach_cpu_pause(volatile char *); + void pause_cpus(cpu_t *off_cp); void start_cpus(void); int cpus_paused(void); diff --git a/usr/src/uts/common/sys/dtrace.h b/usr/src/uts/common/sys/dtrace.h index d53b88ab82..1c76417830 100644 --- a/usr/src/uts/common/sys/dtrace.h +++ b/usr/src/uts/common/sys/dtrace.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2196,6 +2196,8 @@ extern void dtrace_panic(const char *, ...); extern int dtrace_safe_defer_signal(void); extern void dtrace_safe_synchronous_signal(void); +extern int dtrace_mach_aframes(void); + #if defined(__i386) || defined(__amd64) extern int dtrace_instr_size(uchar_t *instr); extern int dtrace_instr_size_isa(uchar_t *, model_t, int *); diff --git a/usr/src/uts/common/sys/dumphdr.h b/usr/src/uts/common/sys/dumphdr.h index 5949b218c8..dc450713de 100644 --- a/usr/src/uts/common/sys/dumphdr.h +++ b/usr/src/uts/common/sys/dumphdr.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -134,6 +133,9 @@ extern void dumpsys(void); extern void dump_messages(void); extern void dump_ereports(void); extern void dumpvp_write(const void *, size_t); +extern int dump_plat_addr(void); +extern void dump_plat_pfn(void); +extern int dump_plat_data(void *); #endif /* _KERNEL */ diff --git a/usr/src/uts/common/sys/filep.h b/usr/src/uts/common/sys/filep.h index d68fab846b..0cd2b0734e 100644 --- a/usr/src/uts/common/sys/filep.h +++ b/usr/src/uts/common/sys/filep.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -58,6 +57,9 @@ typedef struct dev_ident { /* device identifier block */ #define FI_PARTIAL_CACHE 0x200000 #define FI_NOCACHE 0x400000 +#define FI_COMPRESSED 0x8 /* File compressed in ramdisk */ +#define DECOMP_BUFSIZE (512 * 1024) /* size of decompress buffer */ + typedef struct file_ident { /* file identifier block */ uint_t fi_filedes; char *fi_path; @@ -69,9 +71,14 @@ typedef struct file_ident { /* file identifier block */ char fi_flags; devid_t *fi_devp; char fi_buf[MAXBSIZE]; + int (*fi_getblock)(struct file_ident *); struct inode *fi_inode; struct file_ident *fi_forw; struct file_ident *fi_back; + off_t fi_cfoff; /* compressed file offset */ + caddr_t fi_dcscrbuf; /* decomp scratch buffer */ + size_t fi_dcscrused; /* used bytes in scratch buf */ + struct z_stream_s *fi_dcstream; /* decompression stream */ } fileid_t; extern int diskread(fileid_t *); diff --git a/usr/src/uts/common/sys/hold_page.h b/usr/src/uts/common/sys/hold_page.h new file mode 100644 index 0000000000..0f73e22646 --- /dev/null +++ b/usr/src/uts/common/sys/hold_page.h @@ -0,0 +1,76 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_HOLD_PAGE_H +#define _SYS_HOLD_PAGE_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> +#include <vm/page.h> + +/* + * swrand generates entropy by mapping different pages in the system. This + * can create problems for some hypervisors, as certain pages may be removed + * from the system at any time. The following interfaces allow swrand to + * check the validity and make sure a page is not given away while it is mapped. + * + * int plat_hold_page(pfn_t pfn, int lock, page_t **pp_ret) + * + * If lock is PLAT_HOLD_NO_LOCK, simply check if the page pfn is valid + * in the system. If the page is valid, PLAT_HOLD_OK will be returned. + * pp_ret is ignored if lock is PLAT_HOLD_NO_LOCK. + * + * If lock is PLAT_HOLD_LOCK, in addition to the above, attempt to lock + * the page exclusively. Again, if the lock is successful, the page + * pointer will be put in pp, and PLAT_HOLD_OK will be returned. pp_ret + * must be passed to a later call to plat_release_page. If the page + * wasn't found, or the lock couldn't be grabbed, the return value will + * be PLAT_HOLD_FAIL. + * + * void plat_release_page(page_t *pp) + * + * Unlock the page pp. Should only be called after a previous, + * successful call to plat_release_page(pfn, PLAT_HOLD_LOCK, &pp); + */ + +#define PLAT_HOLD_NO_LOCK 0 +#define PLAT_HOLD_LOCK 1 + +#define PLAT_HOLD_OK 0 +#define PLAT_HOLD_FAIL 1 + +extern int plat_hold_page(pfn_t, int, page_t **); +extern void plat_release_page(page_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_HOLD_PAGE_H */ diff --git a/usr/src/uts/common/sys/isa_defs.h b/usr/src/uts/common/sys/isa_defs.h index b045eb02d8..08fcbd02e5 100644 --- a/usr/src/uts/common/sys/isa_defs.h +++ b/usr/src/uts/common/sys/isa_defs.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -201,6 +201,11 @@ * _RTC_CONFIG * This indicates whether or not the implementation uses /etc/rtc_config * to configure the real-time clock in the kernel. + * + * _UNIX_KRTLD + * This indicates that the implementation uses a dynamically + * linked unix + krtld to form the core kernel image at boot + * time, or (in the absence of this symbol) a prelinked kernel image. */ #ifdef __cplusplus @@ -397,6 +402,7 @@ extern "C" { #define _DMA_USES_VIRTADDR #define _NO_FDISK_PRESENT #define _HAVE_TEM_FIRMWARE +#define _UNIX_KRTLD /* * The following set of definitions characterize the implementation of diff --git a/usr/src/uts/common/sys/kdi.h b/usr/src/uts/common/sys/kdi.h index 64f2b7b7cf..6959aef7d2 100644 --- a/usr/src/uts/common/sys/kdi.h +++ b/usr/src/uts/common/sys/kdi.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -29,6 +28,8 @@ #pragma ident "%Z%%M% %I% %E% SMI" +#include <sys/types.h> + /* * The Kernel/Debugger interface. * @@ -45,17 +46,11 @@ extern "C" { #endif -/* The VA range reserved for the debugger. */ -#if defined(__sparc) -#define SEGDEBUGBASE 0xedd00000 -#define SEGDEBUGSIZE (0xf0000000 - SEGDEBUGBASE) -#elif defined(__amd64) -#define SEGDEBUGBASE 0xffffffffff800000 -#define SEGDEBUGSIZE 0x400000 -#else -#define SEGDEBUGBASE 0xff800000 -#define SEGDEBUGSIZE 0x400000 -#endif +/* + * The VA range reserved for the debugger; used by kmdb. + */ +extern const caddr_t kdi_segdebugbase; +extern const size_t kdi_segdebugsize; struct cpu; struct modctl; @@ -68,16 +63,12 @@ typedef struct kdi kdi_t; extern kdi_debugvec_t *kdi_dvec; extern struct modctl *kdi_dmods; -#define KDI_VERSION 6 +#define KDI_VERSION 7 -extern void kdi_dvec_enter(void); -extern void kdi_dvec_cpu_init(struct cpu *); -#if defined(__i386) || defined(__amd64) -extern void kdi_dvec_idt_sync(struct gate_desc *); -#endif /* __i386 || __amd64 */ extern void kdi_dvec_vmready(void); extern void kdi_dvec_memavail(void); #if defined(__sparc) +extern void kdi_dvec_cpu_init(struct cpu *); extern void kdi_dvec_cpr_restart(void); #endif extern void kdi_dvec_modavail(void); diff --git a/usr/src/uts/common/sys/kdi_impl.h b/usr/src/uts/common/sys/kdi_impl.h index ce605c1815..e488ae6b14 100644 --- a/usr/src/uts/common/sys/kdi_impl.h +++ b/usr/src/uts/common/sys/kdi_impl.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,6 +30,7 @@ #include <sys/kdi.h> #include <sys/kdi_machimpl.h> +#include <sys/privregs.h> #ifdef __cplusplus extern "C" { @@ -43,29 +43,24 @@ struct gdscr; * The debugvec is used by the kernel to interact with the debugger. */ struct kdi_debugvec { - void (*dv_enter)(void); - - void (*dv_cpu_init)(struct cpu *); - void (*dv_kctl_cpu_init)(void); - -#if defined(__i386) || defined(__amd64) - void (*dv_idt_sync)(gate_desc_t *); -#endif /* __i386 || __amd64 */ - - void (*dv_vmready)(void); void (*dv_kctl_vmready)(void); - void (*dv_kctl_memavail)(void); - int (*dv_memavail)(caddr_t, size_t); - -#if defined(__sparc) - void (*dv_cpr_restart)(void); -#endif - void (*dv_kctl_modavail)(void); void (*dv_kctl_thravail)(void); + + void (*dv_vmready)(void); + void (*dv_memavail)(caddr_t, size_t); void (*dv_mod_loaded)(struct modctl *); void (*dv_mod_unloading)(struct modctl *); + +#if defined(__i386) || defined(__amd64) + void (*dv_handle_fault)(greg_t, greg_t, greg_t, int); +#endif +#if defined(__sparc) + void (*dv_kctl_cpu_init)(void); + void (*dv_cpu_init)(struct cpu *); + void (*dv_cpr_restart)(void); +#endif }; typedef struct kdi_plat { @@ -88,6 +83,7 @@ typedef struct kdi_plat { * have been stopped. In such an environment, blocking services such as memory * allocation or synchronization primitives are not available. */ + struct kdi { int kdi_version; @@ -139,6 +135,8 @@ struct kdi { void (*kdi_plat_call)(void (*)(void)); + void (*kdi_kmdb_enter)(void); + kdi_mach_t kdi_mach; kdi_plat_t kdi_plat; }; @@ -155,6 +153,9 @@ extern void cpu_kdi_init(kdi_t *); extern void mach_kdi_init(kdi_t *); extern void plat_kdi_init(kdi_t *); +extern void *boot_kdi_tmpinit(void); +extern void boot_kdi_tmpfini(void *); + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/sys/mem.h b/usr/src/uts/common/sys/mem.h index d1307589a1..31cf613939 100644 --- a/usr/src/uts/common/sys/mem.h +++ b/usr/src/uts/common/sys/mem.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +33,7 @@ extern "C" { #endif #include <sys/types.h> +#include <sys/uio.h> /* * Memory Device Minor Numbers @@ -142,6 +142,8 @@ typedef struct mem_info { extern pfn_t impl_obmem_pfnum(pfn_t); +extern int plat_mem_valid_page(uintptr_t, uio_rw_t); + #endif /* _KERNEL */ #ifdef __cplusplus diff --git a/usr/src/uts/common/sys/mem_config.h b/usr/src/uts/common/sys/mem_config.h index 151d5a4438..31ea4059d1 100644 --- a/usr/src/uts/common/sys/mem_config.h +++ b/usr/src/uts/common/sys/mem_config.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,8 +19,8 @@ * CDDL HEADER END */ /* - * Copyright (c) 1997-2001 by Sun Microsystems, Inc. - * All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ #ifndef _SYS_MEM_CONFIG_H @@ -144,9 +143,6 @@ extern int arch_kphysm_del_supported(void); extern int pfn_is_being_deleted(pfn_t); -extern void memsegs_lock(int); -extern void memsegs_unlock(int); - #endif /* _KERNEL */ #ifdef __cplusplus diff --git a/usr/src/uts/common/sys/memlist.h b/usr/src/uts/common/sys/memlist.h index 10ad8237e6..371ecc522d 100644 --- a/usr/src/uts/common/sys/memlist.h +++ b/usr/src/uts/common/sys/memlist.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,8 +19,8 @@ * CDDL HEADER END */ /* - * Copyright (c) 1991-1998 by Sun Microsystems, Inc. - * All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ #ifndef _SYS_MEMLIST_H @@ -59,8 +58,6 @@ extern int address_in_memlist(struct memlist *, uint64_t, size_t); * to protect reading this list. */ extern struct memlist *phys_install; -extern void memlist_read_lock(void); -extern void memlist_read_unlock(void); #ifdef __cplusplus } diff --git a/usr/src/psm/stand/boot/i386/common/multiboot.h b/usr/src/uts/common/sys/multiboot.h index 7674c16faf..1118aa9f53 100644 --- a/usr/src/psm/stand/boot/i386/common/multiboot.h +++ b/usr/src/uts/common/sys/multiboot.h @@ -18,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,112 +34,115 @@ extern "C" { #endif /* - * Multiboot header must be present withing the first - * 8192 bytes of the elf executable. The flag bit fields - * are defined to request multiboot info from the boot - * loader (see struct multiboot_info below): - * flag[0] mem_upper, mem_loader - * flag[1] boot_device - * flag[2] cmdline (for launching kernel) - * flag[3] mods_count, mods_addr - * flag[4] symbol table for a.out - * flag[5] symbol table for elf - * flag[6] mmap_length, mmap_addr - * flag[7] drives_length, drivers_addr - * flag[8] config_table - * flag[9] boot_loader_name - * flag[10] apm_table - * flag[11] vbe_control_info - * vbe_mode_info - * vbe_mode - * vbe_interface_seg - * vbe_interface_off - * vbe_interface_len + * Definitions of structures/data for using a multiboot compliant OS loader. */ +#define MB_HEADER_MAGIC 0x1BADB002 /* magic */ +#define MB_HEADER_FLAGS 0x00010003 /* flags we use */ +#define MB_HEADER_CHECKSUM -0x1BAEB005 /* -(magic + flag) */ -#define MB_HEADER_MAGIC 0x1BADB002 /* magic */ -#define MB_HEADER_FLAGS 0x00000003 /* flag */ -#define MB_HEADER_CHECKSUM -0x1BADB005 /* -(magic + flag) */ - -/* passed by boot loader to kernel */ +/* + * passed by boot loader to kernel + */ #define MB_BOOTLOADER_MAGIC 0x2BADB002 -#define MB_NETWORK_DRIVE 0x20 /* not clear if part of spec */ - -#define STACK_SIZE 0x4000 - #ifndef _ASM /* excluded from assembly routines */ #include <sys/types.h> +#include <sys/types32.h> -/* The Multiboot header. */ +/* + * The Multiboot header must be somewhere in the 1st 8K of the image that + * the loader loads into memory. + */ typedef struct multiboot_header { - ulong_t magic; - ulong_t flags; - ulong_t checksum; - ulong_t header_addr; - ulong_t load_addr; - ulong_t load_end_addr; - ulong_t bss_end_addr; - ulong_t entry_addr; + uint32_t magic; + uint32_t flags; + uint32_t checksum; + caddr32_t header_addr; /* use as (mutliboot_header_t *) */ + caddr32_t load_addr; + caddr32_t load_end_addr; + caddr32_t bss_end_addr; + caddr32_t entry_addr; } multiboot_header_t; /* The section header table for ELF. */ typedef struct mb_elf_shtable { - ulong_t num; - ulong_t size; - ulong_t addr; - ulong_t shndx; + uint32_t num; + uint32_t size; + uint32_t addr; + uint32_t shndx; } mb_elf_shtable_t; -/* The Multiboot information. */ -typedef struct multiboot_info { - ulong_t flags; - ulong_t mem_lower; - ulong_t mem_upper; - ulong_t boot_device; - ulong_t cmdline; - ulong_t mods_count; - ulong_t mods_addr; - mb_elf_shtable_t elf_sec; - ulong_t mmap_length; - ulong_t mmap_addr; - ulong_t drives_length; /* overload with dhcpack */ - ulong_t drives_addr; - ulong_t config_table; - ulong_t boot_loader_name; - ulong_t apm_table; - ulong_t vbe_control_info; - ulong_t vbe_mode_info; - ushort_t vbe_mode; - ushort_t vbe_interface_seg; - ushort_t vbe_interface_off; - ushort_t vbe_interface_len; - ulong_t efi_systab; - ulong_t acpi_root_tab; -} multiboot_info_t; - /* The module structure. */ typedef struct mb_module { - ulong_t mod_start; - ulong_t mod_end; - ulong_t string; - ulong_t reserved; + caddr32_t mod_start; + caddr32_t mod_end; + caddr32_t mod_name; /* use as (char *) */ + uint32_t reserved; } mb_module_t; /* - * The memory map. Be careful that the offset 0 is base_addr_low - * but no size. + * Memory map data structure. Walked in a bizarre way - see mutltiboot + * documentation for example. */ typedef struct mb_memory_map { - ulong_t size; - ulong_t base_addr_low; - ulong_t base_addr_high; - ulong_t length_low; - ulong_t length_high; - ulong_t type; + uint32_t size; + uint32_t base_addr_low; + uint32_t base_addr_high; + uint32_t length_low; + uint32_t length_high; + uint32_t type; /* only value of 1 is RAM */ } mb_memory_map_t; + +/* + * The Multiboot information. This is supplied by the multiboot loader + * for the OS. + * + * The flag bit fields defined what multiboot info the boot + * loader (see struct multiboot_info below) supplied: + * flag[0] mem_upper, mem_loader + * flag[1] boot_device + * flag[2] cmdline (for launching kernel) + * flag[3] mods_count, mods_addr + * flag[4] symbol table for a.out + * flag[5] symbol table for elf + * flag[6] mmap_length, mmap_addr + * flag[7] drives_length, drivers_addr + * flag[8] config_table + * flag[9] boot_loader_name + * flag[10] apm_table + * flag[11] vbe_control_info + * vbe_mode_info + * vbe_mode + * vbe_interface_seg + * vbe_interface_off + * vbe_interface_len + */ +typedef struct multiboot_info { + uint32_t flags; + uint32_t mem_lower; /* # of pages below 1Meg */ + uint32_t mem_upper; /* # of pages above 1Meg */ + uint32_t boot_device; + caddr32_t cmdline; /* use as (char *) */ + uint32_t mods_count; + caddr32_t mods_addr; /* use as (mb_module_t *) */ + mb_elf_shtable_t elf_sec; + uint32_t mmap_length; + caddr32_t mmap_addr; /* use as (mb_memory_map_t *) */ + uint32_t drives_length; + caddr32_t drives_addr; + caddr32_t config_table; + caddr32_t boot_loader_name; + caddr32_t apm_table; + uint32_t vbe_control_info; + uint32_t vbe_mode_info; + uint16_t vbe_mode; + uint16_t vbe_interface_seg; + uint16_t vbe_interface_off; + uint16_t vbe_interface_len; +} multiboot_info_t; + /* * netinfo for Solaris diskless booting * XXX - not part of multiboot spec @@ -156,13 +160,12 @@ struct sol_netinfo { }; /* identify bootp/dhcp reply or rarp/ifconfig */ -#define SN_TYPE_BOOTP 2 -#define SN_TYPE_RARP 0xf0 +#define SN_TYPE_BOOTP 2 +#define SN_TYPE_RARP 0xf0 + -/* Check if the bit BIT in FLAGS is set. */ -#define MB_CHECK_FLAG(flags, bit) ((flags) & (1 << (bit))) +#endif /* _ASM */ -#endif /* _ASM */ #ifdef __cplusplus } diff --git a/usr/src/uts/common/sys/ontrap.h b/usr/src/uts/common/sys/ontrap.h index 5b19af9d74..a7718848a1 100644 --- a/usr/src/uts/common/sys/ontrap.h +++ b/usr/src/uts/common/sys/ontrap.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -87,6 +86,10 @@ extern "C" { #define OT_DATA_ACCESS 0x01 /* data access exception protection */ #define OT_DATA_EC 0x02 /* error correction trap protection */ +#if defined(__x86) +#define OT_SEGMENT_ACCESS 0x03 /* segmentation exception */ +#endif + #if !defined(_ASM) typedef struct on_trap_data { diff --git a/usr/src/uts/common/sys/param.h b/usr/src/uts/common/sys/param.h index 4103fde786..cb7ab43c2f 100644 --- a/usr/src/uts/common/sys/param.h +++ b/usr/src/uts/common/sys/param.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -420,6 +419,12 @@ extern const int _clsize; #define dtopt(DD) ((DD) >> (PAGESHIFT - DEV_BSHIFT)) /* + * kB to pages and back + */ +#define kbtop(x) ((x) >> (PAGESHIFT - 10)) +#define ptokb(x) ((x) << (PAGESHIFT - 10)) + +/* * POSIX.4 related configuration parameters */ #define _AIO_LISTIO_MAX (4096) diff --git a/usr/src/uts/common/sys/systm.h b/usr/src/uts/common/sys/systm.h index ac465ad49f..5f1b4ee211 100644 --- a/usr/src/uts/common/sys/systm.h +++ b/usr/src/uts/common/sys/systm.h @@ -23,7 +23,7 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -168,64 +168,6 @@ dev_t expldev(dev32_t); int bcmp(const void *, const void *, size_t) __PURE; int stoi(char **); void numtos(ulong_t, char *); -size_t strlen(const char *) __PURE; -char *strcat(char *, const char *); -char *strncat(char *, const char *, size_t); -char *strcpy(char *, const char *); -char *strncpy(char *, const char *, size_t); -/* Need to be consistent with <string.h> C++ definitions */ -#if __cplusplus >= 199711L -extern const char *strchr(const char *, int); -#ifndef _STRCHR_INLINE -#define _STRCHR_INLINE -extern "C++" { - inline char *strchr(char *__s, int __c) { - return (char *)strchr((const char *)__s, __c); - } -} -#endif /* _STRCHR_INLINE */ -extern const char *strrchr(const char *, int); -#ifndef _STRRCHR_INLINE -#define _STRRCHR_INLINE -extern "C++" { - inline char *strrchr(char *__s, int __c) { - return (char *)strrchr((const char *)__s, __c); - } -} -#endif /* _STRRCHR_INLINE */ -extern const char *strstr(const char *, const char *); -#ifndef _STRSTR_INLINE -#define _STRSTR_INLINE -extern "C++" { - inline char *strstr(char *__s1, const char *__s2) { - return (char *)strstr((const char *)__s1, __s2); - } -} -#endif /* _STRSTR_INLINE */ -#else /* __cplusplus >= 199711L */ -char *strchr(const char *, int); -char *strrchr(const char *, int); -char *strstr(const char *, const char *); -#endif /* __cplusplus >= 199711L */ -char *strnrchr(const char *, int, size_t); -int strcmp(const char *, const char *) __PURE; -int strncmp(const char *, const char *, size_t) __PURE; -int strcasecmp(const char *, const char *) __PURE; -int strncasecmp(const char *, const char *, size_t) __PURE; -/* Need to be consistent with <string.h> C++ definitions */ -#if __cplusplus >= 199711L -extern const char *strpbrk(const char *, const char *); -#ifndef _STRPBRK_INLINE -#define _STRPBRK_INLINE -extern "C++" { - inline char *strpbrk(char *__s1, const char *__s2) { - return (char *)strpbrk((const char *)__s1, __s2); - } -} -#endif /* _STRPBRK_INLINE */ -#else /* __cplusplus >= 199711L */ -char *strpbrk(const char *, const char *); -#endif /* __cplusplus >= 199711L */ int strident_valid(const char *); void strident_canon(char *, size_t); int getsubopt(char **optionsp, char * const *tokens, char **valuep); @@ -244,22 +186,15 @@ int copyinstr_noerr(const char *, char *, size_t, size_t *); int copyoutstr(const char *, char *, size_t, size_t *); int copyoutstr_noerr(const char *, char *, size_t, size_t *); int copystr(const char *, char *, size_t, size_t *); -void bcopy(const void *, void *, size_t); void ucopy(const void *, void *, size_t); void ucopystr(const char *, char *, size_t, size_t *); void pgcopy(const void *, void *, size_t); void ovbcopy(const void *, void *, size_t); -void bzero(void *, size_t); void uzero(void *, size_t); int kcopy(const void *, void *, size_t); int kcopy_nta(const void *, void *, size_t, int); int kzero(void *, size_t); -extern void *memset(void *, int, size_t); -extern void *memcpy(void *, const void *, size_t); -extern void *memmove(void *, const void *, size_t); -extern int memcmp(const void *, const void *, size_t); - int fuword8(const void *, uint8_t *); int fuword16(const void *, uint16_t *); int fuword32(const void *, uint32_t *); @@ -441,11 +376,6 @@ extern void swtch(void); extern uint_t kcpc_key; /* TSD key for performance counter context */ -#ifdef __lint -extern int __lintzero; /* for spoofing lint */ -#endif - - /* * initname holds the path to init and is used as a point of rendezvous * between krtld (which processes the boot arguments) and the kernel. @@ -465,6 +395,82 @@ extern int start_init_common(void); #endif /* _KERNEL */ +#if defined(_KERNEL) || defined(_BOOT) + +size_t strlcat(char *, const char *, size_t); +size_t strlen(const char *) __PURE; +char *strcat(char *, const char *); +char *strncat(char *, const char *, size_t); +char *strcpy(char *, const char *); +char *strncpy(char *, const char *, size_t); +/* Need to be consistent with <string.h> C++ definitions */ +#if __cplusplus >= 199711L +extern const char *strchr(const char *, int); +#ifndef _STRCHR_INLINE +#define _STRCHR_INLINE +extern "C++" { + inline char *strchr(char *__s, int __c) { + return (char *)strchr((const char *)__s, __c); + } +} +#endif /* _STRCHR_INLINE */ +extern const char *strrchr(const char *, int); +#ifndef _STRRCHR_INLINE +#define _STRRCHR_INLINE +extern "C++" { + inline char *strrchr(char *__s, int __c) { + return (char *)strrchr((const char *)__s, __c); + } +} +#endif /* _STRRCHR_INLINE */ +extern const char *strstr(const char *, const char *); +#ifndef _STRSTR_INLINE +#define _STRSTR_INLINE +extern "C++" { + inline char *strstr(char *__s1, const char *__s2) { + return (char *)strstr((const char *)__s1, __s2); + } +} +#endif /* _STRSTR_INLINE */ +#else /* __cplusplus >= 199711L */ +char *strchr(const char *, int); +char *strrchr(const char *, int); +char *strstr(const char *, const char *); +#endif /* __cplusplus >= 199711L */ +char *strnrchr(const char *, int, size_t); +int strcmp(const char *, const char *) __PURE; +int strncmp(const char *, const char *, size_t) __PURE; +int strcasecmp(const char *, const char *) __PURE; +int strncasecmp(const char *, const char *, size_t) __PURE; +/* Need to be consistent with <string.h> C++ definitions */ +#if __cplusplus >= 199711L +extern const char *strpbrk(const char *, const char *); +#ifndef _STRPBRK_INLINE +#define _STRPBRK_INLINE +extern "C++" { + inline char *strpbrk(char *__s1, const char *__s2) { + return (char *)strpbrk((const char *)__s1, __s2); + } +} +#endif /* _STRPBRK_INLINE */ +#else /* __cplusplus >= 199711L */ +char *strpbrk(const char *, const char *); +#endif /* __cplusplus >= 199711L */ +void bcopy(const void *, void *, size_t); +void bzero(void *, size_t); + +extern void *memset(void *, int, size_t); +extern void *memcpy(void *, const void *, size_t); +extern void *memmove(void *, const void *, size_t); +extern int memcmp(const void *, const void *, size_t); + +#ifdef __lint +extern int __lintzero; /* for spoofing lint */ +#else /* __lint */ +#define __lintzero 0 +#endif /* __lint */ +#endif /* _KERNEL || _BOOT */ + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/sys/time.h b/usr/src/uts/common/sys/time.h index ab74c47d5f..ffc2c7dcfb 100644 --- a/usr/src/uts/common/sys/time.h +++ b/usr/src/uts/common/sys/time.h @@ -9,7 +9,7 @@ */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -411,7 +411,8 @@ int gettimeofday(); * non-X/Open applications, including this header will still make * visible these definitions. */ -#if !defined(_KERNEL) && !defined(__XOPEN_OR_POSIX) || defined(__EXTENSIONS__) +#if !defined(_BOOT) && !defined(_KERNEL) && \ + !defined(__XOPEN_OR_POSIX) || defined(__EXTENSIONS__) #include <time.h> #endif diff --git a/usr/src/uts/common/sys/types.h b/usr/src/uts/common/sys/types.h index b38a5d1e13..ac5de5d5c0 100644 --- a/usr/src/uts/common/sys/types.h +++ b/usr/src/uts/common/sys/types.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -24,7 +23,7 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -235,7 +234,7 @@ typedef longlong_t offset_t; typedef u_longlong_t u_offset_t; typedef u_longlong_t len_t; typedef u_longlong_t diskaddr_t; -#if (defined(_KERNEL) || defined(_KMEMUSER)) +#if (defined(_KERNEL) || defined(_KMEMUSER) || defined(_BOOT)) typedef uint64_t paddr_t; #endif diff --git a/usr/src/uts/common/sys/user.h b/usr/src/uts/common/sys/user.h index 7d58d69e8c..9061fa5a23 100644 --- a/usr/src/uts/common/sys/user.h +++ b/usr/src/uts/common/sys/user.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -246,7 +246,6 @@ typedef struct user { #include <sys/proc.h> /* cannot include before user defined */ #ifdef _KERNEL -#define u (curproc->p_user) /* user is now part of proc structure */ #define P_FINFO(p) (&(p)->p_user.u_finfo) #endif /* _KERNEL */ diff --git a/usr/src/uts/common/syscall/mkdir.c b/usr/src/uts/common/syscall/mkdir.c index fc9262b0a3..ef50e5a99d 100644 --- a/usr/src/uts/common/syscall/mkdir.c +++ b/usr/src/uts/common/syscall/mkdir.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,11 +18,13 @@ * * CDDL HEADER END */ + /* - * Copyright 1996 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ + /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ @@ -32,7 +33,7 @@ * under license from the Regents of the University of California. */ -#ident "%Z%%M% %I% %E% SMI" +#pragma ident "%Z%%M% %I% %E% SMI" #include <sys/param.h> #include <sys/isa_defs.h> @@ -59,7 +60,7 @@ mkdir(char *dname, int dmode) vattr.va_mode = dmode & PERMMASK; vattr.va_mask = AT_TYPE|AT_MODE; error = vn_create(dname, UIO_USERSPACE, &vattr, EXCL, 0, &vp, CRMKDIR, - 0, u.u_cmask); + 0, PTOU(curproc)->u_cmask); if (error) return (set_errno(error)); VN_RELE(vp); diff --git a/usr/src/uts/common/syscall/mknod.c b/usr/src/uts/common/syscall/mknod.c index 26250387e4..2b61dac506 100644 --- a/usr/src/uts/common/syscall/mknod.c +++ b/usr/src/uts/common/syscall/mknod.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -90,7 +89,7 @@ mknod(char *fname, mode_t fmode, dev_t dev) } why = ((fmode & S_IFMT) == S_IFDIR) ? CRMKDIR : CRMKNOD; if (error = vn_create(fname, UIO_USERSPACE, &vattr, EXCL, 0, &vp, - why, 0, u.u_cmask)) + why, 0, PTOU(curproc)->u_cmask)) return (set_errno(error)); VN_RELE(vp); return (0); diff --git a/usr/src/uts/common/syscall/open.c b/usr/src/uts/common/syscall/open.c index 40e7faa097..f5b873bdb7 100644 --- a/usr/src/uts/common/syscall/open.c +++ b/usr/src/uts/common/syscall/open.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -160,7 +159,7 @@ copen(int startfd, char *fname, int filemode, int createmode) */ error = vn_openat(fname, UIO_USERSPACE, filemode, (int)(createmode & MODEMASK), &vp, CRCREAT, - u.u_cmask, startvp); + PTOU(curproc)->u_cmask, startvp); if (startvp != NULL) VN_RELE(startvp); diff --git a/usr/src/uts/common/syscall/sigaction.c b/usr/src/uts/common/syscall/sigaction.c index cc9850229e..0ed2022fd8 100644 --- a/usr/src/uts/common/syscall/sigaction.c +++ b/usr/src/uts/common/syscall/sigaction.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -50,6 +49,7 @@ sigaction(int sig, struct sigaction *actp, struct sigaction *oactp) struct sigaction oact; k_sigset_t set; proc_t *p; + user_t *ua; int sigcld_look = 0; if (sig <= 0 || sig >= NSIG || @@ -77,26 +77,27 @@ sigaction(int sig, struct sigaction *actp, struct sigaction *oactp) } p = curproc; + ua = PTOU(p); mutex_enter(&p->p_lock); if (oactp) { int flags; void (*disp)(); - disp = u.u_signal[sig - 1]; + disp = ua->u_signal[sig - 1]; flags = 0; if (disp != SIG_DFL && disp != SIG_IGN) { - set = u.u_sigmask[sig-1]; + set = ua->u_sigmask[sig-1]; if (sigismember(&p->p_siginfo, sig)) flags |= SA_SIGINFO; - if (sigismember(&u.u_sigrestart, sig)) + if (sigismember(&ua->u_sigrestart, sig)) flags |= SA_RESTART; - if (sigismember(&u.u_sigonstack, sig)) + if (sigismember(&ua->u_sigonstack, sig)) flags |= SA_ONSTACK; - if (sigismember(&u.u_sigresethand, sig)) + if (sigismember(&ua->u_sigresethand, sig)) flags |= SA_RESETHAND; - if (sigismember(&u.u_signodefer, sig)) + if (sigismember(&ua->u_signodefer, sig)) flags |= SA_NODEFER; } else sigemptyset(&set); @@ -144,6 +145,7 @@ sigaction32(int sig, struct sigaction32 *actp, struct sigaction32 *oactp) struct sigaction32 oact32; k_sigset_t set; proc_t *p; + user_t *ua; int sigcld_look = 0; if (sig <= 0 || sig >= NSIG || @@ -171,26 +173,27 @@ sigaction32(int sig, struct sigaction32 *actp, struct sigaction32 *oactp) } p = curproc; + ua = PTOU(p); mutex_enter(&p->p_lock); if (oactp) { int flags; void (*disp)(); - disp = u.u_signal[sig - 1]; + disp = ua->u_signal[sig - 1]; flags = 0; if (disp != SIG_DFL && disp != SIG_IGN) { - set = u.u_sigmask[sig-1]; + set = ua->u_sigmask[sig-1]; if (sigismember(&p->p_siginfo, sig)) flags |= SA_SIGINFO; - if (sigismember(&u.u_sigrestart, sig)) + if (sigismember(&ua->u_sigrestart, sig)) flags |= SA_RESTART; - if (sigismember(&u.u_sigonstack, sig)) + if (sigismember(&ua->u_sigonstack, sig)) flags |= SA_ONSTACK; - if (sigismember(&u.u_sigresethand, sig)) + if (sigismember(&ua->u_sigresethand, sig)) flags |= SA_RESETHAND; - if (sigismember(&u.u_signodefer, sig)) + if (sigismember(&ua->u_signodefer, sig)) flags |= SA_NODEFER; } else sigemptyset(&set); diff --git a/usr/src/uts/common/syscall/ssig.c b/usr/src/uts/common/syscall/ssig.c index e0998f474b..946e2f5cac 100644 --- a/usr/src/uts/common/syscall/ssig.c +++ b/usr/src/uts/common/syscall/ssig.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -24,7 +23,7 @@ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -107,7 +106,7 @@ ssig(int signo, void (*func)()) if (sigismember(&curthread->t_hold, sig)) retval = (int)SIG_HOLD; else - retval = (int)(uintptr_t)u.u_signal[sig-1]; + retval = (int)(uintptr_t)PTOU(curproc)->u_signal[sig-1]; if (func == SIG_HOLD) { sigaddset(&curthread->t_hold, sig); mutex_exit(&p->p_lock); @@ -140,7 +139,7 @@ ssig(int signo, void (*func)()) return (set_errno(EINVAL)); } #endif - retval = (int)(uintptr_t)u.u_signal[sig-1]; + retval = (int)(uintptr_t)PTOU(curproc)->u_signal[sig-1]; flags = SA_RESETHAND|SA_NODEFER; break; diff --git a/usr/src/uts/common/syscall/uadmin.c b/usr/src/uts/common/syscall/uadmin.c index 3b9833088e..cb71c07b9a 100644 --- a/usr/src/uts/common/syscall/uadmin.c +++ b/usr/src/uts/common/syscall/uadmin.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -217,15 +217,15 @@ kadmin(int cmd, int fcn, void *mdep, cred_t *credp) * do not release these resources. */ if (ttoproc(curthread) != &p0) { - VN_RELE(u.u_cdir); - if (u.u_rdir) - VN_RELE(u.u_rdir); - if (u.u_cwd) - refstr_rele(u.u_cwd); - - u.u_cdir = rootdir; - u.u_rdir = NULL; - u.u_cwd = NULL; + VN_RELE(PTOU(curproc)->u_cdir); + if (PTOU(curproc)->u_rdir) + VN_RELE(PTOU(curproc)->u_rdir); + if (PTOU(curproc)->u_cwd) + refstr_rele(PTOU(curproc)->u_cwd); + + PTOU(curproc)->u_cdir = rootdir; + PTOU(curproc)->u_rdir = NULL; + PTOU(curproc)->u_cwd = NULL; } /* diff --git a/usr/src/uts/common/syscall/umask.c b/usr/src/uts/common/syscall/umask.c index e80d1de9a6..b753269afc 100644 --- a/usr/src/uts/common/syscall/umask.c +++ b/usr/src/uts/common/syscall/umask.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,11 +18,16 @@ * * CDDL HEADER END */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ -#ident "%Z%%M% %I% %E% SMI" /* from SVr4.0 1.78 */ +#pragma ident "%Z%%M% %I% %E% SMI" #include <sys/param.h> #include <sys/types.h> @@ -41,9 +45,9 @@ int umask(int mask) { - register mode_t t; + mode_t t; - t = u.u_cmask; - u.u_cmask = (mode_t)(mask & PERMMASK); + t = PTOU(curproc)->u_cmask; + PTOU(curproc)->u_cmask = (mode_t)(mask & PERMMASK); return ((int)t); } diff --git a/usr/src/uts/common/vm/page.h b/usr/src/uts/common/vm/page.h index 733e4574c2..5824f1ef9e 100644 --- a/usr/src/uts/common/vm/page.h +++ b/usr/src/uts/common/vm/page.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -872,6 +872,7 @@ int page_szc_user_filtered(size_t); #define P_NORELOC 0x40 /* Page is non-relocatable */ #define P_MIGRATE 0x20 /* Migrate page on next touch */ #define P_SWAP 0x10 /* belongs to vnode that is V_ISSWAP */ +#define P_BOOTPAGES 0x08 /* member of bootpages list */ #define PP_ISFREE(pp) ((pp)->p_state & P_FREE) #define PP_ISAGED(pp) (((pp)->p_state & P_FREE) && \ @@ -882,6 +883,7 @@ int page_szc_user_filtered(size_t); #define PP_ISNORELOCKERNEL(pp) (PP_ISNORELOC(pp) && PP_ISKAS(pp)) #define PP_ISMIGRATE(pp) ((pp)->p_state & P_MIGRATE) #define PP_ISSWAP(pp) ((pp)->p_state & P_SWAP) +#define PP_ISBOOTPAGES(pp) ((pp)->p_state & P_BOOTPAGES) #define PP_SETFREE(pp) ((pp)->p_state = ((pp)->p_state & ~P_MIGRATE) \ | P_FREE) @@ -889,12 +891,14 @@ int page_szc_user_filtered(size_t); #define PP_SETNORELOC(pp) ((pp)->p_state |= P_NORELOC) #define PP_SETMIGRATE(pp) ((pp)->p_state |= P_MIGRATE) #define PP_SETSWAP(pp) ((pp)->p_state |= P_SWAP) +#define PP_SETBOOTPAGES(pp) ((pp)->p_state |= P_BOOTPAGES) #define PP_CLRFREE(pp) ((pp)->p_state &= ~P_FREE) #define PP_CLRAGED(pp) ASSERT(!PP_ISAGED(pp)) #define PP_CLRNORELOC(pp) ((pp)->p_state &= ~P_NORELOC) #define PP_CLRMIGRATE(pp) ((pp)->p_state &= ~P_MIGRATE) #define PP_CLRSWAP(pp) ((pp)->p_state &= ~P_SWAP) +#define PP_CLRBOOTPAGES(pp) ((pp)->p_state &= ~P_BOOTPAGES) /* * Flags for page_t p_toxic, for tracking memory hardware errors. @@ -1133,6 +1137,14 @@ int page_trycapture(page_t *pp, uint_t szc, uint_t flags, void *datap); void page_unlock_capture(page_t *pp); int page_capture_unretire_pp(page_t *); +extern void memsegs_lock(int); +extern void memsegs_unlock(int); +extern int memsegs_lock_held(void); +extern void memlist_read_lock(void); +extern void memlist_read_unlock(void); +extern void memlist_write_lock(void); +extern void memlist_write_unlock(void); + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/vm/page_lock.c b/usr/src/uts/common/vm/page_lock.c index 4dab7c8bc7..9b00532b01 100644 --- a/usr/src/uts/common/vm/page_lock.c +++ b/usr/src/uts/common/vm/page_lock.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -983,3 +983,56 @@ page_szc_lock_assert(page_t *pp) return (MUTEX_HELD(mtx)); } + +/* + * memseg locking + */ +static krwlock_t memsegslock; + +/* + * memlist (phys_install, phys_avail) locking. + */ +static krwlock_t memlists_lock; + +void +memsegs_lock(int writer) +{ + rw_enter(&memsegslock, writer ? RW_WRITER : RW_READER); +} + +/*ARGSUSED*/ +void +memsegs_unlock(int writer) +{ + rw_exit(&memsegslock); +} + +int +memsegs_lock_held(void) +{ + return (RW_LOCK_HELD(&memsegslock)); +} + +void +memlist_read_lock(void) +{ + rw_enter(&memlists_lock, RW_READER); +} + +void +memlist_read_unlock(void) +{ + rw_exit(&memlists_lock); +} + +void +memlist_write_lock(void) +{ + rw_enter(&memlists_lock, RW_WRITER); +} + +void +memlist_write_unlock(void) +{ + rw_exit(&memlists_lock); +} diff --git a/usr/src/uts/common/zmod/zmod.c b/usr/src/uts/common/zmod/zmod.c index 48383db9dc..677505f5d0 100644 --- a/usr/src/uts/common/zmod/zmod.c +++ b/usr/src/uts/common/zmod/zmod.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ */ /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -88,29 +87,3 @@ z_strerror(int err) return (z_errmsg[i]); } - -static struct modlmisc modlmisc = { - &mod_miscops, "RFC 1950 decompression routines" -}; - -static struct modlinkage modlinkage = { - MODREV_1, &modlmisc, NULL -}; - -int -_init(void) -{ - return (mod_install(&modlinkage)); -} - -int -_info(struct modinfo *mip) -{ - return (mod_info(&modlinkage, mip)); -} - -int -_fini(void) -{ - return (mod_remove(&modlinkage)); -} diff --git a/usr/src/uts/i86pc/Makefile b/usr/src/uts/i86pc/Makefile index cfd649a46b..aa3fb7f1f2 100644 --- a/usr/src/uts/i86pc/Makefile +++ b/usr/src/uts/i86pc/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -43,7 +43,8 @@ INTEL_LIB_DIR = $(UTSBASE)/intel/lint-libs/$(OBJS_DIR) INTEL_LINTS = genunix LINT_LIBS = $(LINT_LIB) \ - $(KMODS:%=$(LINT_LIB_DIR)/llib-l%.ln) \ + $(GENUNIX_KMODS:%=$(LINT_LIB_DIR)/llib-l%.ln) \ + $(PARALLEL_KMODS:%=$(LINT_LIB_DIR)/llib-l%.ln) \ $(CLOSED_KMODS:%=$(LINT_LIB_DIR)/llib-l%.ln) \ $(INTEL_LINTS:%=$(INTEL_LIB_DIR)/llib-l%.ln) @@ -65,7 +66,7 @@ check := TARGET= check .KEEP_STATE: -.PARALLEL: $(KMODS) $(CLOSED_KMODS) $(XMODS) $(CLOSED_XMODS) \ +.PARALLEL: $(PARALLEL_KMODS) $(CLOSED_KMODS) $(XMODS) $(CLOSED_XMODS) \ modlist modlist.intel INITIAL_TARGETS = \ @@ -120,18 +121,6 @@ install_h check: FRC @cd sys; pwd; $(MAKE) $(TARGET) # -# For some x86 OEMs that deliver their own platform kernel modules but -# will not deliver anything in usr/platform, they should add their platforms -# here so a symlink will be created to the standard usr/platform/i86pc. -# -OEM_LINKS = ncri86pc - -OEM_USR_PLAT_LINKS = $(OEM_LINKS:%=$(USR_PLAT_DIR)/%) - -$(OEM_USR_PLAT_LINKS): - $(INS.slink1) - -# # Definitions for the /platform directory aliases. # Currently none for i86pc. # @@ -148,11 +137,6 @@ install_platforms: $(ROOT_PSM_DIR) $(USR_PSM_DIR) \ $(OEM_USR_PLAT_LINKS) # -# Work-around to disable acpica global crosscheck lint warnings -# -LGREP.i86pc = grep -v 'i86pc/io/acpica' - -# # Full kernel lint target. # LINT_TARGET = globallint @@ -162,15 +146,13 @@ globallint := LINTFLAGS += -erroff=E_NAME_MULTIPLY_DEF2 globallint: @-$(ECHO) "\nFULL KERNEL: global crosschecks:" - @-$(LINT) $(LINTFLAGS) $(LINT_LIBS) 2>&1 | $(LGREP.i86pc) | $(LGREP.2) + @-$(LINT) $(LINTFLAGS) $(LINT_LIBS) 2>&1 | $(LGREP.2) lint: lintlib .WAIT modlintlib .WAIT $(INTEL_LINTS) $(LINT_DEPS) $(INTEL_LINTS): FRC @cd $(UTSBASE)/intel/$@; pwd; $(MAKE) modlintlib -FRC: - include ../Makefile.targ # diff --git a/usr/src/uts/i86pc/Makefile.files b/usr/src/uts/i86pc/Makefile.files index ebbb9934aa..927f65344c 100644 --- a/usr/src/uts/i86pc/Makefile.files +++ b/usr/src/uts/i86pc/Makefile.files @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -36,6 +36,7 @@ CORE_OBJS += \ beeper.o \ biosdisk.o \ + bios_call.o \ cbe.o \ cmi.o \ confunix.o \ @@ -44,16 +45,26 @@ CORE_OBJS += \ ddi_impl.o \ dtrace_subr.o \ dvma.o \ + fpu_subr.o \ + fakebop.o \ graphics.o \ + hardclk.o \ hat_i86.o \ hat_kdi.o \ hment.o \ + hold_page.o \ hrtimers.o \ htable.o \ + i8254.o \ + i86_mmu.o \ instr_size.o \ intr.o \ + kboot_mmu.o \ + kdi_subr.o \ + kdi_idt.o \ + kdi_idthdl.o \ + kdi_asm.o \ lgrpplat.o \ - mach_i86mmu.o \ mach_kdi.o \ mach_sysconfig.o \ machdep.o \ @@ -63,6 +74,7 @@ CORE_OBJS += \ mp_call.o \ mp_implfuncs.o \ mp_machdep.o \ + mp_pc.o \ mp_startup.o \ memscrub.o \ mpcore.o \ @@ -77,6 +89,7 @@ CORE_OBJS += \ ppage.o \ startup.o \ timestamp.o \ + todpc_subr.o \ trap.o \ vm_machdep.o \ x_call.o @@ -88,6 +101,20 @@ CORE_OBJS += \ CORE_OBJS += $(SMBIOS_OBJS) # +# These get compiled twice: +# - once in the dboot (direct boot) identity mapped code +# - once for use during early startup in unix +# +BOOT_DRIVER_OBJS = \ + boot_console.o \ + boot_keyboard.o \ + boot_keyboard_table.o \ + boot_vga.o \ + boot_mmu.o + +CORE_OBJS += $(BOOT_DRIVER_OBJS) + +# # locore.o is special. It must be the first file relocated so that it # it is relocated just where its name implies. # @@ -106,37 +133,35 @@ SPECIAL_OBJS_64 += \ SPECIAL_OBJS += $(SPECIAL_OBJS_$(CLASS)) # -# driver modules +# Objects that get compiled into the identity mapped PT_LOAD section of unix +# to handle the earliest part of booting. # -ROOTNEX_OBJS += rootnex.o -ISANEXUS_OBJS += isa.o dma_engine.o i8237A.o -PCINEXUS_OBJS += pci.o pci_common.o pci_kstats.o pci_tools.o -PCI_PCINEXUS_OBJS += pci_pci.o - -TCIC_OBJS += tcic.o +DBOOT_OBJS_32 = -FD_OBJS += fd.o +DBOOT_OBJS_64 += dboot_elfload.o -PCN_OBJS += mii.o - -DNET_OBJS += dnet.o mii.o -LOGI_OBJS += logi.o -MSCSI_OBJS += mscsi.o -MSMOUSE_OBJS += msm.o -PCPLUSMP_OBJS += apic.o psm_common.o apic_introp.o -RTLS_OBJS += rtls.o -AGPGART_OBJS += agpgart.o \ - agp_kstat.o -AGPTARGET_OBJS += agptarget.o -AMD64GART_OBJS += amd64_gart.o -TZMON_OBJS += tzmon.o +DBOOT_OBJS += \ + dboot_grub.o \ + dboot_startkern.o \ + dboot_printf.o \ + memcpy.o \ + memset.o \ + muldiv.o \ + string.o \ + $(BOOT_DRIVER_OBJS) \ + $(DBOOT_OBJS_$(CLASS)) -GHD_OBJS += ghd.o ghd_debug.o ghd_dma.o ghd_queue.o ghd_scsa.o \ - ghd_scsi.o ghd_timer.o ghd_waitq.o ghd_gcmd.o - -ATA_OBJS += $(GHD_OBJS) ata_blacklist.o ata_common.o ata_disk.o \ - ata_dma.o atapi.o atapi_fsm.o ata_debug.o \ - sil3xxx.o +# +# driver and misc modules +# +GFX_PRIVATE_OBJS += gfx_private.o gfxp_pci.o gfxp_segmap.o \ + gfxp_devmap.o gfxp_vgatext.o gfxp_vm.o vgasubr.o +ISANEXUS_OBJS += isa.o dma_engine.o i8237A.o +PCI_E_MISC_OBJS += pcie_error.o +PCI_E_NEXUS_OBJS += npe.o npe_misc.o +PCI_E_NEXUS_OBJS += pci_common.o pci_kstats.o pci_tools.o +PCINEXUS_OBJS += pci.o pci_common.o pci_kstats.o pci_tools.o +PCPLUSMP_OBJS += apic.o psm_common.o apic_introp.o mp_platform_common.o include $(SRC)/common/mc/mc-amd/Makefile.mcamd MCAMD_OBJS += \ @@ -146,77 +171,25 @@ MCAMD_OBJS += \ mcamd_subr.o \ mcamd_pcicfg.o -# -# PCI-Express driver modules -# -PCI_E_MISC_OBJS += pcie_error.o -PCI_E_NEXUS_OBJS += npe.o npe_misc.o -PCI_E_NEXUS_OBJS += pci_common.o pci_kstats.o pci_tools.o -PCI_E_PCINEXUS_OBJS += pcie_pci.o -PCIEHPCNEXUS_OBJS += pciehpc_x86.o pciehpc_acpi.o pciehpc_nvidia.o - -# -# platform specific modules -# +ROOTNEX_OBJS += rootnex.o +TZMON_OBJS += tzmon.o UPPC_OBJS += uppc.o psm_common.o -PCI_AUTOCONFIG_OBJS += \ - pci_autoconfig.o \ - pci_boot.o \ - pcie_nvidia.o \ - pci_memlist.o \ - pci_resource.o - -ACPICA_OBJS += dbcmds.o dbdisply.o \ - dbexec.o dbfileio.o dbhistry.o dbinput.o dbstats.o \ - dbutils.o dbxface.o evevent.o evgpe.o evgpeblk.o \ - evmisc.o evregion.o evrgnini.o evsci.o evxface.o \ - evxfevnt.o evxfregn.o hwacpi.o hwgpe.o hwregs.o \ - hwsleep.o hwtimer.o dsfield.o dsinit.o dsmethod.o \ - dsmthdat.o dsobject.o dsopcode.o dsutils.o dswexec.o \ - dswload.o dswscope.o dswstate.o exconfig.o exconvrt.o \ - excreate.o exdump.o exfield.o exfldio.o exmisc.o \ - exmutex.o exnames.o exoparg1.o exoparg2.o exoparg3.o \ - exoparg6.o exprep.o exregion.o exresnte.o exresolv.o \ - exresop.o exstore.o exstoren.o exstorob.o exsystem.o \ - exutils.o psargs.o psopcode.o psparse.o psscope.o \ - pstree.o psutils.o pswalk.o psxface.o nsaccess.o \ - nsalloc.o nsdump.o nsdumpdv.o nseval.o nsinit.o \ - nsload.o nsnames.o nsobject.o nsparse.o nssearch.o \ - nsutils.o nswalk.o nsxfeval.o nsxfname.o nsxfobj.o \ - rsaddr.o rscalc.o rscreate.o rsdump.o \ - rsinfo.o rsio.o rsirq.o rslist.o rsmemory.o rsmisc.o \ - rsutils.o rsxface.o tbconvrt.o tbget.o tbgetall.o \ - tbinstal.o tbrsdt.o tbutils.o tbxface.o tbxfroot.o \ - utalloc.o utclib.o utcopy.o utdebug.o utdelete.o \ - uteval.o utglobal.o utinit.o utmath.o utmisc.o \ - utobject.o utresrc.o utxface.o acpica.o acpi_enum.o \ - master_ops.o osl.o osl_ml.o acpica_ec.o utcache.o \ - utmutex.o utstate.o dmbuffer.o dmnames.o dmobject.o \ - dmopcode.o dmresrc.o dmresrcl.o dmresrcs.o dmutils.o \ - dmwalk.o psloop.o uttrack.o - -POWER_OBJS += power.o - -GFX_PRIVATE_OBJS += gfx_private.o gfxp_pci.o gfxp_segmap.o \ - gfxp_devmap.o gfxp_vgatext.o gfxp_vm.o vgasubr.o -AGP_OBJS += agpmaster.o - -# DRM Intel integrated chipsets (i915) codes -I915_OBJS += i915_sundrv.o i915_dma.o i915_drv.o i915_irq.o i915_mem.o +XSVC_OBJS += xsvc.o # # Build up defines and paths. # ALL_DEFS += -Di86pc -INC_PATH += -I$(UTSBASE)/i86pc +INC_PATH += -I$(UTSBASE)/i86pc -I$(SRC)/common # -# Since assym.h is a derived file, the dependency must be explicit for +# Since the assym files are derived, the dependencies must be explicit for # all files including this file. (This is only actually required in the # instance when the .nse_depinfo file does not exist.) It may seem that # the lint targets should also have a similar dependency, but they don't # since only C headers are included when #defined(__lint) is true. # + ASSYM_DEPS += \ copy.o \ desctbls_asm.o \ @@ -233,3 +206,7 @@ ASSYM_DEPS += \ swtch.o \ syscall_asm.o \ syscall_asm_amd64.o + +$(KDI_ASSYM_DEPS:%=$(OBJS_DIR)/%): $(DSF_DIR)/$(OBJS_DIR)/kdi_assym.h + +ASSYM_DEPS += kdi_asm.o diff --git a/usr/src/uts/i86pc/Makefile.i86pc.shared b/usr/src/uts/i86pc/Makefile.i86pc.shared index aae56c8ea4..73ef283182 100644 --- a/usr/src/uts/i86pc/Makefile.i86pc.shared +++ b/usr/src/uts/i86pc/Makefile.i86pc.shared @@ -22,7 +22,7 @@ # # uts/i86pc/Makefile.i86pc # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -37,6 +37,11 @@ PLATFORM = i86pc # +# uname -m value +# +UNAME_M = $(PLATFORM) + +# # Everybody needs to know how to build modstubs.o and to locate unix.o # UNIX_DIR = $(UTSBASE)/$(PLATFORM)/unix @@ -56,6 +61,7 @@ UNIX_O = $(UNIX_DIR)/$(OBJS_DIR)/unix.o MODSTUBS_O = $(MODSTUBS_DIR)/$(OBJS_DIR)/modstubs.o GENLIB = $(GENLIB_DIR)/$(OBJS_DIR)/libgenunix.so LINT_LIB = $(LINT_LIB_DIR)/llib-lunix.ln +DBOOT_LINT_LIB = $(LINT_LIB_DIR)/llib-ldboot.ln GEN_LINT_LIB = $(GEN_LINT_LIB_DIR)/llib-lgenunix.ln # @@ -89,8 +95,10 @@ ALL_BUILDS = $(ALL_BUILDS64) $(ALL_BUILDS32) # # x86 or amd64 inline templates # -INLINES_32 = $(UTSBASE)/intel/ia32/ml/ia32.il -INLINES_64 = $(UTSBASE)/intel/amd64/ml/amd64.il +INLINES_32 = $(UTSBASE)/intel/ia32/ml/ia32.il \ + $(UTSBASE)/$(PLATFORM)/ml/ia32.il +INLINES_64 = $(UTSBASE)/intel/amd64/ml/amd64.il \ + $(UTSBASE)/$(PLATFORM)/ml/amd64.il INLINES += $(INLINES_$(CLASS)) # @@ -135,6 +143,7 @@ OFFSETS_SRC = $(UTSBASE)/$(PLATFORM)/ml/offsets.in PLATFORM_OFFSETS_32 = $(UTSBASE)/$(PLATFORM)/ml/mach_offsets.in PLATFORM_OFFSETS_64 = $(UTSBASE)/intel/amd64/ml/mach_offsets.in PLATFORM_OFFSETS_SRC = $(PLATFORM_OFFSETS_$(CLASS)) +KDI_OFFSETS_SRC = $(UTSBASE)/intel/kdi/kdi_offsets.in # # Define the actual specific platforms @@ -148,14 +157,6 @@ MACHINE_DEFS = -D$(PLATFORM) -D_MACHDEP include $(UTSBASE)/$(PLATFORM)/Makefile.workarounds # -# Simulator flag -# -i386_SIMULATOR = -D_SIMULATOR_SUPPORT -amd64_SIMULATOR = -D_SIMULATOR_SUPPORT - -SIMULATOR = $($(MACH)_SIMULATOR) - -# # Debugging level # # Special knowledge of which special debugging options effect which @@ -167,10 +168,8 @@ SIMULATOR = $($(MACH)_SIMULATOR) # DEBUG_DEFS_OBJ32 = DEBUG_DEFS_DBG32 = -DDEBUG -DEBUG_DEFS_DBG32 += $(SIMULATOR) DEBUG_DEFS_OBJ64 = DEBUG_DEFS_DBG64 = -DDEBUG -DEBUG_DEFS_DBG64 += $(SIMULATOR) DEBUG_DEFS = $(DEBUG_DEFS_$(BUILD_TYPE)) DEBUG_COND_OBJ32 :sh = echo \\043 @@ -184,10 +183,14 @@ $(IF_DEBUG_OBJ)syscall_asm.o := DEBUG_DEFS += -DSYSCALLTRACE -DTRAPTRACE $(IF_DEBUG_OBJ)syscall_asm_amd64.o := DEBUG_DEFS += -DSYSCALLTRACE -DTRAPTRACE $(IF_DEBUG_OBJ)fast_trap_asm.o := DEBUG_DEFS += -DTRAPTRACE $(IF_DEBUG_OBJ)interrupt.o := DEBUG_DEFS += -DTRAPTRACE +$(IF_DEBUG_OBJ)intr.o := DEBUG_DEFS += -DTRAPTRACE $(IF_DEBUG_OBJ)locore.o := DEBUG_DEFS += -DTRAPTRACE $(IF_DEBUG_OBJ)mp_startup.o := DEBUG_DEFS += -DTRAPTRACE $(IF_DEBUG_OBJ)machdep.o := DEBUG_DEFS += -DTRAPTRACE $(IF_DEBUG_OBJ)exception.o := DEBUG_DEFS += -DTRAPTRACE +$(IF_DEBUG_OBJ)x_call.o := DEBUG_DEFS += -DTRAPTRACE +$(IF_DEBUG_OBJ)mp_call.o := DEBUG_DEFS += -DTRAPTRACE +$(IF_DEBUG_OBJ)cbe.o := DEBUG_DEFS += -DTRAPTRACE # # Build `options'. These are historical and the need for these @@ -237,52 +240,18 @@ MACH_NOT_YET_KMODS = $(AUTOCONF_OBJS) # DRV_KMODS_32 are built only 32-bit # DRV_KMODS_64 are built only 64-bit # -# XXX: How many of these are really machine specific? -# DRV_KMODS += rootnex DRV_KMODS += isa +DRV_KMODS += pcplusmp +DRV_KMODS += cpc DRV_KMODS += pci -DRV_KMODS += pci_pci -DRV_KMODS += pcie_pci DRV_KMODS += npe - -DRV_KMODS += ata -DRV_KMODS += fd -DRV_KMODS += fdc -DRV_KMODS += kb8042 DRV_KMODS += pci-ide -DRV_KMODS += audio810 -DRV_KMODS += audiohd -DRV_KMODS += audioixp - -DRV_KMODS_32 += dnet -DRV_KMODS += logi -DRV_KMODS_32 += mscsi -DRV_KMODS_32 += msm -DRV_KMODS += pcplusmp -DRV_KMODS += agpgart -DRV_KMODS += agptarget -DRV_KMODS += amd64_gart -DRV_KMODS += i915 - -DRV_KMODS += cpc +DRV_KMODS += xsvc DRV_KMODS += mc-amd -DRV_KMODS += power DRV_KMODS += tzmon -DRV_KMODS += pcic - -$(CLOSED_BUILD)CLOSED_DRV_KMODS += audiovia823x -$(CLOSED_BUILD)CLOSED_DRV_KMODS += audioens -$(CLOSED_BUILD)CLOSED_DRV_KMODS += bmc -$(CLOSED_BUILD)CLOSED_DRV_KMODS += bscbus -$(CLOSED_BUILD)CLOSED_DRV_KMODS += bscv -$(CLOSED_BUILD)CLOSED_DRV_KMODS += elxl -$(CLOSED_BUILD)CLOSED_DRV_KMODS += iprb + $(CLOSED_BUILD)CLOSED_DRV_KMODS += memtest -$(CLOSED_BUILD)CLOSED_DRV_KMODS_32 += ncrs -$(CLOSED_BUILD)CLOSED_DRV_KMODS += pcn -$(CLOSED_BUILD)CLOSED_DRV_KMODS += rtls -$(CLOSED_BUILD)CLOSED_DRV_KMODS_32 += sbpro # # CPU Modules @@ -308,11 +277,7 @@ FS_KMODS += # # Streams Modules (/kernel/strmod): # -STRMOD_KMODS += vuid2ps2 -STRMOD_KMODS += vuid3ps2 -STRMOD_KMODS += vuidm3p -STRMOD_KMODS += vuidm4p -STRMOD_KMODS += vuidm5p +STRMOD_KMODS += # # 'System' Modules (/kernel/sys): @@ -322,15 +287,14 @@ SYS_KMODS += # # 'Misc' Modules (/kernel/misc): # -MISC_KMODS += pci_autoconfig bootdev acpica pcie pciehpc gfx_private \ - agpmaster drm +MISC_KMODS += gfx_private pcie # -# 'Mach' Modules (/kernel/mach): +# 'Dacf' modules (/kernel/dacf) # -MACH_KMODS += uppc +DACF_KMODS += consconfig_dacf # -# Modules excluded from the product: +# 'Mach' Modules (/kernel/mach): # -$(CLOSED_BUILD)CLOSED_XMODS += spwr +MACH_KMODS += uppc diff --git a/usr/src/uts/i86pc/Makefile.rules b/usr/src/uts/i86pc/Makefile.rules index fc4d4e6dbd..4891b73ee8 100644 --- a/usr/src/uts/i86pc/Makefile.rules +++ b/usr/src/uts/i86pc/Makefile.rules @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -75,10 +75,6 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/pciex/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/pciex/hotplug/pciehpc/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - $(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/pcplusmp/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) @@ -104,6 +100,10 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/os/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) +$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/boot/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + $(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/vm/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) @@ -120,91 +120,85 @@ $(OBJS_DIR)/%.o: $(SRC)/common/dis/i386/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/agpgart/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - $(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/gfx_private/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/agpmaster/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/drm/%.c +$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/xsvc/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/drm/%.s - $(COMPILE.s) -o $@ $< - -# ridiculous contortions --- -ATOMIC_SUBDIR_32 = i386 -ATOMIC_SUBDIR_64 = amd64 -ATOMIC_SUBDIR = $(ATOMIC_SUBDIR_$(CLASS)) - -$(OBJS_DIR)/%.o: $(SRC)/common/atomic/$(ATOMIC_SUBDIR)/%.s - $(COMPILE.s) -o $@ $< - -$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/power/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) +# +# dboot stuff is always 32 bit, linked to run with phys_addr == virt_addr +# +DBOOT_OBJS_DIR = dboot/$(OBJS_DIR) +DBOOT_MACH_32 = -D_BOOT_TARGET_i386 +DBOOT_MACH_64 = -D_BOOT_TARGET_amd64 +DBOOT_DEFS = -D_BOOT $(DBOOT_MACH_$(CLASS)) +DBOOT_DEFS += -D_MACHDEP -D_KMEMUSER -U_KERNEL -D_I32LPx -$(OBJS_DIR)/%.o: $(SRC)/common/mc/mc-amd/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) +DBOOT_CC_INCL = -I$(SRC)/common $(INCLUDE_PATH) +DBOOT_AS_INCL = $(AS_INC_PATH) -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/acpica/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) +DBOOT_AS = $(ONBLD_TOOLS)/bin/$(MACH)/aw -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/acpica/%.s - $(COMPILE.s) -o $@ $< +DBOOT_LINTS_DIR = $(DBOOT_OBJS_DIR) +DBOOT_LINTFLAGS_i86pc = $(LINTFLAGS_i386_32) $(LINTTAGS_i386_32) -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/acpica/debugger/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) +DBOOT_LINTFLAGS = $(DBOOT_LINTFLAGS_$(PLATFORM)) $(C99LMODE) $(CPPFLAGS) \ + $(DBOOT_DEFS) +DBOOT_LOCAL_LINTFLAGS = -c -dirout=$(DBOOT_LINTS_DIR) -I$(SRC)/common \ + $(DBOOT_LINTFLAGS) -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/acpica/events/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) +$(DBOOT_OBJS_DIR)/%.o: $(UTSBASE)/i86pc/boot/%.c + $(i386_CC) $(CERRWARN) -O $(DBOOT_DEFS) $(DBOOT_CC_INCL) -c -o $@ $< -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/acpica/hardware/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) +$(DBOOT_OBJS_DIR)/%.o: $(UTSBASE)/i86pc/dboot/%.c + $(i386_CC) $(CERRWARN) -O $(DBOOT_DEFS) $(DBOOT_CC_INCL) -c -o $@ $< -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/acpica/interpreter/dispatcher/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) +$(DBOOT_OBJS_DIR)/%.o: $(COMMONBASE)/util/%.c + $(i386_CC) $(CERRWARN) -O $(DBOOT_DEFS) $(DBOOT_CC_INCL) -c -o $@ $< -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/acpica/interpreter/executer/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) +$(DBOOT_OBJS_DIR)/%.o: $(COMMONBASE)/util/i386/%.s + $(DBOOT_AS) -P -D_ASM $(DBOOT_DEFS) $(DBOOT_AS_INCL) -o $@ $< -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/acpica/interpreter/parser/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) +$(DBOOT_OBJS_DIR)/%.o: $(UTSBASE)/i86pc/dboot/%.s + $(DBOOT_AS) -P -D_ASM $(DBOOT_DEFS) $(DBOOT_AS_INCL) -o $@ $< -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/acpica/namespace/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) +# +# Stuff to build bios_call.o for the kernel. +# +MAPFILE_BIOS = $(UTSBASE)/i86pc/conf/Mapfile.bios +$(OBJS_DIR)/bios_call.o: $(UTSBASE)/i86pc/ml/bios_call_src.s + $(COMPILE.s) -o $(OBJS_DIR)/bios_call_src.o \ + $(UTSBASE)/i86pc/ml/bios_call_src.s + $(LD) -dn -M $(MAPFILE_BIOS) \ + -o $(OBJS_DIR)/bios_call_src $(OBJS_DIR)/bios_call_src.o + @echo " .data" > $(OBJS_DIR)/bios_call.s + @echo " .globl bios_image" >> $(OBJS_DIR)/bios_call.s + @echo "bios_image:" >> $(OBJS_DIR)/bios_call.s + $(ELFEXTRACT) $(OBJS_DIR)/bios_call_src >> $(OBJS_DIR)/bios_call.s + @echo " .align 4" >> $(OBJS_DIR)/bios_call.s + @echo " .globl bios_size" >> $(OBJS_DIR)/bios_call.s + @echo "bios_size:" >> $(OBJS_DIR)/bios_call.s + @echo " .long . - bios_image" >> $(OBJS_DIR)/bios_call.s + $(COMPILE.s) -o $@ $(OBJS_DIR)/bios_call.s -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/acpica/resources/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) +# ridiculous contortions --- +ATOMIC_SUBDIR_32 = i386 +ATOMIC_SUBDIR_64 = amd64 +ATOMIC_SUBDIR = $(ATOMIC_SUBDIR_$(CLASS)) -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/acpica/tables/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) +$(OBJS_DIR)/%.o: $(SRC)/common/atomic/$(ATOMIC_SUBDIR)/%.s + $(COMPILE.s) -o $@ $< -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/acpica/utilities/%.c +$(OBJS_DIR)/%.o: $(SRC)/common/mc/mc-amd/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/acpica/disassembler/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) +# +# dtrace stubs +# $(OBJS_DIR)/dtracestubs.s: $(UNIX_O) $(LIBS) nm -u $(UNIX_O) $(LIBS) | grep __dtrace_probe_ | sort | uniq | nawk '{ \ @@ -244,9 +238,6 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/pci/%.c $(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/pciex/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/pciex/hotplug/pciehpc/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - $(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/pcplusmp/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) @@ -268,6 +259,9 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/ml/%.s $(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/os/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) +$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/boot/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + $(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/vm/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) @@ -280,63 +274,40 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/common/os/%.c $(LINTS_DIR)/%.ln: $(SRC)/common/dis/i386/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/agpgart/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - $(LINTS_DIR)/%.ln: $(SRC)/common/atomic/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) $(LINTS_DIR)/%.ln: $(SRC)/common/mc/mc-amd/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/acpica/%.s - @($(LHEAD) $(LINT.s) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/acpica/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/acpica/debugger/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/acpica/events/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/acpica/hardware/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/acpica/interpreter/dispatcher/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/acpica/interpreter/executer/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/acpica/interpreter/parser/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/acpica/namespace/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/acpica/resources/%.c +$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/gfx_private/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/acpica/tables/%.c +$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/xsvc/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/acpica/utilities/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) +# +# bios call has a funky name change while building +# +$(LINTS_DIR)/bios_call.ln: $(UTSBASE)/i86pc/ml/bios_call_src.s + @($(LHEAD) $(LINT.s) $(UTSBASE)/i86pc/ml/bios_call_src.s $(LTAIL)) + @mv $(LINTS_DIR)/bios_call_src.ln $(LINTS_DIR)/bios_call.ln -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/acpica/disassembler/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) +# +# dboot always compiles in 32-bit mode, so force lint to be 32-bit mode too. +# +$(DBOOT_LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/dboot/%.c + @($(LHEAD) $(DBOOT_LINT) $(DBOOT_LOCAL_LINTFLAGS) $< $(LTAIL)) -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/gfx_private/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) +$(DBOOT_LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/dboot/%.s + @($(LHEAD) $(DBOOT_LINT) $(DBOOT_LOCAL_LINTFLAGS) $< $(LTAIL)) -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/agpmaster/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) +$(DBOOT_LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/boot/%.c + @($(LHEAD) $(DBOOT_LINT) $(DBOOT_LOCAL_LINTFLAGS) $< $(LTAIL)) -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/drm/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) +$(DBOOT_LINTS_DIR)/%.ln: $(COMMONBASE)/util/%.c + @($(LHEAD) $(DBOOT_LINT) $(DBOOT_LOCAL_LINTFLAGS) $< $(LTAIL)) -$(LINTS_DIR)/%.ln: $(UTSBASE)/i86pc/io/drm/%.s - @($(LHEAD) $(LINT.s) $< $(LTAIL)) +$(DBOOT_LINTS_DIR)/%.ln: $(COMMONBASE)/util/i386/%.s + @($(LHEAD) $(DBOOT_LINT) $(DBOOT_LOCAL_LINTFLAGS) $< $(LTAIL)) diff --git a/usr/src/uts/i86pc/Makefile.workarounds b/usr/src/uts/i86pc/Makefile.workarounds index 54e82c9abf..cdc555b44b 100644 --- a/usr/src/uts/i86pc/Makefile.workarounds +++ b/usr/src/uts/i86pc/Makefile.workarounds @@ -18,7 +18,7 @@ # # CDDL HEADER END # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -87,9 +87,9 @@ WORKAROUND_DEFS += -DOPTERON_ERRATUM_122 # Processors # # Solaris does not currently support PowerNow which is required for this -# Erratum. Disable for now. +# Erratum. Check anyway. # -#WORKAROUND_DEFS += -DOPTERON_ERRATUM_123 +WORKAROUND_DEFS += -DOPTERON_ERRATUM_123 # # Multiprocessor Systems with Four or More Cores May Deadlock Waiting for a diff --git a/usr/src/uts/i86pc/boot/boot_console.c b/usr/src/uts/i86pc/boot/boot_console.c new file mode 100644 index 0000000000..71134377ec --- /dev/null +++ b/usr/src/uts/i86pc/boot/boot_console.c @@ -0,0 +1,556 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/archsystm.h> +#include <sys/boot_console.h> + +#include "boot_serial.h" +#include "boot_vga.h" + +#if defined(_BOOT) +#include "../dboot/dboot_xboot.h" +#include <util/string.h> +#else +#include <sys/bootconf.h> +static char *usbser_buf; +static char *usbser_cur; +#endif + +static int cons_color = CONS_COLOR; +int console = CONS_SCREEN_TEXT; +/* or CONS_TTYA, CONS_TTYB */ +static int serial_ischar(void); +static int serial_getchar(void); +static void serial_putchar(int); +static void serial_adjust_prop(void); + +static char *boot_line = NULL; + +/* Clear the screen and initialize VIDEO, XPOS and YPOS. */ +static void +clear_screen(void) +{ + /* + * XXX should set vga mode so we don't depend on the + * state left by the boot loader + */ + vga_clear(cons_color); + vga_setpos(0, 0); +} + +/* Put the character C on the screen. */ +static void +screen_putchar(int c) +{ + int row, col; + + vga_getpos(&row, &col); + switch (c) { + case '\t': + col += 8 - (col % 8); + if (col == VGA_TEXT_COLS) + col = 79; + vga_setpos(row, col); + break; + + case '\r': + vga_setpos(row, 0); + break; + + case '\b': + if (col > 0) + vga_setpos(row, col - 1); + break; + + case '\n': + if (row < VGA_TEXT_ROWS - 1) + vga_setpos(row + 1, col); + else + vga_scroll(cons_color); + break; + + default: + vga_drawc(c, cons_color); + if (col < VGA_TEXT_COLS -1) + vga_setpos(row, col + 1); + else if (row < VGA_TEXT_ROWS - 1) + vga_setpos(row + 1, 0); + else { + vga_setpos(row, 0); + vga_scroll(cons_color); + } + break; + } +} + +/* serial port stuff */ +static int port; + +static void +serial_init(void) +{ + switch (console) { + case CONS_TTYA: + port = 0x3f8; + break; + case CONS_TTYB: + port = 0x2f8; + break; + } + + outb(port + ISR, 0x20); + if (inb(port + ISR) & 0x20) { + /* + * 82510 chip is present + */ + outb(port + DAT+7, 0x04); /* clear status */ + outb(port + ISR, 0x40); /* set to bank 2 */ + outb(port + MCR, 0x08); /* IMD */ + outb(port + DAT, 0x21); /* FMD */ + outb(port + ISR, 0x00); /* set to bank 0 */ + } else { + /* + * set the UART in FIFO mode if it has FIFO buffers. + * use 16550 fifo reset sequence specified in NS + * application note. disable fifos until chip is + * initialized. + */ + outb(port + FIFOR, 0x00); /* clear */ + outb(port + FIFOR, FIFO_ON); /* enable */ + outb(port + FIFOR, FIFO_ON|FIFORXFLSH); /* reset */ + outb(port + FIFOR, + FIFO_ON|FIFODMA|FIFOTXFLSH|FIFORXFLSH|0x80); + if ((inb(port + ISR) & 0xc0) != 0xc0) { + /* + * no fifo buffers so disable fifos. + * this is true for 8250's + */ + outb(port + FIFOR, 0x00); + } + } + + /* disable interrupts */ + outb(port + ICR, 0); + + /* adjust setting based on tty properties */ + serial_adjust_prop(); + +#if defined(_BOOT) + /* + * Do a full reset to match console behavior. + * 0x1B + c - reset everything + */ + serial_putchar(0x1B); + serial_putchar('c'); +#endif +} + + +#define MATCHES(p, pat) \ + (strncmp(p, pat, strlen(pat)) == 0 ? (p += strlen(pat), 1) : 0) + +#define SKIP(p, c) \ + while (*(p) != 0 && *p != (c)) \ + ++(p); \ + if (*(p) == (c)) \ + ++(p); + +/* + * find a tty mode property either from cmdline or from boot properties + */ +static char * +get_mode_value(char *name) +{ + char *p; + + /* + * when specified on boot line it looks like "name" "=".... + */ + if (boot_line != NULL) { + p = strstr(boot_line, name); + if (p == NULL) + return (NULL); + SKIP(p, '='); + return (p); + } + +#if defined(_BOOT) + return (NULL); +#else + /* + * if we're running in the full kernel we check the bootenv.rc settings + */ + { + static char propval[20]; + + propval[0] = 0; + if (bootops == NULL || BOP_GETPROPLEN(bootops, name) == 0) + return (NULL); + (void) BOP_GETPROP(bootops, name, propval); + return (propval); + } +#endif +} + +/* + * adjust serial port based on properties + * These come either from the cmdline or from boot properties. + */ +static void +serial_adjust_prop(void) +{ + char propname[20]; + char *propval; + char *p; + ulong_t baud; + uchar_t lcr = 0; + uchar_t mcr = DTR | RTS; + + (void) strcpy(propname, "ttyX-mode"); + propname[3] = 'a' + console - CONS_TTYA; + propval = get_mode_value(propname); + if (propval == NULL) + propval = "9600,8,n,1,-"; + + /* property is of the form: "9600,8,n,1,-" */ + p = propval; + if (MATCHES(p, "110,")) + baud = ASY110; + else if (MATCHES(p, "150,")) + baud = ASY150; + else if (MATCHES(p, "300,")) + baud = ASY300; + else if (MATCHES(p, "600,")) + baud = ASY600; + else if (MATCHES(p, "1200,")) + baud = ASY1200; + else if (MATCHES(p, "2400,")) + baud = ASY2400; + else if (MATCHES(p, "4800,")) + baud = ASY4800; + else if (MATCHES(p, "19200,")) + baud = ASY19200; + else if (MATCHES(p, "38400,")) + baud = ASY38400; + else if (MATCHES(p, "57600,")) + baud = ASY57600; + else if (MATCHES(p, "115200,")) + baud = ASY115200; + else { + baud = ASY9600; + SKIP(p, ','); + } + outb(port + LCR, DLAB); + outb(port + DAT + DLL, baud & 0xff); + outb(port + DAT + DLH, (baud >> 8) & 0xff); + + switch (*p) { + case '5': + lcr |= BITS5; + ++p; + break; + case '6': + lcr |= BITS6; + ++p; + break; + case '7': + lcr |= BITS7; + ++p; + break; + case '8': + ++p; + default: + lcr |= BITS8; + break; + } + + SKIP(p, ','); + + switch (*p) { + case 'n': + lcr |= PARITY_NONE; + ++p; + break; + case 'o': + lcr |= PARITY_ODD; + ++p; + break; + case 'e': + ++p; + default: + lcr |= PARITY_EVEN; + break; + } + + + SKIP(p, ','); + + switch (*p) { + case '1': + /* STOP1 is 0 */ + ++p; + break; + default: + lcr |= STOP2; + break; + } + /* set parity bits */ + outb(port + LCR, lcr); + + (void) strcpy(propname, "ttyX-rts-dtr-off"); + propname[3] = 'a' + console - CONS_TTYA; + propval = get_mode_value(propname); + if (propval == NULL) + propval = "false"; + if (propval[0] != 'f' && propval[0] != 'F') + mcr = 0; + /* set modem control bits */ + outb(port + MCR, mcr | OUT2); +} + +void +bcons_init(char *bootstr) +{ + boot_line = bootstr; + console = CONS_INVALID; + + if (strstr(bootstr, "console=ttya") != 0) + console = CONS_TTYA; + else if (strstr(bootstr, "console=ttyb") != 0) + console = CONS_TTYB; + else if (strstr(bootstr, "console=text") != 0) + console = CONS_SCREEN_TEXT; + + /* + * If no console device specified, default to text. + * Remember what was specified for second phase. + */ + if (console == CONS_INVALID) + console = CONS_SCREEN_TEXT; + + switch (console) { + case CONS_TTYA: + case CONS_TTYB: + serial_init(); + break; + + case CONS_SCREEN_TEXT: + default: +#if defined(_BOOT) + clear_screen(); /* clears the grub screen */ +#endif + kb_init(); + break; + } + boot_line = NULL; +} + +/* + * 2nd part of console initialization. + * In the kernel (ie. fakebop), this can be used only to switch to + * using a serial port instead of screen based on the contents + * of the bootenv.rc file. + */ +/*ARGSUSED*/ +void +bcons_init2(char *inputdev, char *outputdev, char *consoledev) +{ +#if !defined(_BOOT) + int cons = CONS_INVALID; + + if (consoledev) { + if (strstr(consoledev, "ttya") != 0) + cons = CONS_TTYA; + else if (strstr(consoledev, "ttyb") != 0) + cons = CONS_TTYB; + else if (strstr(consoledev, "usb-serial") != 0) + cons = CONS_USBSER; + } + + if (cons == CONS_INVALID && inputdev) { + if (strstr(inputdev, "ttya") != 0) + cons = CONS_TTYA; + else if (strstr(inputdev, "ttyb") != 0) + cons = CONS_TTYB; + else if (strstr(inputdev, "usb-serial") != 0) + cons = CONS_USBSER; + } + + if (cons == CONS_INVALID && outputdev) { + if (strstr(outputdev, "ttya") != 0) + cons = CONS_TTYA; + else if (strstr(outputdev, "ttyb") != 0) + cons = CONS_TTYB; + else if (strstr(outputdev, "usb-serial") != 0) + cons = CONS_USBSER; + } + + if (cons == CONS_INVALID) + return; + if (cons == console) + return; + + console = cons; + if (cons == CONS_TTYA || cons == CONS_TTYB) { + serial_init(); + return; + } + + /* + * USB serial -- we just collect data into a buffer + */ + if (cons == CONS_USBSER) { + extern void *usbser_init(size_t); + usbser_buf = usbser_cur = usbser_init(MMU_PAGESIZE); + } +#endif /* _BOOT */ +} + +#if !defined(_BOOT) +static void +usbser_putchar(int c) +{ + if (usbser_cur - usbser_buf < MMU_PAGESIZE) + *usbser_cur++ = c; +} +#endif /* _BOOT */ + +static void +serial_putchar(int c) +{ + int checks = 10000; + + while (((inb(port + LSR) & XHRE) == 0) && checks--) + ; + outb(port + DAT, (char)c); +} + +static int +serial_getchar(void) +{ + uchar_t lsr; + + while (serial_ischar() == 0) + ; + + lsr = inb(port + LSR); + if (lsr & (SERIAL_BREAK | SERIAL_FRAME | + SERIAL_PARITY | SERIAL_OVERRUN)) { + if (lsr & SERIAL_OVERRUN) { + return (inb(port + DAT)); + } else { + /* Toss the garbage */ + (void) inb(port + DAT); + return (0); + } + } + return (inb(port + DAT)); +} + +static int +serial_ischar(void) +{ + return (inb(port + LSR) & RCA); +} + +static void +_doputchar(int c) +{ + switch (console) { + case CONS_TTYA: + case CONS_TTYB: + serial_putchar(c); + return; + case CONS_SCREEN_TEXT: + screen_putchar(c); + return; +#if !defined(_BOOT) + case CONS_USBSER: + usbser_putchar(c); + return; +#endif /* _BOOT */ + } +} + +void +bcons_putchar(int c) +{ + static int bhcharpos = 0; + + if (c == '\t') { + do { + _doputchar(' '); + } while (++bhcharpos % 8); + return; + } else if (c == '\n' || c == '\r') { + bhcharpos = 0; + _doputchar('\r'); + _doputchar(c); + return; + } else if (c == '\b') { + if (bhcharpos) + bhcharpos--; + _doputchar(c); + return; + } + + bhcharpos++; + _doputchar(c); +} + +/* + * kernel character input functions + */ +int +bcons_getchar(void) +{ + switch (console) { + case CONS_TTYA: + case CONS_TTYB: + return (serial_getchar()); + default: + return (kb_getchar()); + } +} + +#if !defined(_BOOT) + +int +bcons_ischar(void) +{ + switch (console) { + case CONS_TTYA: + case CONS_TTYB: + return (serial_ischar()); + default: + return (kb_ischar()); + } +} + +#endif /* _BOOT */ diff --git a/usr/src/uts/i86pc/boot/boot_gdt.s b/usr/src/uts/i86pc/boot/boot_gdt.s new file mode 100644 index 0000000000..99875989ee --- /dev/null +++ b/usr/src/uts/i86pc/boot/boot_gdt.s @@ -0,0 +1,108 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(__lint) + +int global_descriptor_table[0x10]; + +#else /* __lint */ + + .align 16 + + /* + * This must remain in sync with the entries in intel/sys/gdt.h; in + * particular kmdb uses B64CODE_SEL or B32CODE_SEL in perpetuity for + * its IDT entries (they're copied to the kernel's GDT in init_idt()). + */ + +global_descriptor_table: + .long 0 + .long 0 + + /* GDT_B32DATA: 32 bit flat data descriptor */ + .value 0xFFFF /* segment limit 0..15 */ + .value 0x0000 /* segment base 0..15 */ + .byte 0x0 /* segment base 16..23 */ + .byte 0x92 /* P = 1, read/write data */ + .byte 0xCF /* G=1, B=1, Limit (16..19)=1111 */ + .byte 0x0 /* segment base 24..32 */ + + /* GDT_B32CODE 32 bit flat code descriptor */ + .value 0xFFFF /* segment limit 0..15 */ + .value 0x0000 /* segment base 0..15 */ + .byte 0x0 /* segment base 16..23 */ + .byte 0x9E /* P=1, code, exec, readable */ + .byte 0xCF /* G=1, D=1, Limit (16..19)=1111 */ + .byte 0x0 /* segment base 24..32 */ + + /* + * GDT_B16CODE 16 bit code descriptor for doing BIOS calls + */ + .value 0xFFFF /* segment limit 0..15 */ + .value 0x0000 /* segment base 0..15 */ + .byte 0x0 /* segment base 16..23 */ + .byte 0x9E /* P=1, code, exec, readable */ + .byte 0x0F /* G=0, D=0, Limit (16..19)=1111 */ + .byte 0x0 /* segment base 24..32 */ + + /* + * GDT_B16DATA 16 bit data descriptor for doing BIOS calls + */ + .value 0xFFFF /* segment limit 0..15 */ + .value 0x0000 /* segment base 0..15 */ + .byte 0x0 /* segment base 16..23 */ + .byte 0x92 /* P = 1, read/write data */ + .byte 0x4F /* G=0, D=1, Limit (16..19)=1111 */ + .byte 0x0 /* segment base 24..32 */ + + /* GDT_B64CODE: 64 bit flat code descriptor - only L bit has meaning */ + .value 0xFFFF /* segment limit 0..15 */ + .value 0x0000 /* segment base 0..15 */ + .byte 0x0 /* segment base 16..23 */ + .byte 0x9E /* P=1, code, exec, readable */ + .byte 0xAF /* G=1, D=0, L=1, Limit (16..19)=1111 */ + .byte 0x0 /* segment base 24..32 */ + + /* + * unused + */ + .long 0 + .long 0 + + /* + * GDT_BGSTMP -- an entry for kmdb to use during boot + */ + .long 0 + .long 0 + +gdt_info: + .value gdt_info - global_descriptor_table - 1 + .long global_descriptor_table + .long 0 /* needed for 64 bit */ + +#endif /* __lint */ diff --git a/usr/src/psm/stand/boot/i386/common/keyboard.c b/usr/src/uts/i86pc/boot/boot_keyboard.c index dc3f09d68c..7f362b648f 100644 --- a/usr/src/psm/stand/boot/i386/common/keyboard.c +++ b/usr/src/uts/i86pc/boot/boot_keyboard.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,11 +32,13 @@ */ #include <sys/types.h> -#include "chario.h" -#include "keyboard_table.h" -#include "console.h" -#include "util.h" -#include "debug.h" +#include <sys/archsystm.h> +#include <sys/boot_console.h> +#include "boot_keyboard_table.h" + +#if defined(_BOOT) +#include "dboot/dboot_xboot.h" +#endif /* * Definitions for BIOS keyboard state. We use BIOS's variable to store @@ -98,8 +100,6 @@ #define peek8(p) (*(p)) #define poke8(p, val) (*(p) = (val)) -#define peeks(p) (*(p)) -#define pokes(p, val) (*(p) = (val)) static struct { boolean_t initialized; @@ -123,8 +123,6 @@ static struct { -1, /* pending */ }; -#define kb_debug (debug & D_KEYBOARD) - static int kb_translate(unsigned char code); static void kb_send(unsigned char cmd); static void kb_update_leds(void); @@ -135,9 +133,6 @@ kb_getchar(void) { int ret; - if (kb_debug) - printf(" getchar()"); - while (!kb_ischar()) /* LOOP */; @@ -155,9 +150,6 @@ kb_getchar(void) kb.pending = -1; } - if (kb_debug) - printf("=0x%x ", ret); - return (ret); } @@ -167,16 +159,12 @@ kb_ischar(void) unsigned char buffer_stat; unsigned char code; unsigned char leds; - static int cnt = 0; if (!kb.initialized) { kb_init(); kb.initialized = B_TRUE; } - if (kb_debug) - printf("%c\b", "/-\\|"[cnt++ % 4]); - if (kb.pending >= 0) return (1); @@ -200,9 +188,6 @@ kb_ischar(void) code = inb(I8042_DATA); - if (kb_debug) - printf("0x%x->", code); - switch (code) { /* * case 0xAA: @@ -219,8 +204,6 @@ kb_ischar(void) * in this mini-driver. */ case 0xFA: - if (kb_debug) - printf("ack "); switch (kb.led_state) { case KB_LED_IDLE: @@ -253,80 +236,53 @@ kb_ischar(void) * We don't care, and the codes are carefully arranged * so that we don't have to. */ - if (kb_debug) - printf("ignored "); continue; default: if (code & 0x80) { - if (kb_debug) - printf("release->"); /* Release */ code &= 0x7f; switch (keyboard_translate[code].normal) { case KBTYPE_SPEC_LSHIFT: poke8(kb_flag, peek8(kb_flag) & ~BIOS_LEFT_SHIFT); - if (kb_debug) - printf("lshift "); break; case KBTYPE_SPEC_RSHIFT: poke8(kb_flag, peek8(kb_flag) & ~BIOS_RIGHT_SHIFT); - if (kb_debug) - printf("rshift "); break; case KBTYPE_SPEC_CTRL: poke8(kb_flag, peek8(kb_flag) & ~BIOS_CTL_SHIFT); - if (kb_debug) - printf("ctrl "); break; case KBTYPE_SPEC_ALT: poke8(kb_flag, peek8(kb_flag) & ~BIOS_ALT_SHIFT); - if (kb_debug) - printf("alt "); break; case KBTYPE_SPEC_CAPS_LOCK: poke8(kb_flag_1, peek8(kb_flag_1) & ~BIOS_CAPS_SHIFT); - if (kb_debug) - printf("caps "); break; case KBTYPE_SPEC_NUM_LOCK: poke8(kb_flag_1, peek8(kb_flag_1) & ~BIOS_NUM_SHIFT); - if (kb_debug) - printf("num "); break; case KBTYPE_SPEC_SCROLL_LOCK: poke8(kb_flag_1, peek8(kb_flag_1) & ~BIOS_SCROLL_SHIFT); - if (kb_debug) - printf("scroll "); break; default: /* * Ignore all other releases. */ - if (kb_debug) - printf("ignored "); break; } } else { /* Press */ - if (kb_debug) - printf("press->"); kb.pending = kb_translate(code); if (kb.pending >= 0) { - if (kb_debug) - printf("0x%x ", kb.pending); return (1); - } else { - if (kb_debug) - printf("ignored "); } } } @@ -430,11 +386,13 @@ kb_translate(unsigned char code) break; case KBTYPE_SPEC_MAYBE_REBOOT: +#if 0 /* Solaris doesn't reboot via ctrl-alt-del */ if ((peek8(kb_flag) & (BIOS_CTL_SHIFT|BIOS_ALT_SHIFT)) == (BIOS_CTL_SHIFT|BIOS_ALT_SHIFT)) { reset(); /* NOTREACHED */ } +#endif break; default: @@ -560,5 +518,5 @@ kb_calculate_leds(void) if (peek8(kb_flag) & BIOS_SCROLL_STATE) res |= KB_LED_SCROLL_LOCK; - return (res); + return ((char)res); } diff --git a/usr/src/uts/i86pc/boot/boot_keyboard.h b/usr/src/uts/i86pc/boot/boot_keyboard.h new file mode 100644 index 0000000000..390bb1f4fe --- /dev/null +++ b/usr/src/uts/i86pc/boot/boot_keyboard.h @@ -0,0 +1,46 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _BOOT_KEYBOARD_H +#define _BOOT_KEYBOARD_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Interfaces to the simple keyboard driver. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +int kb_ischar(void); +char kb_getchar(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _BOOT_KEYBOARD_H */ diff --git a/usr/src/psm/stand/boot/i386/common/keyboard_table.c b/usr/src/uts/i86pc/boot/boot_keyboard_table.c index 64d57720df..6c352001f7 100644 --- a/usr/src/psm/stand/boot/i386/common/keyboard_table.c +++ b/usr/src/uts/i86pc/boot/boot_keyboard_table.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,17 +19,17 @@ * CDDL HEADER END */ /* - * Copyright (c) 1999 by Sun Microsystems, Inc. - * All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /* - * Keyboard table for bootstrap's miniature keyboard driver. + * Keyboard table for bootstrap's simple keyboard driver. */ -#include "keyboard_table.h" +#include "boot_keyboard_table.h" #define A | KBTYPE_ALPHA #define C & 0x1f diff --git a/usr/src/psm/stand/boot/i386/common/keyboard_table.h b/usr/src/uts/i86pc/boot/boot_keyboard_table.h index 2b72bdc0a3..4720d688a7 100644 --- a/usr/src/psm/stand/boot/i386/common/keyboard_table.h +++ b/usr/src/uts/i86pc/boot/boot_keyboard_table.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,17 +19,17 @@ * CDDL HEADER END */ /* - * Copyright (c) 1999 by Sun Microsystems, Inc. - * All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ -#ifndef _KEYBOARD_TABLE_H -#define _KEYBOARD_TABLE_H +#ifndef _BOOT_KEYBOARD_TABLE_H +#define _BOOT_KEYBOARD_TABLE_H #pragma ident "%Z%%M% %I% %E% SMI" /* - * Structure of the keyboard table for the bootstrap miniature + * Structure of the keyboard table for the bootstrap simple * keyboard driver. */ @@ -48,16 +47,16 @@ extern "C" { #define KBTYPE_FUNC 0x300 /* Extended Function. Send this code, */ /* prefixed with zero. */ #define KBTYPE_SPEC 0x400 /* One-of-a-kind codes. Self-explanatory. */ -#define KBTYPE_SPEC_NOP (KBTYPE_SPEC | 0x00) -#define KBTYPE_SPEC_UNDEF (KBTYPE_SPEC | 0x01) -#define KBTYPE_SPEC_LSHIFT (KBTYPE_SPEC | 0x02) -#define KBTYPE_SPEC_RSHIFT (KBTYPE_SPEC | 0x03) -#define KBTYPE_SPEC_CTRL (KBTYPE_SPEC | 0x04) -#define KBTYPE_SPEC_ALT (KBTYPE_SPEC | 0x05) -#define KBTYPE_SPEC_CAPS_LOCK (KBTYPE_SPEC | 0x06) -#define KBTYPE_SPEC_NUM_LOCK (KBTYPE_SPEC | 0x07) -#define KBTYPE_SPEC_SCROLL_LOCK (KBTYPE_SPEC | 0x08) -#define KBTYPE_SPEC_MAYBE_REBOOT (KBTYPE_SPEC | 0x09) +#define KBTYPE_SPEC_NOP (KBTYPE_SPEC | 0x00) +#define KBTYPE_SPEC_UNDEF (KBTYPE_SPEC | 0x01) +#define KBTYPE_SPEC_LSHIFT (KBTYPE_SPEC | 0x02) +#define KBTYPE_SPEC_RSHIFT (KBTYPE_SPEC | 0x03) +#define KBTYPE_SPEC_CTRL (KBTYPE_SPEC | 0x04) +#define KBTYPE_SPEC_ALT (KBTYPE_SPEC | 0x05) +#define KBTYPE_SPEC_CAPS_LOCK (KBTYPE_SPEC | 0x06) +#define KBTYPE_SPEC_NUM_LOCK (KBTYPE_SPEC | 0x07) +#define KBTYPE_SPEC_SCROLL_LOCK (KBTYPE_SPEC | 0x08) +#define KBTYPE_SPEC_MAYBE_REBOOT (KBTYPE_SPEC | 0x09) struct keyboard_translate { unsigned short normal; @@ -72,4 +71,4 @@ extern struct keyboard_translate keyboard_translate[128]; } #endif -#endif /* _KEYBOARD_TABLE_H */ +#endif /* _BOOT_KEYBOARD_TABLE_H */ diff --git a/usr/src/uts/i86pc/boot/boot_mmu.c b/usr/src/uts/i86pc/boot/boot_mmu.c new file mode 100644 index 0000000000..6c7622f4e1 --- /dev/null +++ b/usr/src/uts/i86pc/boot/boot_mmu.c @@ -0,0 +1,121 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * WARNING: This file is used by both dboot and the kernel. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/param.h> +#include <sys/machparam.h> +#include <sys/mach_mmu.h> + +#ifdef _BOOT +#include <dboot/dboot_printf.h> +#define bop_panic dboot_panic +#else +#include <sys/bootconf.h> +#endif + +uint_t shift_amt_nopae[] = {12, 22}; +uint_t shift_amt_pae[] = {12, 21, 30, 39}; +uint_t *shift_amt; +uint_t ptes_per_table; +uint_t pte_size; +uint32_t lpagesize; +paddr_t top_page_table; +uint_t top_level; + +/* + * Return the index corresponding to a virt address at a given page table level. + */ +static uint_t +vatoindex(uint64_t va, uint_t level) +{ + return ((va >> shift_amt[level]) & (ptes_per_table - 1)); +} + +/* + * Return a pointer to the page table entry that maps a virtual address. + * If there is no page table and probe_only is not set, one is created. + */ +x86pte_t * +find_pte(uint64_t va, paddr_t *pa, uint_t level, uint_t probe_only) +{ + uint_t l; + uint_t index; + paddr_t table; + + if (pa) + *pa = 0; + +#ifndef _BOOT + if (IN_HYPERVISOR_VA(va)) + return (NULL); +#endif + + /* + * Walk down the page tables creating any needed intermediate tables. + */ + table = top_page_table; + for (l = top_level; l != level; --l) { + uint64_t pteval; + paddr_t new_table; + + index = vatoindex(va, l); + pteval = get_pteval(table, index); + + /* + * Life is easy if we find the pagetable. We just use it. + */ + if (pteval & PT_VALID) { + table = ma_to_pa(pteval & MMU_PAGEMASK); + if (table == -1) { + if (probe_only) + return (NULL); + bop_panic("find_pte(): phys not found!"); + } + continue; + } + + if (probe_only) + return (NULL); + + new_table = make_ptable(&pteval, l); + set_pteval(table, index, l, pteval); + + table = new_table; + } + + /* + * Return a pointer into the current pagetable. + */ + index = vatoindex(va, l); + if (pa) + *pa = table + index * pte_size; + return (map_pte(table, index)); +} diff --git a/usr/src/uts/i86pc/boot/boot_serial.h b/usr/src/uts/i86pc/boot/boot_serial.h new file mode 100644 index 0000000000..dd031f4f9a --- /dev/null +++ b/usr/src/uts/i86pc/boot/boot_serial.h @@ -0,0 +1,148 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _BOOT_SERIAL_H +#define _BOOT_SERIAL_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---- ports on 16550 serial chips ---- */ +#define DAT 0 /* ... data */ +#define ICR 1 /* ... intr control reg */ +#define ISR 2 /* ... intr status reg */ +#define LCR 3 /* ... line control reg */ +#define MCR 4 /* ... modem control reg */ +#define LSR 5 /* ... line status reg */ +#define MSR 6 /* ... modem status reg */ +#define DLL 0 /* ... data latch low (used for baud rate) */ +#define DLH 1 /* ... data latch high (ditto) */ +#define FIFOR ISR /* ... fifo write reg */ + +/* ---- LSR bits ---- */ +#define RCA 0x01 /* ... receive char avail */ +#define XHRE 0x20 /* ... xmit hold buffer empty */ + +/* ---- Modem bits ---- */ +#define DTR 0x01 +#define RTS 0x02 +#define OUT2 0x08 + +#define FIFO_ON 0x01 +#define FIFO_OFF 0x00 +#define FIFORXFLSH 0x02 +#define FIFOTXFLSH 0x04 +#define FIFODMA 0x08 + +/* ---- LCR bits ---- */ +#define STOP1 00 +#define STOP2 0x04 +#define BITS5 0x00 /* 5 bits per char */ +#define BITS6 0x01 /* 6 bits per char */ +#define BITS7 0x02 /* 7 bits per char */ +#define BITS8 0x03 /* 8 bits per char */ + +/* baud rate definitions */ +#define DLAB 0x80 /* divisor latch access bit */ +#define ASY110 1047 /* 110 baud rate for serial console */ +#define ASY150 768 /* 150 baud rate for serial console */ +#define ASY300 384 /* 300 baud rate for serial console */ +#define ASY600 192 /* 600 baud rate for serial console */ +#define ASY1200 96 /* 1200 baud rate for serial console */ +#define ASY2400 48 /* 2400 baud rate for serial console */ +#define ASY4800 24 /* 4800 baud rate for serial console */ +#define ASY9600 12 /* 9600 baud rate for serial console */ +#define ASY19200 6 /* 19200 baud rate for serial console */ +#define ASY38400 3 /* 38400 baud rate for serial console */ +#define ASY57600 2 /* 57600 baud rate for serial console */ +#define ASY115200 1 /* 115200 baud rate for serial console */ + + +/* + * Defines for the serial port + */ + +#define SERIAL_FIFO_FLUSH 16 /* maximum number of chars to flush */ + +/* ---- Bit 11 defines direct serial port ---- */ +#define SDIRECT 0x1000 + +/* ---- Bits 9-10 define flow control ---- */ +#define SSOFT 0x800 +#define SHARD 0x400 + +/* ---- Bits 5-8 define baud rate ---- */ +#define S110 0x00 +#define S150 0x20 +#define S300 0x40 +#define S600 0x60 +#define S1200 0x80 +#define S2400 0xa0 +#define S4800 0xc0 +#define S9600 0xe0 +#define S19200 0x100 +#define S38400 0x120 +#define S57600 0x140 +#define S76800 0x160 +#define S115200 0x180 +#define S153600 0x1a0 +#define S230400 0x1c0 +#define S307200 0x1e0 +#define S460800 0x200 + +/* ---- Bits 3 & 4 are parity ---- */ +#define PARITY_NONE 0x10 +#define PARITY_ODD 0x08 +#define PARITY_EVEN 0x18 + +/* ---- Bit 2 is stop bit ---- */ +#define STOP_1 0x00 +#define STOP_2 0x04 + +/* ---- Bits 0 & 1 are data bits ---- */ +#define DATA_8 0x03 +#define DATA_7 0x02 +#define DATA_6 0x01 +#define DATA_5 0x00 + +/* ---- Line Status ---- */ +#define SERIAL_TIMEOUT 0x80 +#define SERIAL_XMITSHFT 0x40 +#define SERIAL_XMITHOLD 0x20 +#define SERIAL_BREAK 0x10 +#define SERIAL_FRAME 0x08 +#define SERIAL_PARITY 0x04 +#define SERIAL_OVERRUN 0x02 +#define SERIAL_DATA 0x01 + + +#ifdef __cplusplus +} +#endif + +#endif /* _BOOT_SERIAL_H */ diff --git a/usr/src/psm/stand/boot/i386/common/vga.c b/usr/src/uts/i86pc/boot/boot_vga.c index d534894cc3..7de0682776 100644 --- a/usr/src/psm/stand/boot/i386/common/vga.c +++ b/usr/src/uts/i86pc/boot/boot_vga.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,8 +32,12 @@ #include <sys/archsystm.h> #include <sys/vgareg.h> -#include "util.h" -#include "vga.h" + +#include "boot_vga.h" + +#if defined(_BOOT) +#include "../dboot/dboot_xboot.h" +#endif #define VGA_COLOR_CRTC_INDEX 0x3d4 #define VGA_COLOR_CRTC_DATA 0x3d5 diff --git a/usr/src/psm/stand/boot/i386/common/vga.h b/usr/src/uts/i86pc/boot/boot_vga.h index ec7fd2c371..87f818fc41 100644 --- a/usr/src/psm/stand/boot/i386/common/vga.h +++ b/usr/src/uts/i86pc/boot/boot_vga.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,12 +19,12 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#ifndef _VGA_H -#define _VGA_H +#ifndef _BOOT_VGA_H +#define _BOOT_VGA_H #pragma ident "%Z%%M% %I% %E% SMI" @@ -54,4 +53,4 @@ extern void vga_drawc(int, int); } #endif -#endif /* _VGA_H */ +#endif /* _BOOT_VGA_H */ diff --git a/usr/src/uts/i86pc/conf/Mapfile b/usr/src/uts/i86pc/conf/Mapfile index 73b304e07c..b822134be1 100644 --- a/usr/src/uts/i86pc/conf/Mapfile +++ b/usr/src/uts/i86pc/conf/Mapfile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -19,21 +18,28 @@ # # CDDL HEADER END # -# Copyright 2000 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" -text = LOAD ?RXN V0xFE800000; +# +# this is the 32 bit 1:1 mapped code to which grub jumps. +# +dboot = LOAD ?RWXN P0xC00000 V0xC00000; +dboot : $PROGBITS ?AW : *dboot.o; + +# +# this is the kernel text +# +text = LOAD ?RXN P0x400000 V0xFE800000; text | .text; text : $PROGBITS ?A!W; # # start the data segment on a new 4MB page boundary -# Not all x86 machines support 4MB pages so startup() -# has to deal with that edge case. # -data = LOAD ?RWX V0xFEc00000 A0x1000; +data = LOAD ?RWX P0x800000 V0xFEc00000; data | .data; data : $PROGBITS ?AW; data : $NOBITS ?AW; diff --git a/usr/src/uts/i86pc/conf/Mapfile.amd64 b/usr/src/uts/i86pc/conf/Mapfile.amd64 index 6afe016b73..fca1e493c3 100644 --- a/usr/src/uts/i86pc/conf/Mapfile.amd64 +++ b/usr/src/uts/i86pc/conf/Mapfile.amd64 @@ -1,13 +1,12 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -27,16 +26,20 @@ #pragma ident "%Z%%M% %I% %E% SMI" # -text = LOAD ?RXN V0xFFFFFFFFFB800000; +# +# this is the 32 bit 1:1 mapped code to which grub jumps. +# +dboot = LOAD ?RWXN P0xC00000 V0xC00000; +dboot : $PROGBITS ?AW : *dboot.o; + +text = LOAD ?RXN P0x400000 V0xFFFFFFFFFB800000; text | .text; text : $PROGBITS ?A!W; # -# start the data segment on a new 4MB page boundary -# Not all x86 machines support 4MB pages so startup() -# has to deal with that edge case. +# kernel data # -data = LOAD ?RWX V0xFFFFFFFFFBc00000 A0x1000; +data = LOAD ?RWX P0x800000 V0xFFFFFFFFFBc00000; data | .data; data : $PROGBITS ?AW; data : $NOBITS ?AW; diff --git a/usr/src/psm/stand/boot/i386/common/mapfile b/usr/src/uts/i86pc/conf/Mapfile.bios index 85a3c88c5d..18aa3ef9fc 100644 --- a/usr/src/psm/stand/boot/i386/common/mapfile +++ b/usr/src/uts/i86pc/conf/Mapfile.bios @@ -1,13 +1,9 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,7 +18,13 @@ # # CDDL HEADER END # -#ident "%Z%%M% %I% %E% SMI" -multiboot = LOAD ?RWX V0x1000000 P0x1000000 A0x1000; -multiboot : ?A; +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +#pragma ident "%Z%%M% %I% %E% SMI" + +bios = LOAD ?NRWX V0x5000 P0x5000 A0x1000; +bios : ?A; diff --git a/usr/src/uts/intel/consconfig_dacf/Makefile b/usr/src/uts/i86pc/consconfig_dacf/Makefile index a9c1c27c38..3867201c6b 100644 --- a/usr/src/uts/intel/consconfig_dacf/Makefile +++ b/usr/src/uts/i86pc/consconfig_dacf/Makefile @@ -19,9 +19,9 @@ # CDDL HEADER END # # -# uts/intel/consconfig_dacf/Makefile +# uts/i86pc/consconfig_dacf/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -39,12 +39,12 @@ UTSBASE = ../.. MODULE = consconfig_dacf OBJECTS = $(CONSCONFIG_DACF_OBJS:%=$(OBJS_DIR)/%) LINTS = $(CONSCONFIG_DACF_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_DACF_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_PSM_DACF_DIR)/$(MODULE) # # Include common rules. # -include $(UTSBASE)/intel/Makefile.intel +include $(UTSBASE)/i86pc/Makefile.i86pc # # Define targets @@ -79,4 +79,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/intel/Makefile.targ +include $(UTSBASE)/i86pc/Makefile.targ diff --git a/usr/src/uts/i86pc/dboot/dboot_elfload.c b/usr/src/uts/i86pc/dboot/dboot_elfload.c new file mode 100644 index 0000000000..5260d2d405 --- /dev/null +++ b/usr/src/uts/i86pc/dboot/dboot_elfload.c @@ -0,0 +1,168 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <sys/inttypes.h> +#include <sys/systm.h> +#include <sys/elf.h> +#include <sys/elf_notes.h> + +#include <util/memcpy.h> + +#include "dboot_xboot.h" +#include "dboot_elfload.h" +#include "dboot_printf.h" + +static caddr_t elf_file = 0; + +#define PGETBYTES(offset) ((void *)(elf_file + (offset))) + +static void * +getehdr(void) +{ + uchar_t *ident; + void *hdr = NULL; + + ident = PGETBYTES(0); + if (ident == NULL) + dboot_panic("Cannot read kernel ELF header\n"); + + if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 || + ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) + dboot_panic("not an ELF file!\n"); + + if (ident[EI_CLASS] == ELFCLASS32) + hdr = PGETBYTES(0); + else if (ident[EI_CLASS] == ELFCLASS64) + hdr = PGETBYTES(0); + else + dboot_panic("Unknown ELF class\n"); + + return (hdr); +} + + +/* + * parse the elf file for program information + */ +int +dboot_elfload64(uintptr_t file_image) +{ + Elf64_Ehdr *eh; + Elf64_Phdr *phdr; + caddr_t allphdrs; + int i; + paddr_t src; + paddr_t dst; + + elf_file = (caddr_t)file_image; + + allphdrs = NULL; + + eh = getehdr(); + if (eh == NULL) + dboot_panic("getehdr() failed\n"); + + if (eh->e_type != ET_EXEC) + dboot_panic("not ET_EXEC, e_type = 0x%x\n", eh->e_type); + + if (eh->e_phnum == 0 || eh->e_phoff == 0) + dboot_panic("no program headers\n"); + + /* + * Get the program headers. + */ + allphdrs = PGETBYTES(eh->e_phoff); + if (allphdrs == NULL) + dboot_panic("Failed to get program headers e_phnum = %d\n", + eh->e_phnum); + + /* + * Next look for interesting program headers. + */ + for (i = 0; i < eh->e_phnum; i++) { + /*LINTED [ELF program header alignment]*/ + phdr = (Elf64_Phdr *)(allphdrs + eh->e_phentsize * i); + + /* + * Dynamically-linked executable. + * Complain. + */ + if (phdr->p_type == PT_INTERP) { + dboot_printf("warning: PT_INTERP section\n"); + continue; + } + + /* + * at this point we only care about PT_LOAD segments + */ + if (phdr->p_type != PT_LOAD) + continue; + + if (phdr->p_flags == (PF_R | PF_W) && phdr->p_vaddr == 0) { + dboot_printf("warning: krtld reloc info?\n"); + continue; + } + + /* + * If memory size is zero just ignore this header. + */ + if (phdr->p_memsz == 0) + continue; + + /* + * If load address 1:1 then ignore this header. + */ + if (phdr->p_paddr == phdr->p_vaddr) { + if (prom_debug) + dboot_printf("Skipping PT_LOAD segment for " + "paddr = 0x%lx\n", (ulong_t)phdr->p_paddr); + continue; + } + + /* + * copy the data to kernel area + */ + if (phdr->p_paddr != FOUR_MEG && phdr->p_paddr != 2 * FOUR_MEG) + dboot_panic("Bad paddr for kernel nucleus segment\n"); + src = (uintptr_t)PGETBYTES(phdr->p_offset); + dst = ktext_phys + phdr->p_paddr - FOUR_MEG; + if (prom_debug) + dboot_printf("copying %lu bytes from ELF offset 0x%lx " + "to physaddr 0x%lx (va=0x%lx)\n", + (ulong_t)phdr->p_filesz, (ulong_t)phdr->p_offset, + (ulong_t)dst, (ulong_t)phdr->p_vaddr); + (void) memcpy((void *)(uintptr_t)dst, + (void *)(uintptr_t)src, (size_t)phdr->p_filesz); + } + + /* + * Ignore the intepreter (or should we die if there is one??) + */ + return (0); +} diff --git a/usr/src/uts/intel/sys/mmu.h b/usr/src/uts/i86pc/dboot/dboot_elfload.h index 167a7ee895..16b7a16011 100644 --- a/usr/src/uts/intel/sys/mmu.h +++ b/usr/src/uts/i86pc/dboot/dboot_elfload.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,20 +18,25 @@ * * CDDL HEADER END */ + /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#ifndef _SYS_MMU_H -#define _SYS_MMU_H +#ifndef _ELFLOAD_H +#define _ELFLOAD_H #pragma ident "%Z%%M% %I% %E% SMI" -#if defined(__i386) || defined(__amd64) +#ifdef __cplusplus +extern "C" { +#endif -#include <ia32/sys/mmu.h> /* XX64 x86/sys/mmu.h */ +extern int dboot_elfload64(uintptr_t); +#ifdef __cplusplus +} #endif -#endif /* _SYS_MMU_H */ +#endif /* _ELFLOAD_H */ diff --git a/usr/src/uts/i86pc/dboot/dboot_grub.s b/usr/src/uts/i86pc/dboot/dboot_grub.s new file mode 100644 index 0000000000..503e1fd31c --- /dev/null +++ b/usr/src/uts/i86pc/dboot/dboot_grub.s @@ -0,0 +1,283 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(__lint) + +int silence_lint_warnings = 0; + +#else /* __lint */ + +#include <sys/multiboot.h> +#include <sys/asm_linkage.h> +#include <sys/segments.h> +#include <sys/controlregs.h> + +#include "dboot_xboot.h" + + .text + .globl _start +_start: + jmp code_start + + /* + * The multiboot header has to be at the start of the file + * + * The 32 bit kernel is ELF32, so the MB header is mostly ignored. + * + * The 64 bit kernel is ELF64, so we get grub to load the entire + * ELF file into memory and trick it into jumping into this code. + * The trick is done by a binary utility run after unix is linked, + * that rewrites the mb_header. + */ + .align 4 + .globl mb_header +mb_header: + .long MB_HEADER_MAGIC /* magic number */ + .long MB_HEADER_FLAGS /* flags */ + .long MB_HEADER_CHECKSUM /* checksum */ + .long 0x11111111 /* header_addr: patched by elfpatch */ + .long 0x100000 /* load_addr: patched by elfpatch */ + .long 0 /* load_end_addr - 0 means entire file */ + .long 0 /* bss_end_addr */ + .long 0x2222222 /* entry_addr: patched by elfpatch */ + .long 0 /* video mode.. */ + .long 0 /* width 0 == don't care */ + .long 0 /* height 0 == don't care */ + .long 0 /* depth 0 == don't care */ + + /* + * At entry we are in protected mode, 32 bit execution, paging and + * interrupts are disabled. + * + * EAX == 0x2BADB002 + * EBX points to multiboot information + * segment registers all have segments with base 0, limit == 0xffffffff + */ +code_start: + movl %ebx, mb_info + + movl $stack_space, %esp /* load my stack pointer */ + addl $STACK_SIZE, %esp + + pushl $0x0 /* push a dead-end frame */ + pushl $0x0 + movl %esp, %ebp + + pushl $0x0 /* clear all processor flags */ + popf + + /* + * setup a global descriptor table with known contents + */ + lgdt gdt_info + movw $B32DATA_SEL, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + ljmp $B32CODE_SEL, $newgdt +newgdt: + nop + + /* + * go off and determine memory config, build page tables, etc. + */ + call startup_kernel + + /* + * On amd64 we'll want the stack pointer to be 16 byte aligned. + */ + andl $0xfffffff0, %esp + + /* + * Enable PGE, PAE and large pages + */ + movl %cr4, %eax + testl $1, pge_support + jz 1f + orl $CR4_PGE, %eax +1: + testl $1, pae_support + jz 1f + orl $CR4_PAE, %eax +1: + testl $1, largepage_support + jz 1f + orl $CR4_PSE, %eax +1: + movl %eax, %cr4 + + /* + * enable NX protection if processor supports it + */ + testl $1, NX_support + jz 1f + movl $MSR_AMD_EFER, %ecx + rdmsr + orl $AMD_EFER_NXE, %eax + wrmsr +1: + + + /* + * load the pagetable base address into cr3 + */ + movl top_page_table, %eax + movl %eax, %cr3 + +#if defined(_BOOT_TARGET_amd64) + /* + * enable long mode + */ + movl $MSR_AMD_EFER, %ecx + rdmsr + orl $AMD_EFER_LME, %eax + wrmsr +#endif + + /* + * enable paging + */ + movl %cr0, %eax + orl $CR0_PG, %eax + movl %eax, %cr0 + jmp paging_on +paging_on: + + /* + * The xboot_info ptr gets passed to the kernel as its argument + */ + movl bi, %edi + movl entry_addr_low, %esi + +#if defined(_BOOT_TARGET_i386) + + pushl %edi + call *%esi + +#elif defined(_BOOT_TARGET_amd64) + + /* + * We're still in compatibility mode with 32 bit execution. + * Switch to 64 bit mode now by switching to a 64 bit code segment. + * then set up and do a lret to get into 64 bit execution. + */ + pushl $B64CODE_SEL + pushl $longmode + lret +longmode: + .code64 + movq $0xffffffff00000000,%rdx + orq %rdx, %rsi /* set upper bits of entry addr */ + notq %rdx + andq %rdx, %rdi /* clean %rdi for passing arg */ + call *%rsi + +#else +#error "undefined target" +#endif + + .code32 + + /* + * uint8_t inb(int port) + */ + ENTRY_NP(inb) + movl 4(%esp), %edx + inb (%dx) + andl $0xff, %eax + ret + SET_SIZE(inb) + + /* + * void outb(int port, uint8_t value) + */ + ENTRY_NP(outb) + movl 4(%esp), %edx + movl 8(%esp), %eax + outb (%dx) + ret + SET_SIZE(outb) + + /* + * if reset fails halt the system + */ + ENTRY_NP(dboot_halt) + hlt + SET_SIZE(dboot_halt) + + /* + * flush the TLB + */ + ENTRY_NP(reload_cr3) + movl %cr3, %eax + movl %eax, %cr3 + ret + SET_SIZE(reload_cr3) + + /* + * do a cpuid instruction, returning the eax/edx values + */ + ENTRY_NP(get_cpuid_edx) + movl 4(%esp), %ecx + movl (%ecx), %eax + pushl %ebx + cpuid + popl %ebx + movl 4(%esp), %ecx + movl %eax, (%ecx) + movl %edx, %eax + ret + SET_SIZE(get_cpuid_edx) + + /* + * Detect if we can do cpuid, see if we can change bit 21 of eflags. + * Note we don't do the bizarre tests for Cyrix CPUs in ml/locore.s. + * If you're on such a CPU, you're stuck with non-PAE 32 bit kernels. + */ + ENTRY_NP(have_cpuid) + pushf + pushf + xorl %eax, %eax + popl %ecx + movl %ecx, %edx + xorl $0x200000, %ecx + pushl %ecx + popf + pushf + popl %ecx + cmpl %ecx, %edx + setne %al + popf + ret + SET_SIZE(have_cpuid) + +#include "../boot/boot_gdt.s" + +#endif /* __lint */ diff --git a/usr/src/uts/i86pc/dboot/dboot_printf.c b/usr/src/uts/i86pc/dboot/dboot_printf.c new file mode 100644 index 0000000000..44450a8c2d --- /dev/null +++ b/usr/src/uts/i86pc/dboot/dboot_printf.c @@ -0,0 +1,205 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/machparam.h> +#include <sys/archsystm.h> + +#include <sys/boot_console.h> + +#include "dboot_printf.h" + +#include "dboot_xboot.h" +#include <sys/varargs.h> + +/* + * This file provides simple output formatting via dboot_printf() + */ + +static void do_dboot_printf(char *fmt, va_list args); + +static char digits[] = "0123456789abcdef"; + +/* + * Primitive version of panic, prints a message then resets the system + */ +void +dboot_panic(char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + do_dboot_printf(fmt, args); + + if (console == CONS_SCREEN_TEXT) { + dboot_printf("Press any key to reboot\n"); + (void) bcons_getchar(); + } + + outb(0x64, 0xfe); /* this resets the system, see pc_reset() */ + dboot_halt(); /* just in case */ +} + +/* + * printf for boot code + */ +void +dboot_printf(char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + do_dboot_printf(fmt, args); +} + + +/* + * output a string + */ +static void +dboot_puts(char *s) +{ + while (*s != 0) { + bcons_putchar(*s); + ++s; + } +} + +static void +dboot_putnum(uint64_t x, uint_t is_signed, uint8_t base) +{ + char buffer[64]; /* digits in reverse order */ + int i; + + if (is_signed && (int64_t)x < 0) { + bcons_putchar('-'); + x = -x; + } + + for (i = -1; x != 0 && i <= 63; x /= base) + buffer[++i] = digits[x - ((x / base) * base)]; + + if (i < 0) + buffer[++i] = '0'; + + while (i >= 0) + bcons_putchar(buffer[i--]); +} + +/* + * very primitive printf - only does %s, %d, %x, %lx, or %% + */ +static void +do_dboot_printf(char *fmt, va_list args) +{ + char *s; + uint64_t x; + uint8_t base; + uint8_t size; + uint_t is_signed = 1; + + if (fmt == NULL) { + dboot_puts("dboot_printf(): 1st arg is NULL\n"); + return; + } + for (; *fmt; ++fmt) { + if (*fmt != '%') { + bcons_putchar(*fmt); + continue; + } + + size = 0; +again: + ++fmt; + switch (*fmt) { + + case '%': + bcons_putchar(*fmt); + break; + + case 'c': + x = va_arg(args, int); + bcons_putchar(x); + break; + + case 's': + s = va_arg(args, char *); + if (s == NULL) + dboot_puts("*NULL*"); + else + dboot_puts(s); + break; + + case 'p': + x = va_arg(args, ulong_t); + dboot_putnum(x, !is_signed, 16); + break; + + case 'l': + if (size == 0) + size = sizeof (long); + else if (size == sizeof (long)) + size = sizeof (long long); + goto again; + + case 'd': + if (size == 0) + x = va_arg(args, int); + else if (size == sizeof (long)) + x = va_arg(args, long); + else + x = va_arg(args, long long); + dboot_putnum(x, is_signed, 10); + break; + + case 'b': + base = 2; + goto unsigned_num; + + case 'o': + base = 8; + goto unsigned_num; + + case 'x': + base = 16; +unsigned_num: + if (size == 0) + x = va_arg(args, uint_t); + else if (size == sizeof (long)) + x = va_arg(args, ulong_t); + else + x = va_arg(args, unsigned long long); + dboot_putnum(x, !is_signed, base); + break; + + default: + dboot_puts("dboot_printf(): unknown % escape\n"); + } + } +} diff --git a/usr/src/psm/stand/boot/amd64/amd64/cpu.h b/usr/src/uts/i86pc/dboot/dboot_printf.h index 9f035799f3..22cf561e51 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/cpu.h +++ b/usr/src/uts/i86pc/dboot/dboot_printf.h @@ -18,13 +18,14 @@ * * CDDL HEADER END */ + /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#ifndef _AMD64_CPU -#define _AMD64_CPU +#ifndef _DBOOT_PRINTF_H +#define _DBOOT_PRINTF_H #pragma ident "%Z%%M% %I% %E% SMI" @@ -32,35 +33,25 @@ extern "C" { #endif -#include <sys/types.h> - -extern void amd64_flush_tlb(void); -extern void amd64_flush_tlbentry(caddr_t); - -extern ulong_t amd64_get_cr2(void); -extern ulong_t amd64_get_cr0(void); -extern ulong_t amd64_get_cr3(void); -extern ulong_t amd64_get_cr4(void); - -extern ulong_t amd64_get_eflags(void); - -struct amd64_cpuid_regs { - uint32_t r_eax; - uint32_t r_ebx; - uint32_t r_ecx; - uint32_t r_edx; -}; +/* + * Very primitive printf. This only understands the following simple formats: + * %%, %c, %s, %d, %ld, %lld, %x, %lx, %llx, %p + */ +/*PRINTFLIKE1*/ +extern void dboot_printf(char *fmt, ...) + __KPRINTFLIKE(1); -#define AMD64_Auth 0x68747541 -#define AMD64_enti 0x69746e65 -#define AMD64_cAMD 0x444d4163 +/* + * Primitive version of panic, prints a message, waits for a keystroke, + * then resets the system + */ +/*PRINTFLIKE1*/ +extern void dboot_panic(char *fmt, ...) + __KPRINTFLIKE(1); -extern uint32_t amd64_cpuid_supported(void); -extern void amd64_cpuid_insn(uint32_t, struct amd64_cpuid_regs *); -extern uint32_t amd64_special_hw(void); #ifdef __cplusplus } #endif -#endif /* _AMD64_CPU */ +#endif /* _DBOOT_PRINTF_H */ diff --git a/usr/src/uts/i86pc/dboot/dboot_startkern.c b/usr/src/uts/i86pc/dboot/dboot_startkern.c new file mode 100644 index 0000000000..ba336c0e9b --- /dev/null +++ b/usr/src/uts/i86pc/dboot/dboot_startkern.c @@ -0,0 +1,827 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <sys/machparam.h> +#include <sys/x86_archext.h> +#include <sys/systm.h> +#include <sys/mach_mmu.h> + +#include <sys/multiboot.h> + +extern multiboot_header_t mb_header; +extern int have_cpuid(void); +extern uint32_t get_cpuid_edx(uint32_t *eax); + +#include <sys/inttypes.h> +#include <sys/bootinfo.h> +#include <sys/mach_mmu.h> +#include <sys/boot_console.h> + +#include "dboot_printf.h" +#include "dboot_xboot.h" +#include "dboot_elfload.h" + +/* + * This file contains code that runs to transition us from either a multiboot + * compliant loader (32 bit non-paging) or Xen domain loader to regular kernel + * execution. Its task is to setup the kernel memory image and page tables. + * + * The code executes as: + * - 32 bits under GRUB (for 32 or 64 bit Solaris) + * - 32 bit program for Xen 32 bit + * - 64 bit program for Xen 64 bit (at least that's my assumption for now) + * + * Under Xen, we must create mappings for any memory beyond the initial + * start of day allocation (such as the kernel itself). + * + * When not under Xen, the mapping between maddr_t and paddr_t is 1:1. + * Since we are running in real mode, so all such memory is accessible. + */ + +/* + * Standard bits used in PTE (page level) and PTP (internal levels) + */ +x86pte_t ptp_bits = PT_VALID | PT_REF | PT_USER | PT_WRITABLE | PT_USER; +x86pte_t pte_bits = PT_VALID | PT_REF | PT_MOD | PT_NOCONSIST | PT_WRITABLE; + +/* + * This is the target addresses (physical) where the kernel text and data + * nucleus pages will be unpacked. On Xen this is actually a virtual address. + */ +paddr_t ktext_phys; +uint32_t ksize = 2 * FOUR_MEG; /* kernel nucleus is 8Meg */ + +static uint64_t target_kernel_text; /* value to use for KERNEL_TEXT */ + +/* + * The stack is setup in assembler before entering startup_kernel() + */ +char stack_space[STACK_SIZE]; + +/* + * Used to track physical memory allocation + */ +static paddr_t next_avail_addr = 0; + +multiboot_info_t *mb_info; + +/* + * This contains information passed to the kernel + */ +struct xboot_info boot_info[2]; /* extra space to fix alignement for amd64 */ +struct xboot_info *bi; + +/* + * Page table and memory stuff. + */ +static uint64_t max_mem; /* maximum memory address */ + +/* + * Information about processor MMU + */ +int amd64_support = 0; +int largepage_support = 0; +int pae_support = 0; +int pge_support = 0; +int NX_support = 0; + +/* + * Low 32 bits of kernel entry address passed back to assembler. + * When running a 64 bit kernel, the high 32 bits are 0xffffffff. + */ +uint32_t entry_addr_low; + +/* + * Memlists for the kernel. We shouldn't need a lot of these. + */ +#define MAX_MEMLIST (10) +struct boot_memlist memlists[MAX_MEMLIST]; +uint_t memlists_used = 0; + +#define MAX_MODULES (10) +struct boot_modules modules[MAX_MODULES]; +uint_t modules_used = 0; + +/* + * Debugging macros + */ +uint_t prom_debug = 0; +uint_t map_debug = 0; + +/* + * The Xen/Grub specific code builds the initial memlists. This code does + * sort/merge/link for final use. + */ +static void +sort_physinstall(void) +{ + int i; + int j; + struct boot_memlist tmp; + + /* + * Now sort the memlists, in case they weren't in order. + * Yeah, this is a bubble sort; small, simple and easy to get right. + */ + DBG_MSG("Sorting phys-installed list\n"); + for (j = memlists_used - 1; j > 0; --j) { + for (i = 0; i < j; ++i) { + if (memlists[i].addr < memlists[i + 1].addr) + continue; + tmp = memlists[i]; + memlists[i] = memlists[i + 1]; + memlists[i + 1] = tmp; + } + } + + /* + * Merge any memlists that don't have holes between them. + */ + for (i = 0; i <= memlists_used - 1; ++i) { + if (memlists[i].addr + memlists[i].size != memlists[i + 1].addr) + continue; + + if (prom_debug) + dboot_printf( + "merging mem segs %" PRIx64 "...%" PRIx64 + " w/ %" PRIx64 "...%" PRIx64 "\n", + memlists[i].addr, + memlists[i].addr + memlists[i].size, + memlists[i + 1].addr, + memlists[i + 1].addr + memlists[i + 1].size); + + memlists[i].size += memlists[i + 1].size; + for (j = i + 1; j < memlists_used - 1; ++j) + memlists[j] = memlists[j + 1]; + --memlists_used; + DBG(memlists_used); + --i; /* after merging we need to reexamine, so do this */ + } + + if (prom_debug) { + dboot_printf("\nFinal memlists:\n"); + for (i = 0; i < memlists_used; ++i) { + dboot_printf("\t%d: addr=%" PRIx64 " size=%" + PRIx64 "\n", i, memlists[i].addr, memlists[i].size); + } + } + + /* + * link together the memlists with native size pointers + */ + memlists[0].next = 0; + memlists[0].prev = 0; + for (i = 1; i < memlists_used; ++i) { + memlists[i].prev = (native_ptr_t)(uintptr_t)(memlists + i - 1); + memlists[i].next = 0; + memlists[i - 1].next = (native_ptr_t)(uintptr_t)(memlists + i); + } + bi->bi_phys_install = (native_ptr_t)memlists; + DBG(bi->bi_phys_install); +} + +x86pte_t +get_pteval(paddr_t table, uint_t index) +{ + if (pae_support) + return (((x86pte_t *)(uintptr_t)table)[index]); + return (((x86pte32_t *)(uintptr_t)table)[index]); +} + +/*ARGSUSED*/ +void +set_pteval(paddr_t table, uint_t index, uint_t level, x86pte_t pteval) +{ + uintptr_t tab_addr = (uintptr_t)table; + + if (pae_support) + ((x86pte_t *)tab_addr)[index] = pteval; + else + ((x86pte32_t *)tab_addr)[index] = (x86pte32_t)pteval; + if (level == top_level && level == 2) + reload_cr3(); +} + +paddr_t +make_ptable(x86pte_t *pteval, uint_t level) +{ + paddr_t new_table = (paddr_t)(uintptr_t)mem_alloc(MMU_PAGESIZE); + + if (level == top_level && level == 2) + *pteval = pa_to_ma((uintptr_t)new_table) | PT_VALID; + else + *pteval = pa_to_ma((uintptr_t)new_table) | ptp_bits; + + if (map_debug) + dboot_printf("new page table lvl=%d paddr=0x%lx ptp=0x%" + PRIx64 "\n", level, (ulong_t)new_table, *pteval); + return (new_table); +} + +x86pte_t * +map_pte(paddr_t table, uint_t index) +{ + return ((x86pte_t *)(uintptr_t)(table + index * pte_size)); +} + +#if 0 /* useful if debugging */ +/* + * dump out the contents of page tables... + */ +static void +dump_tables(void) +{ + uint_t save_index[4]; /* for recursion */ + char *save_table[4]; /* for recursion */ + uint_t l; + uint64_t va; + uint64_t pgsize; + int index; + int i; + x86pte_t pteval; + char *table; + static char *tablist = "\t\t\t"; + char *tabs = tablist + 3 - top_level; + uint_t pa, pa1; + + dboot_printf("Finished pagetables:\n"); + table = (char *)top_page_table; + l = top_level; + va = 0; + for (index = 0; index < ptes_per_table; ++index) { + pgsize = 1ull << shift_amt[l]; + if (pae_support) + pteval = ((x86pte_t *)table)[index]; + else + pteval = ((x86pte32_t *)table)[index]; + if (pteval == 0) + goto next_entry; + + dboot_printf("%s %lx[0x%x] = %" PRIx64 ", va=%" PRIx64, + tabs + l, table, index, (uint64_t)pteval, va); + pa = ma_to_pa(pteval & MMU_PAGEMASK); + dboot_printf(" physaddr=%" PRIx64 "\n", pa); + + /* + * Don't try to walk hypervisor private pagetables + */ + if ((l > 1 || (l == 1 && (pteval & PT_PAGESIZE) == 0))) { + save_table[l] = table; + save_index[l] = index; + --l; + index = -1; + table = (char *)(uintptr_t) + ma_to_pa(pteval & MMU_PAGEMASK); + goto recursion; + } + + /* + * shorten dump for consecutive mappings + */ + for (i = 1; index + i < ptes_per_table; ++i) { + if (pae_support) + pteval = ((x86pte_t *)table)[index + i]; + else + pteval = ((x86pte32_t *)table)[index + i]; + if (pteval == 0) + break; + pa1 = ma_to_pa(pteval & MMU_PAGEMASK); + if (pa1 != pa + i * pgsize) + break; + } + if (i > 2) { + dboot_printf("%s...\n", tabs + l); + va += pgsize * (i - 2); + index += i - 2; + } +next_entry: + va += pgsize; + if (l == 3 && index == 256) /* VA hole */ + va = 0xffff800000000000ull; +recursion: + ; + } + if (l < top_level) { + ++l; + index = save_index[l]; + table = save_table[l]; + goto recursion; + } +} +#endif + +/* + * Add a mapping for the physical page at the given virtual address. + */ +static void +map_pa_at_va(paddr_t pa, native_ptr_t va, uint_t level) +{ + x86pte_t *ptep; + x86pte_t pteval; + + pteval = pa_to_ma(pa) | pte_bits; + if (level > 0) + pteval |= PT_PAGESIZE; + if (va >= target_kernel_text && pge_support) + pteval |= PT_GLOBAL; + + if (map_debug && pa != va) + dboot_printf("mapping pa=0x%" PRIx64 " va=0x%" PRIx64 + " pte=0x%" PRIx64 " l=%d\n", + (uint64_t)pa, (uint64_t)va, pteval, level); + + /* + * Find the pte that will map this address. This creates any + * missing intermediate level page tables + */ + ptep = find_pte(va, NULL, level, 0); + + /* + * On Xen we must use hypervisor calls to modify the PTE, since + * paging is active. On real hardware we just write to the pagetables + * which aren't in use yet. + */ + if (va < 1024 * 1024) + pteval |= PT_NOCACHE; /* for video RAM */ + if (pae_support) + *ptep = pteval; + else + *((x86pte32_t *)ptep) = (x86pte32_t)pteval; +} + +/* + * During memory allocation, find the highest address not used yet. + */ +static void +check_higher(paddr_t a) +{ + if (a < next_avail_addr) + return; + next_avail_addr = RNDUP(a + 1, MMU_PAGESIZE); + DBG(next_avail_addr); +} + +/* + * Walk through the module information finding the last used address. + * The first available address will become the top level page table. + * + * We then build the phys_install memlist from the multiboot information. + */ +static void +init_mem_alloc(void) +{ + mb_memory_map_t *mmap; + mb_module_t *mod; + uint64_t start; + uint64_t end; + uint64_t page_offset = MMU_PAGEOFFSET; /* needs to be 64 bits */ + extern char _end[]; + int i; + + DBG_MSG("Entered init_mem_alloc()\n"); + DBG((uintptr_t)mb_info); + + /* + * search the modules to find the last used address + * we'll build the module list while we're walking through here + */ + DBG_MSG("\nFinding Modules\n"); + check_higher((paddr_t)&_end); + for (mod = (mb_module_t *)(mb_info->mods_addr), i = 0; + i < mb_info->mods_count; + ++mod, ++i) { + if (prom_debug) { + dboot_printf("\tmodule #%d: %s at: 0x%lx, len 0x%lx\n", + i, (char *)(mod->mod_name), + (ulong_t)mod->mod_start, (ulong_t)mod->mod_end); + } + modules[i].bm_addr = mod->mod_start; + modules[i].bm_size = mod->mod_end; + + check_higher(mod->mod_end); + } + bi->bi_modules = (native_ptr_t)modules; + DBG(bi->bi_modules); + bi->bi_module_cnt = mb_info->mods_count; + DBG(bi->bi_module_cnt); + + /* + * Walk through the memory map from multiboot and build our memlist + * structures. Note these will have native format pointers. + */ + DBG_MSG("\nFinding Memory Map\n"); + DBG(mb_info->flags); + max_mem = 0; + if (mb_info->flags & 0x40) { + DBG(mb_info->mmap_addr); + DBG(mb_info->mmap_length); + check_higher(mb_info->mmap_addr + mb_info->mmap_length); + + for (mmap = (mb_memory_map_t *)mb_info->mmap_addr; + (uint32_t)mmap < mb_info->mmap_addr + mb_info->mmap_length; + mmap = (mb_memory_map_t *)((uint32_t)mmap + mmap->size + + sizeof (mmap->size))) { + + start = ((uint64_t)mmap->base_addr_high << 32) + + mmap->base_addr_low; + end = start + ((uint64_t)mmap->length_high << 32) + + mmap->length_low; + + if (prom_debug) { + dboot_printf("\ttype: %d %" PRIx64 "..%" + PRIx64 "\n", mmap->type, start, end); + } + + /* + * only type 1 is usable RAM + */ + if (mmap->type != 1) + continue; + + /* + * page align start and end + */ + start = (start + page_offset) & ~page_offset; + end &= ~page_offset; + if (end <= start) + continue; + + if (end > max_mem) + max_mem = end; + + memlists[memlists_used].addr = start; + memlists[memlists_used].size = end - start; + ++memlists_used; /* no overflow check */ + } + } else if (mb_info->flags & 0x01) { + DBG(mb_info->mem_lower); + memlists[memlists_used].addr = 0; + memlists[memlists_used].size = mb_info->mem_lower * 1024; + ++memlists_used; + DBG(mb_info->mem_upper); + memlists[memlists_used].addr = 1024 * 1024; + memlists[memlists_used].size = mb_info->mem_upper * 1024; + ++memlists_used; + } else { + dboot_panic("No memory info from boot loader!!!\n"); + } + + check_higher(bi->bi_cmdline); + + /* + * finish processing the physinstall list + */ + sort_physinstall(); +} + +/* + * Simple memory allocator, allocates aligned physical memory. + * Note that startup_kernel() only allocates memory, never frees. + * Memory usage just grows in an upward direction. + */ +static void * +do_mem_alloc(uint32_t size, uint32_t align) +{ + uint_t i; + uint64_t best; + uint64_t start; + uint64_t end; + + /* + * make sure size is a multiple of pagesize + */ + size = RNDUP(size, MMU_PAGESIZE); + next_avail_addr = RNDUP(next_avail_addr, align); + + /* + * a really large bootarchive that causes you to run out of memory + * may cause this to blow up + */ + /* LINTED E_UNEXPECTED_UINT_PROMOTION */ + best = (uint64_t)-size; + for (i = 0; i < memlists_used; ++i) { + start = memlists[i].addr; + end = start + memlists[i].size; + + /* + * did we find the desired address? + */ + if (start <= next_avail_addr && next_avail_addr + size <= end) { + best = next_avail_addr; + goto done; + } + + /* + * if not is this address the best so far? + */ + if (start > next_avail_addr && start < best && + RNDUP(start, align) + size <= end) + best = RNDUP(start, align); + } + + /* + * We didn't find exactly the address we wanted, due to going off the + * end of a memory region. Return the best found memory address. + */ +done: + next_avail_addr = best + size; + (void) memset((void *)(uintptr_t)best, 0, size); + return ((void *)(uintptr_t)best); +} + +void * +mem_alloc(uint32_t size) +{ + return (do_mem_alloc(size, MMU_PAGESIZE)); +} + + +/* + * Build page tables to map all of memory used so far as well as the kernel. + */ +static void +build_page_tables(void) +{ + uint32_t psize; + uint32_t level; + uint32_t off; + uint32_t i; + uint64_t start; + uint64_t end; + uint64_t next_mapping; + + /* + * If we're not using Xen, we need to create the top level pagetable. + */ + top_page_table = (paddr_t)(uintptr_t)mem_alloc(MMU_PAGESIZE); + DBG((uintptr_t)top_page_table); + + /* + * Determine if we'll use large mappings for kernel, then map it. + */ + if (largepage_support) { + psize = lpagesize; + level = 1; + } else { + psize = MMU_PAGESIZE; + level = 0; + } + + DBG_MSG("Mapping kernel\n"); + DBG(ktext_phys); + DBG(target_kernel_text); + DBG(ksize); + DBG(psize); + for (off = 0; off < ksize; off += psize) + map_pa_at_va(ktext_phys + off, target_kernel_text + off, level); + + /* + * The kernel will need a 1 page window to work with page tables + */ + bi->bi_pt_window = (uintptr_t)mem_alloc(MMU_PAGESIZE); + DBG(bi->bi_pt_window); + bi->bi_pte_to_pt_window = + (uintptr_t)find_pte(bi->bi_pt_window, NULL, 0, 0); + DBG(bi->bi_pte_to_pt_window); + + /* + * Under multiboot we need 1:1 mappings for all of low memory, which + * includes our pagetables. The following code works because our + * simple memory allocator only grows usage in an upwards direction. + * + * We map *all* possible addresses below 1 Meg, since things like + * the video RAM are down there. + * + * Skip memory between 1M and _start, this acts as a reserve + * of memory usable for DMA. + */ + next_mapping = (uintptr_t)_start & MMU_PAGEMASK; + if (map_debug) + dboot_printf("1:1 map pa=0..1Meg\n"); + for (start = 0; start < 1024 * 1024; start += MMU_PAGESIZE) + map_pa_at_va(start, start, 0); + + for (i = 0; i < memlists_used; ++i) { + start = memlists[i].addr; + if (start < next_mapping) + start = next_mapping; + + end = start + memlists[i].size; + + if (map_debug) + dboot_printf("1:1 map pa=%" PRIx64 "..%" PRIx64 "\n", + start, end); + while (start < end && start < next_avail_addr) { + map_pa_at_va(start, start, 0); + start += MMU_PAGESIZE; + } + } + + DBG_MSG("\nPage tables constructed\n"); +} + +#define NO_MULTIBOOT \ +"multiboot is no longer used to boot the Solaris Operating System.\n\ +The grub entry should be changed to:\n\ +kernel$ /platform/i86pc/kernel/$ISADIR/unix\n\ +module$ /platform/i86pc/$ISADIR/boot_archive\n\ +See http://www.sun.com/msg/SUNOS-8000-AK for details.\n" + +/* + * startup_kernel has a pretty simple job. It builds pagetables which reflect + * 1:1 mappings for all memory in use. It then also adds mappings for + * the kernel nucleus at virtual address of target_kernel_text using large page + * mappings. The page table pages are also accessible at 1:1 mapped + * virtual addresses. + */ +/*ARGSUSED*/ +void +startup_kernel(void) +{ + char *cmdline; + uintptr_t addr; + + /* + * At this point we are executing in a 32 bit real mode. + */ + cmdline = (char *)mb_info->cmdline; + prom_debug = (strstr(cmdline, "prom_debug") != NULL); + map_debug = (strstr(cmdline, "map_debug") != NULL); + bcons_init(cmdline); + DBG_MSG("\n\nSolaris prekernel set: "); + DBG_MSG(cmdline); + DBG_MSG("\n"); + + if (strstr(cmdline, "multiboot") != NULL) { + dboot_panic(NO_MULTIBOOT); + } + + /* + * boot info must be 16 byte aligned for 64 bit kernel ABI + */ + addr = (uintptr_t)boot_info; + addr = (addr + 0xf) & ~0xf; + bi = (struct xboot_info *)addr; + DBG((uintptr_t)bi); + bi->bi_cmdline = (native_ptr_t)(uintptr_t)cmdline; + + /* + * Need correct target_kernel_text value + */ +#if defined(_BOOT_TARGET_amd64) + target_kernel_text = KERNEL_TEXT_amd64; +#else + target_kernel_text = KERNEL_TEXT_i386; +#endif + DBG(target_kernel_text); + + /* + * use cpuid to enable MMU features + */ + if (have_cpuid()) { + uint32_t eax, edx; + + eax = 1; + edx = get_cpuid_edx(&eax); + if (edx & CPUID_INTC_EDX_PSE) + largepage_support = 1; + if (edx & CPUID_INTC_EDX_PGE) + pge_support = 1; + if (edx & CPUID_INTC_EDX_PAE) + pae_support = 1; + + eax = 0x80000000; + edx = get_cpuid_edx(&eax); + if (eax >= 0x80000001) { + eax = 0x80000001; + edx = get_cpuid_edx(&eax); + if (edx & CPUID_AMD_EDX_LM) + amd64_support = 1; + if (edx & CPUID_AMD_EDX_NX) + NX_support = 1; + } + } else { + dboot_printf("cpuid not supported\n"); + } + +#if defined(_BOOT_TARGET_amd64) + if (amd64_support == 0) + dboot_panic("long mode not supported, rebooting\n"); + else if (pae_support == 0) + dboot_panic("long mode, but no PAE; rebooting\n"); +#endif + + /* + * initialize our memory allocator + */ + init_mem_alloc(); + + /* + * configure mmu information + */ +#if !defined(_BOOT_TARGET_amd64) + if (pae_support && (max_mem > FOUR_GIG || NX_support)) { +#endif + shift_amt = shift_amt_pae; + ptes_per_table = 512; + pte_size = 8; + lpagesize = TWO_MEG; +#if defined(_BOOT_TARGET_amd64) + top_level = 3; +#else + top_level = 2; +#endif +#if !defined(_BOOT_TARGET_amd64) + } else { + pae_support = 0; + NX_support = 0; + shift_amt = shift_amt_nopae; + ptes_per_table = 1024; + pte_size = 4; + lpagesize = FOUR_MEG; + top_level = 1; + } +#endif + + DBG(pge_support); + DBG(NX_support); + DBG(largepage_support); + DBG(amd64_support); + DBG(top_level); + DBG(pte_size); + DBG(ptes_per_table); + DBG(lpagesize); + + ktext_phys = FOUR_MEG; /* from UNIX Mapfile */ + +#if defined(_BOOT_TARGET_amd64) + /* + * For grub, copy kernel bits from the ELF64 file to final place. + */ + DBG_MSG("\nAllocating nucleus pages.\n"); + ktext_phys = (uintptr_t)do_mem_alloc(ksize, FOUR_MEG); + if (ktext_phys == 0) + dboot_panic("failed to allocate aligned kernel memory\n"); + if (dboot_elfload64(mb_header.load_addr) != 0) + dboot_panic("failed to parse kernel ELF image, rebooting\n"); + +#endif + DBG(ktext_phys); + + /* + * Allocate page tables. + */ + build_page_tables(); + + /* + * return to assembly code to switch to running kernel + */ + entry_addr_low = (uint32_t)target_kernel_text; + DBG(entry_addr_low); + bi->bi_use_largepage = largepage_support; + bi->bi_use_pae = pae_support; + bi->bi_use_pge = pge_support; + bi->bi_use_nx = NX_support; + bi->bi_next_paddr = next_avail_addr; + DBG(bi->bi_next_paddr); + bi->bi_next_vaddr = (uintptr_t)next_avail_addr; + DBG(bi->bi_next_vaddr); + bi->bi_mb_info = (uintptr_t)mb_info; + bi->bi_top_page_table = (uintptr_t)top_page_table; + + bi->bi_kseg_size = FOUR_MEG; + DBG(bi->bi_kseg_size); + +#if 0 /* useful if debugging initial page tables */ + if (prom_debug) + dump_tables(); +#endif + + DBG_MSG("\n\n*** DBOOT DONE -- back to asm to jump to kernel\n\n"); +} diff --git a/usr/src/uts/i86pc/dboot/dboot_xboot.h b/usr/src/uts/i86pc/dboot/dboot_xboot.h new file mode 100644 index 0000000000..fac4ee9c74 --- /dev/null +++ b/usr/src/uts/i86pc/dboot/dboot_xboot.h @@ -0,0 +1,83 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _DBOOT_XBOOT_H +#define _DBOOT_XBOOT_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/mach_mmu.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/note.h> + +/* + * Stack used by xboot + */ +#define STACK_SIZE 0x8000 + +#ifndef _ASM + +extern paddr_t ktext_phys; +extern struct xboot_info *bi; + +/* + * Debugging macros + */ +extern uint_t prom_debug; + +#define DBG_MSG(s) do { if (prom_debug) \ + dboot_printf(s); \ + _NOTE(CONSTANTCONDITION) \ + } while (0) + +#define DBG(x) do { if (prom_debug) { \ + dboot_printf("%s is 0x%" PRIx64 "\n", #x, (uint64_t)(x)); \ + _NOTE(CONSTANTCONDITION) \ + } } while (0) + +extern void dboot_halt(void); +extern void *mem_alloc(uint32_t size); + +#define RNDUP(x, y) ((x) + ((y) - 1ul) & ~((y) - 1ul)) + +/* + * this is gross too, but archsystm.h is under a #ifdef _KERNEL + */ +extern uint8_t inb(int port); +extern void outb(int port, uint8_t value); + +#endif /* _ASM */ + + +#ifdef __cplusplus +} +#endif + +#endif /* _DBOOT_XBOOT_H */ diff --git a/usr/src/uts/i86pc/genassym/Makefile b/usr/src/uts/i86pc/genassym/Makefile index 96e0a20169..55425ce673 100644 --- a/usr/src/uts/i86pc/genassym/Makefile +++ b/usr/src/uts/i86pc/genassym/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -37,6 +36,7 @@ UTSBASE = ../.. ASSYM_H = $(DSF_DIR)/$(OBJS_DIR)/assym.h +KDI_ASSYM_H = $(DSF_DIR)/$(OBJS_DIR)/kdi_assym.h GENASSYM = $(DSF_DIR)/$(OBJS_DIR)/genassym # @@ -47,7 +47,7 @@ include $(UTSBASE)/i86pc/Makefile.i86pc # # Define targets # -ALL_TARGET = $(ASSYM_H) +ALL_TARGET = $(ASSYM_H) $(KDI_ASSYM_H) # # This is DSF_DIR. Use a short path. @@ -59,7 +59,7 @@ DSF_DIR = . # Overrides # CLEANFILES = $(GENASSYM) Nothing_to_remove -CLOBBERFILES = $(ASSYM_H) $(CLEANFILES) Nothing_to_remove +CLOBBERFILES = $(ASSYM_H) $(KDI_ASSYM.H) $(CLEANFILES) Nothing_to_remove # # Default build targets. @@ -90,6 +90,10 @@ $(ASSYM_H): $(OFFSETS_SRC) $(PLATFORM_OFFSETS_SRC) $(GENASSYM) $(OFFSETS_CREATE) <$(PLATFORM_OFFSETS_SRC) >>$@ $(GENASSYM) >>$@ +$(KDI_ASSYM_H): $(KDI_OFFSETS_SRC) $(GENASSYM) + $(OFFSETS_CREATE) <$(KDI_OFFSETS_SRC) >$@ + $(GENASSYM) >>$@ + # # Include common targets. # diff --git a/usr/src/uts/i86pc/io/cbe.c b/usr/src/uts/i86pc/io/cbe.c index 2863b289ae..7667bb2219 100644 --- a/usr/src/uts/i86pc/io/cbe.c +++ b/usr/src/uts/i86pc/io/cbe.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,10 +18,12 @@ * * CDDL HEADER END */ + /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ + #pragma ident "%Z%%M% %I% %E% SMI" #include <sys/systm.h> @@ -34,6 +35,7 @@ #include <sys/machsystm.h> #include <sys/smp_impldefs.h> #include <sys/psm_types.h> +#include <sys/psm.h> #include <sys/atomic.h> #include <sys/clock.h> #include <sys/ddi_impldefs.h> @@ -79,7 +81,6 @@ cbe_low_level(void) * to the timer firing at level-14. Because cyclic_fire() can tolerate * spurious calls, it would not matter if we called cyclic_fire() in both * cases. - * */ int cbe_fire(void) @@ -92,8 +93,10 @@ cbe_fire(void) if (cbe_psm_timer_mode != TIMER_ONESHOT && me == 0 && !cross_call) { for (i = 1; i < NCPU; i++) { - if (CPU_IN_SET(cbe_enabled, i)) + if (CPU_IN_SET(cbe_enabled, i)) { + XC_TRACE(TT_XC_CBE_FIRE, -1, i); send_dirint(i, CBE_HIGH_PIL); + } } } @@ -180,6 +183,7 @@ cbe_xcall(void *arg, cpu_t *dest, cyc_func_t func, void *farg) cbe_xcall_cpu = dest; cbe_xcall_func = func; + XC_TRACE(TT_XC_CBE_XCALL, -1, dest->cpu_id); send_dirint(dest->cpu_id, CBE_HIGH_PIL); while (cbe_xcall_func != NULL || cbe_xcall_cpu != NULL) @@ -312,5 +316,4 @@ cbe_init(void) (*psm_post_cyclic_setup)(NULL); mutex_exit(&cpu_lock); - } diff --git a/usr/src/uts/intel/io/consplat.c b/usr/src/uts/i86pc/io/consplat.c index 78500fce34..78500fce34 100644 --- a/usr/src/uts/intel/io/consplat.c +++ b/usr/src/uts/i86pc/io/consplat.c diff --git a/usr/src/uts/common/io/pit.c b/usr/src/uts/i86pc/io/hardclk.c index 6a69ca2d19..05961429c8 100644 --- a/usr/src/uts/common/io/pit.c +++ b/usr/src/uts/i86pc/io/hardclk.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +34,7 @@ #include <sys/time.h> #include <sys/systm.h> #include <sys/archsystm.h> +#include <sys/lockstat.h> #include <sys/clock.h> #include <sys/debug.h> @@ -42,18 +43,15 @@ /* * This file contains all generic part of clock and timer handling. - * Specifics are now in a seperate file and may be overridden by OEM - * modules which get loaded. Defaults come from i8254.c and hardclk.c + * Specifics are now in separate files and may be overridden by TOD + * modules. */ unsigned int microdata = 50; /* loop count for 10 microsecond wait. */ /* MUST be initialized for those who */ /* insist on calling "tenmicrosec" before */ /* the clock has been initialized. */ -timestruc_t (*todgetf)(void) = pc_tod_get; -void (*todsetf)(timestruc_t) = pc_tod_set; - -long gmt_lag; /* offset in seconds of gmt to local time */ +char *tod_module_name; /* Settable in /etc/system */ /* * Write the specified time into the clock chip. @@ -68,7 +66,7 @@ tod_set(timestruc_t ts) * Prevent false alarm in tod_validate() due to tod value change. */ tod_fault_reset(); - (*todsetf)(ts); + TODOP_SET(tod_ops, ts); } /* @@ -83,18 +81,44 @@ tod_get(void) ASSERT(MUTEX_HELD(&tod_lock)); - ts = (*todgetf)(); + ts = TODOP_GET(tod_ops); ts.tv_sec = tod_validate(ts.tv_sec); return (ts); } +/* + * The following wrappers have been added so that locking + * can be exported to platform-independent clock routines + * (ie adjtime(), clock_setttime()), via a functional interface. + */ +int +hr_clock_lock(void) +{ + ushort_t s; + + CLOCK_LOCK(&s); + return (s); +} + +void +hr_clock_unlock(int s) +{ + CLOCK_UNLOCK(s); +} + +/* + * Support routines for horrid GMT lag handling + */ + +static time_t gmt_lag; /* offset in seconds of gmt to local time */ + void -sgmtl(long arg) +sgmtl(time_t arg) { gmt_lag = arg; } -long +time_t ggmtl(void) { return (gmt_lag); @@ -108,7 +132,7 @@ rtcsync(void) timestruc_t ts; mutex_enter(&tod_lock); - ts = (*todgetf)(); + ts = TODOP_GET(tod_ops); set_hrestime(&ts); mutex_exit(&tod_lock); } diff --git a/usr/src/uts/i86pc/io/mp_platform_common.c b/usr/src/uts/i86pc/io/mp_platform_common.c new file mode 100644 index 0000000000..b032ec1b7c --- /dev/null +++ b/usr/src/uts/i86pc/io/mp_platform_common.c @@ -0,0 +1,3736 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * PSMI 1.1 extensions are supported only in 2.6 and later versions. + * PSMI 1.2 extensions are supported only in 2.7 and later versions. + * PSMI 1.3 and 1.4 extensions are supported in Solaris 10. + * PSMI 1.5 extensions are supported in Solaris Nevada. + */ +#define PSMI_1_5 + +#include <sys/processor.h> +#include <sys/time.h> +#include <sys/psm.h> +#include <sys/smp_impldefs.h> +#include <sys/cram.h> +#include <sys/acpi/acpi.h> +#include <sys/acpica.h> +#include <sys/psm_common.h> +#include <sys/apic.h> +#include <sys/pit.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/ddi_impldefs.h> +#include <sys/pci.h> +#include <sys/promif.h> +#include <sys/x86_archext.h> +#include <sys/cpc_impl.h> +#include <sys/uadmin.h> +#include <sys/panic.h> +#include <sys/debug.h> +#include <sys/archsystm.h> +#include <sys/trap.h> +#include <sys/machsystm.h> +#include <sys/cpuvar.h> +#include <sys/rm_platter.h> +#include <sys/privregs.h> +#include <sys/cyclic.h> +#include <sys/note.h> +#include <sys/pci_intr_lib.h> +#include <sys/sunndi.h> + + +/* + * Local Function Prototypes + */ +static int apic_handle_defconf(); +static int apic_parse_mpct(caddr_t mpct, int bypass); +static struct apic_mpfps_hdr *apic_find_fps_sig(caddr_t fptr, int size); +static int apic_checksum(caddr_t bptr, int len); +static int apic_find_bus_type(char *bus); +static int apic_find_bus(int busid); +static int apic_find_bus_id(int bustype); +static struct apic_io_intr *apic_find_io_intr(int irqno); +static int apic_find_free_irq(int start, int end); +static void apic_mark_vector(uchar_t oldvector, uchar_t newvector); +static void apic_xlate_vector_free_timeout_handler(void *arg); +static void apic_reprogram_timeout_handler(void *arg); +static int apic_check_stuck_interrupt(apic_irq_t *irq_ptr, int old_bind_cpu, + int new_bind_cpu, int apicindex, int intin_no, int which_irq, + struct ioapic_reprogram_data *drep); +static void apic_record_rdt_entry(apic_irq_t *irqptr, int irq); +static struct apic_io_intr *apic_find_io_intr_w_busid(int irqno, int busid); +static int apic_find_intin(uchar_t ioapic, uchar_t intin); +static int apic_handle_pci_pci_bridge(dev_info_t *idip, int child_devno, + int child_ipin, struct apic_io_intr **intrp); +static int apic_setup_irq_table(dev_info_t *dip, int irqno, + struct apic_io_intr *intrp, struct intrspec *ispec, iflag_t *intr_flagp, + int type); +static int apic_setup_sci_irq_table(int irqno, uchar_t ipl, + iflag_t *intr_flagp); +static void apic_set_pwroff_method_from_mpcnfhdr(struct apic_mp_cnf_hdr *hdrp); +static void apic_try_deferred_reprogram(int ipl, int vect); +static void delete_defer_repro_ent(int which_irq); +static void apic_ioapic_wait_pending_clear(int ioapicindex, + int intin_no); + +int apic_debug_mps_id = 0; /* 1 - print MPS ID strings */ + +/* ACPI SCI interrupt configuration; -1 if SCI not used */ +int apic_sci_vect = -1; +iflag_t apic_sci_flags; + +/* + * psm name pointer + */ +static char *psm_name; + +/* ACPI support routines */ +static int acpi_probe(char *); +static int apic_acpi_irq_configure(acpi_psm_lnk_t *acpipsmlnkp, dev_info_t *dip, + int *pci_irqp, iflag_t *intr_flagp); + +static int apic_acpi_translate_pci_irq(dev_info_t *dip, int busid, int devid, + int ipin, int *pci_irqp, iflag_t *intr_flagp); +static uchar_t acpi_find_ioapic(int irq); +static int acpi_intr_compatible(iflag_t iflag1, iflag_t iflag2); + + +/* + * number of bits per byte, from <sys/param.h> + */ +#define UCHAR_MAX ((1 << NBBY) - 1) + +/* Max wait time (in repetitions) for flags to clear in an RDT entry. */ +int apic_max_reps_clear_pending = 1000; + +/* The irq # is implicit in the array index: */ +struct ioapic_reprogram_data apic_reprogram_info[APIC_MAX_VECTOR+1]; +/* + * APIC_MAX_VECTOR + 1 is the maximum # of IRQs as well. ioapic_reprogram_info + * is indexed by IRQ number, NOT by vector number. + */ + +int apic_intr_policy = INTR_ROUND_ROBIN_WITH_AFFINITY; + +int apic_next_bind_cpu = 1; /* For round robin assignment */ + /* start with cpu 1 */ + +/* + * If enabled, the distribution works as follows: + * On every interrupt entry, the current ipl for the CPU is set in cpu_info + * and the irq corresponding to the ipl is also set in the aci_current array. + * interrupt exit and setspl (due to soft interrupts) will cause the current + * ipl to be be changed. This is cache friendly as these frequently used + * paths write into a per cpu structure. + * + * Sampling is done by checking the structures for all CPUs and incrementing + * the busy field of the irq (if any) executing on each CPU and the busy field + * of the corresponding CPU. + * In periodic mode this is done on every clock interrupt. + * In one-shot mode, this is done thru a cyclic with an interval of + * apic_redistribute_sample_interval (default 10 milli sec). + * + * Every apic_sample_factor_redistribution times we sample, we do computations + * to decide which interrupt needs to be migrated (see comments + * before apic_intr_redistribute(). + */ + +/* + * Following 3 variables start as % and can be patched or set using an + * API to be defined in future. They will be scaled to + * sample_factor_redistribution which is in turn set to hertz+1 (in periodic + * mode), or 101 in one-shot mode to stagger it away from one sec processing + */ + +int apic_int_busy_mark = 60; +int apic_int_free_mark = 20; +int apic_diff_for_redistribution = 10; + +/* sampling interval for interrupt redistribution for dynamic migration */ +int apic_redistribute_sample_interval = NANOSEC / 100; /* 10 millisec */ + +/* + * number of times we sample before deciding to redistribute interrupts + * for dynamic migration + */ +int apic_sample_factor_redistribution = 101; + +/* timeout for xlate_vector, mark_vector */ +int apic_revector_timeout = 16 * 10000; /* 160 millisec */ + +int apic_redist_cpu_skip = 0; +int apic_num_imbalance = 0; +int apic_num_rebind = 0; + +int apic_nproc = 0; +size_t apic_cpus_size = 0; +int apic_defconf = 0; +int apic_irq_translate = 0; +int apic_spec_rev = 0; +int apic_imcrp = 0; + +int apic_use_acpi = 1; /* 1 = use ACPI, 0 = don't use ACPI */ +int apic_use_acpi_madt_only = 0; /* 1=ONLY use MADT from ACPI */ + +/* + * For interrupt link devices, if apic_unconditional_srs is set, an irq resource + * will be assigned (via _SRS). If it is not set, use the current + * irq setting (via _CRS), but only if that irq is in the set of possible + * irqs (returned by _PRS) for the device. + */ +int apic_unconditional_srs = 1; + +/* + * For interrupt link devices, if apic_prefer_crs is set when we are + * assigning an IRQ resource to a device, prefer the current IRQ setting + * over other possible irq settings under same conditions. + */ + +int apic_prefer_crs = 1; + +uchar_t apic_io_id[MAX_IO_APIC]; +volatile uint32_t *apicioadr[MAX_IO_APIC]; +static uchar_t apic_io_ver[MAX_IO_APIC]; +static uchar_t apic_io_vectbase[MAX_IO_APIC]; +static uchar_t apic_io_vectend[MAX_IO_APIC]; +uchar_t apic_reserved_irqlist[MAX_ISA_IRQ + 1]; +uint32_t apic_physaddr[MAX_IO_APIC]; + +/* + * First available slot to be used as IRQ index into the apic_irq_table + * for those interrupts (like MSI/X) that don't have a physical IRQ. + */ +int apic_first_avail_irq = APIC_FIRST_FREE_IRQ; + +/* + * apic_ioapic_lock protects the ioapics (reg select), the status, temp_bound + * and bound elements of cpus_info and the temp_cpu element of irq_struct + */ +lock_t apic_ioapic_lock; + +/* + * apic_defer_reprogram_lock ensures that only one processor is handling + * deferred interrupt programming at apic_intr_exit time. + */ +static lock_t apic_defer_reprogram_lock; + +/* + * The current number of deferred reprogrammings outstanding + */ +uint_t apic_reprogram_outstanding = 0; + +#ifdef DEBUG +/* + * Counters that keep track of deferred reprogramming stats + */ +uint_t apic_intr_deferrals = 0; +uint_t apic_intr_deliver_timeouts = 0; +uint_t apic_last_ditch_reprogram_failures = 0; +uint_t apic_deferred_setup_failures = 0; +uint_t apic_defer_repro_total_retries = 0; +uint_t apic_defer_repro_successes = 0; +uint_t apic_deferred_spurious_enters = 0; +#endif + +static int apic_io_max = 0; /* no. of i/o apics enabled */ + +static struct apic_io_intr *apic_io_intrp = 0; +static struct apic_bus *apic_busp; + +uchar_t apic_vector_to_irq[APIC_MAX_VECTOR+1]; +uchar_t apic_resv_vector[MAXIPL+1]; + +char apic_level_intr[APIC_MAX_VECTOR+1]; + +static uint32_t eisa_level_intr_mask = 0; + /* At least MSB will be set if EISA bus */ + +static int apic_pci_bus_total = 0; +static uchar_t apic_single_pci_busid = 0; + +/* + * airq_mutex protects additions to the apic_irq_table - the first + * pointer and any airq_nexts off of that one. It also protects + * apic_max_device_irq & apic_min_device_irq. It also guarantees + * that share_id is unique as new ids are generated only when new + * irq_t structs are linked in. Once linked in the structs are never + * deleted. temp_cpu & mps_intr_index field indicate if it is programmed + * or allocated. Note that there is a slight gap between allocating in + * apic_introp_xlate and programming in addspl. + */ +kmutex_t airq_mutex; +apic_irq_t *apic_irq_table[APIC_MAX_VECTOR+1]; +int apic_max_device_irq = 0; +int apic_min_device_irq = APIC_MAX_VECTOR; + +/* + * Following declarations are for revectoring; used when ISRs at different + * IPLs share an irq. + */ +static lock_t apic_revector_lock; +int apic_revector_pending = 0; +static uchar_t *apic_oldvec_to_newvec; +static uchar_t *apic_newvec_to_oldvec; + +typedef struct prs_irq_list_ent { + int list_prio; + int32_t irq; + iflag_t intrflags; + acpi_prs_private_t prsprv; + struct prs_irq_list_ent *next; +} prs_irq_list_t; + + +/* + * ACPI variables + */ +/* 1 = acpi is enabled & working, 0 = acpi is not enabled or not there */ +int apic_enable_acpi = 0; + +/* ACPI Multiple APIC Description Table ptr */ +static MULTIPLE_APIC_TABLE *acpi_mapic_dtp = NULL; + +/* ACPI Interrupt Source Override Structure ptr */ +static MADT_INTERRUPT_OVERRIDE *acpi_isop = NULL; +static int acpi_iso_cnt = 0; + +/* ACPI Non-maskable Interrupt Sources ptr */ +static MADT_NMI_SOURCE *acpi_nmi_sp = NULL; +static int acpi_nmi_scnt = 0; +static MADT_LOCAL_APIC_NMI *acpi_nmi_cp = NULL; +static int acpi_nmi_ccnt = 0; + +extern int apic_pci_msi_enable_vector(dev_info_t *, int, int, + int, int, int); +extern apic_irq_t *apic_find_irq(dev_info_t *, struct intrspec *, int); + +/* + * The following added to identify a software poweroff method if available. + */ + +static struct { + int poweroff_method; + char oem_id[APIC_MPS_OEM_ID_LEN + 1]; /* MAX + 1 for NULL */ + char prod_id[APIC_MPS_PROD_ID_LEN + 1]; /* MAX + 1 for NULL */ +} apic_mps_ids[] = { + { APIC_POWEROFF_VIA_RTC, "INTEL", "ALDER" }, /* 4300 */ + { APIC_POWEROFF_VIA_RTC, "NCR", "AMC" }, /* 4300 */ + { APIC_POWEROFF_VIA_ASPEN_BMC, "INTEL", "A450NX" }, /* 4400? */ + { APIC_POWEROFF_VIA_ASPEN_BMC, "INTEL", "AD450NX" }, /* 4400 */ + { APIC_POWEROFF_VIA_ASPEN_BMC, "INTEL", "AC450NX" }, /* 4400R */ + { APIC_POWEROFF_VIA_SITKA_BMC, "INTEL", "S450NX" }, /* S50 */ + { APIC_POWEROFF_VIA_SITKA_BMC, "INTEL", "SC450NX" } /* S50? */ +}; + +int apic_poweroff_method = APIC_POWEROFF_NONE; + +/* + * Auto-configuration routines + */ + +/* + * Look at MPSpec 1.4 (Intel Order # 242016-005) for details of what we do here + * May work with 1.1 - but not guaranteed. + * According to the MP Spec, the MP floating pointer structure + * will be searched in the order described below: + * 1. In the first kilobyte of Extended BIOS Data Area (EBDA) + * 2. Within the last kilobyte of system base memory + * 3. In the BIOS ROM address space between 0F0000h and 0FFFFh + * Once we find the right signature with proper checksum, we call + * either handle_defconf or parse_mpct to get all info necessary for + * subsequent operations. + */ +int +apic_probe_common(char *modname) +{ + uint32_t mpct_addr, ebda_start = 0, base_mem_end; + caddr_t biosdatap; + caddr_t mpct; + caddr_t fptr; + int i, mpct_size, mapsize, retval = PSM_FAILURE; + ushort_t ebda_seg, base_mem_size; + struct apic_mpfps_hdr *fpsp; + struct apic_mp_cnf_hdr *hdrp; + int bypass_cpu_and_ioapics_in_mptables; + int acpi_user_options; + + if (apic_forceload < 0) + return (retval); + + /* + * Remember who we are + */ + psm_name = modname; + + /* Allow override for MADT-only mode */ + acpi_user_options = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(), 0, + "acpi-user-options", 0); + apic_use_acpi_madt_only = ((acpi_user_options & ACPI_OUSER_MADT) != 0); + + /* Allow apic_use_acpi to override MADT-only mode */ + if (!apic_use_acpi) + apic_use_acpi_madt_only = 0; + + retval = acpi_probe(modname); + + /* + * mapin the bios data area 40:0 + * 40:13h - two-byte location reports the base memory size + * 40:0Eh - two-byte location for the exact starting address of + * the EBDA segment for EISA + */ + biosdatap = psm_map_phys(0x400, 0x20, PROT_READ); + if (!biosdatap) + return (retval); + fpsp = (struct apic_mpfps_hdr *)NULL; + mapsize = MPFPS_RAM_WIN_LEN; + /*LINTED: pointer cast may result in improper alignment */ + ebda_seg = *((ushort_t *)(biosdatap+0xe)); + /* check the 1k of EBDA */ + if (ebda_seg) { + ebda_start = ((uint32_t)ebda_seg) << 4; + fptr = psm_map_phys(ebda_start, MPFPS_RAM_WIN_LEN, PROT_READ); + if (fptr) { + if (!(fpsp = + apic_find_fps_sig(fptr, MPFPS_RAM_WIN_LEN))) + psm_unmap_phys(fptr, MPFPS_RAM_WIN_LEN); + } + } + /* If not in EBDA, check the last k of system base memory */ + if (!fpsp) { + /*LINTED: pointer cast may result in improper alignment */ + base_mem_size = *((ushort_t *)(biosdatap + 0x13)); + + if (base_mem_size > 512) + base_mem_end = 639 * 1024; + else + base_mem_end = 511 * 1024; + /* if ebda == last k of base mem, skip to check BIOS ROM */ + if (base_mem_end != ebda_start) { + + fptr = psm_map_phys(base_mem_end, MPFPS_RAM_WIN_LEN, + PROT_READ); + + if (fptr) { + if (!(fpsp = apic_find_fps_sig(fptr, + MPFPS_RAM_WIN_LEN))) + psm_unmap_phys(fptr, MPFPS_RAM_WIN_LEN); + } + } + } + psm_unmap_phys(biosdatap, 0x20); + + /* If still cannot find it, check the BIOS ROM space */ + if (!fpsp) { + mapsize = MPFPS_ROM_WIN_LEN; + fptr = psm_map_phys(MPFPS_ROM_WIN_START, + MPFPS_ROM_WIN_LEN, PROT_READ); + if (fptr) { + if (!(fpsp = + apic_find_fps_sig(fptr, MPFPS_ROM_WIN_LEN))) { + psm_unmap_phys(fptr, MPFPS_ROM_WIN_LEN); + return (retval); + } + } + } + + if (apic_checksum((caddr_t)fpsp, fpsp->mpfps_length * 16) != 0) { + psm_unmap_phys(fptr, MPFPS_ROM_WIN_LEN); + return (retval); + } + + apic_spec_rev = fpsp->mpfps_spec_rev; + if ((apic_spec_rev != 04) && (apic_spec_rev != 01)) { + psm_unmap_phys(fptr, MPFPS_ROM_WIN_LEN); + return (retval); + } + + /* check IMCR is present or not */ + apic_imcrp = fpsp->mpfps_featinfo2 & MPFPS_FEATINFO2_IMCRP; + + /* check default configuration (dual CPUs) */ + if ((apic_defconf = fpsp->mpfps_featinfo1) != 0) { + psm_unmap_phys(fptr, mapsize); + return (apic_handle_defconf()); + } + + /* MP Configuration Table */ + mpct_addr = (uint32_t)(fpsp->mpfps_mpct_paddr); + + psm_unmap_phys(fptr, mapsize); /* unmap floating ptr struct */ + + /* + * Map in enough memory for the MP Configuration Table Header. + * Use this table to read the total length of the BIOS data and + * map in all the info + */ + /*LINTED: pointer cast may result in improper alignment */ + hdrp = (struct apic_mp_cnf_hdr *)psm_map_phys(mpct_addr, + sizeof (struct apic_mp_cnf_hdr), PROT_READ); + if (!hdrp) + return (retval); + + /* check mp configuration table signature PCMP */ + if (hdrp->mpcnf_sig != 0x504d4350) { + psm_unmap_phys((caddr_t)hdrp, sizeof (struct apic_mp_cnf_hdr)); + return (retval); + } + mpct_size = (int)hdrp->mpcnf_tbl_length; + + apic_set_pwroff_method_from_mpcnfhdr(hdrp); + + psm_unmap_phys((caddr_t)hdrp, sizeof (struct apic_mp_cnf_hdr)); + + if ((retval == PSM_SUCCESS) && !apic_use_acpi_madt_only) { + /* This is an ACPI machine No need for further checks */ + return (retval); + } + + /* + * Map in the entries for this machine, ie. Processor + * Entry Tables, Bus Entry Tables, etc. + * They are in fixed order following one another + */ + mpct = psm_map_phys(mpct_addr, mpct_size, PROT_READ); + if (!mpct) + return (retval); + + if (apic_checksum(mpct, mpct_size) != 0) + goto apic_fail1; + + + /*LINTED: pointer cast may result in improper alignment */ + hdrp = (struct apic_mp_cnf_hdr *)mpct; + apicadr = (uint32_t *)mapin_apic((uint32_t)hdrp->mpcnf_local_apic, + APIC_LOCAL_MEMLEN, PROT_READ | PROT_WRITE); + if (!apicadr) + goto apic_fail1; + + /* Parse all information in the tables */ + bypass_cpu_and_ioapics_in_mptables = (retval == PSM_SUCCESS); + if (apic_parse_mpct(mpct, bypass_cpu_and_ioapics_in_mptables) == + PSM_SUCCESS) + return (PSM_SUCCESS); + + for (i = 0; i < apic_io_max; i++) + mapout_ioapic((caddr_t)apicioadr[i], APIC_IO_MEMLEN); + if (apic_cpus) + kmem_free(apic_cpus, apic_cpus_size); + if (apicadr) + mapout_apic((caddr_t)apicadr, APIC_LOCAL_MEMLEN); +apic_fail1: + psm_unmap_phys(mpct, mpct_size); + return (retval); +} + +static void +apic_set_pwroff_method_from_mpcnfhdr(struct apic_mp_cnf_hdr *hdrp) +{ + int i; + + for (i = 0; i < (sizeof (apic_mps_ids) / sizeof (apic_mps_ids[0])); + i++) { + if ((strncmp(hdrp->mpcnf_oem_str, apic_mps_ids[i].oem_id, + strlen(apic_mps_ids[i].oem_id)) == 0) && + (strncmp(hdrp->mpcnf_prod_str, apic_mps_ids[i].prod_id, + strlen(apic_mps_ids[i].prod_id)) == 0)) { + + apic_poweroff_method = apic_mps_ids[i].poweroff_method; + break; + } + } + + if (apic_debug_mps_id != 0) { + cmn_err(CE_CONT, "%s: MPS OEM ID = '%c%c%c%c%c%c%c%c'" + "Product ID = '%c%c%c%c%c%c%c%c%c%c%c%c'\n", + psm_name, + hdrp->mpcnf_oem_str[0], + hdrp->mpcnf_oem_str[1], + hdrp->mpcnf_oem_str[2], + hdrp->mpcnf_oem_str[3], + hdrp->mpcnf_oem_str[4], + hdrp->mpcnf_oem_str[5], + hdrp->mpcnf_oem_str[6], + hdrp->mpcnf_oem_str[7], + hdrp->mpcnf_prod_str[0], + hdrp->mpcnf_prod_str[1], + hdrp->mpcnf_prod_str[2], + hdrp->mpcnf_prod_str[3], + hdrp->mpcnf_prod_str[4], + hdrp->mpcnf_prod_str[5], + hdrp->mpcnf_prod_str[6], + hdrp->mpcnf_prod_str[7], + hdrp->mpcnf_prod_str[8], + hdrp->mpcnf_prod_str[9], + hdrp->mpcnf_prod_str[10], + hdrp->mpcnf_prod_str[11]); + } +} + +static int +acpi_probe(char *modname) +{ + int i, intmax, index, rv; + uint32_t id, ver; + int acpi_verboseflags = 0; + int madt_seen, madt_size; + APIC_HEADER *ap; + MADT_PROCESSOR_APIC *mpa; + MADT_IO_APIC *mia; + MADT_IO_SAPIC *misa; + MADT_INTERRUPT_OVERRIDE *mio; + MADT_NMI_SOURCE *mns; + MADT_INTERRUPT_SOURCE *mis; + MADT_LOCAL_APIC_NMI *mlan; + MADT_ADDRESS_OVERRIDE *mao; + ACPI_OBJECT_LIST arglist; + ACPI_OBJECT arg; + int sci; + iflag_t sci_flags; + volatile uint32_t *ioapic; + int apic_ix; + char local_ids[NCPU]; + char proc_ids[NCPU]; + uchar_t hid; + + if (!apic_use_acpi) + return (PSM_FAILURE); + + if (AcpiGetFirmwareTable(APIC_SIG, 1, ACPI_LOGICAL_ADDRESSING, + (ACPI_TABLE_HEADER **) &acpi_mapic_dtp) != AE_OK) + return (PSM_FAILURE); + + apicadr = mapin_apic((uint32_t)acpi_mapic_dtp->LocalApicAddress, + APIC_LOCAL_MEMLEN, PROT_READ | PROT_WRITE); + if (!apicadr) + return (PSM_FAILURE); + + id = apicadr[APIC_LID_REG]; + local_ids[0] = (uchar_t)(id >> 24); + apic_nproc = index = 1; + CPUSET_ONLY(apic_cpumask, 0); + apic_io_max = 0; + + ap = (APIC_HEADER *) (acpi_mapic_dtp + 1); + madt_size = acpi_mapic_dtp->Length; + madt_seen = sizeof (*acpi_mapic_dtp); + + while (madt_seen < madt_size) { + switch (ap->Type) { + case APIC_PROCESSOR: + mpa = (MADT_PROCESSOR_APIC *) ap; + if (mpa->ProcessorEnabled) { + if (mpa->LocalApicId == local_ids[0]) + proc_ids[0] = mpa->ProcessorId; + else if (apic_nproc < NCPU) { + local_ids[index] = mpa->LocalApicId; + proc_ids[index] = mpa->ProcessorId; + CPUSET_ADD(apic_cpumask, index); + index++; + apic_nproc++; + } else + cmn_err(CE_WARN, "%s: exceeded " + "maximum no. of CPUs (= %d)", + psm_name, NCPU); + } + break; + + case APIC_IO: + mia = (MADT_IO_APIC *) ap; + if (apic_io_max < MAX_IO_APIC) { + apic_ix = apic_io_max; + apic_io_id[apic_io_max] = mia->IoApicId; + apic_io_vectbase[apic_io_max] = + mia->Interrupt; + apic_physaddr[apic_io_max] = + (uint32_t)mia->Address; + ioapic = apicioadr[apic_io_max] = + mapin_ioapic((uint32_t)mia->Address, + APIC_IO_MEMLEN, PROT_READ | PROT_WRITE); + if (!ioapic) + goto cleanup; + apic_io_max++; + } + break; + + case APIC_XRUPT_OVERRIDE: + mio = (MADT_INTERRUPT_OVERRIDE *) ap; + if (acpi_isop == NULL) + acpi_isop = mio; + acpi_iso_cnt++; + break; + + case APIC_NMI: + /* UNIMPLEMENTED */ + mns = (MADT_NMI_SOURCE *) ap; + if (acpi_nmi_sp == NULL) + acpi_nmi_sp = mns; + acpi_nmi_scnt++; + + cmn_err(CE_NOTE, "!apic: nmi source: %d %d %d\n", + mns->Interrupt, mns->Polarity, + mns->TriggerMode); + break; + + case APIC_LOCAL_NMI: + /* UNIMPLEMENTED */ + mlan = (MADT_LOCAL_APIC_NMI *) ap; + if (acpi_nmi_cp == NULL) + acpi_nmi_cp = mlan; + acpi_nmi_ccnt++; + + cmn_err(CE_NOTE, "!apic: local nmi: %d %d %d %d\n", + mlan->ProcessorId, mlan->Polarity, + mlan->TriggerMode, mlan->Lint); + break; + + case APIC_ADDRESS_OVERRIDE: + /* UNIMPLEMENTED */ + mao = (MADT_ADDRESS_OVERRIDE *) ap; + cmn_err(CE_NOTE, "!apic: address override: %lx\n", + (long)mao->Address); + break; + + case APIC_IO_SAPIC: + /* UNIMPLEMENTED */ + misa = (MADT_IO_SAPIC *) ap; + + cmn_err(CE_NOTE, "!apic: io sapic: %d %d %lx\n", + misa->IoSapicId, misa->InterruptBase, + (long)misa->Address); + break; + + case APIC_XRUPT_SOURCE: + /* UNIMPLEMENTED */ + mis = (MADT_INTERRUPT_SOURCE *) ap; + + cmn_err(CE_NOTE, + "!apic: irq source: %d %d %d %d %d %d %d\n", + mis->ProcessorId, mis->ProcessorEid, + mis->Interrupt, mis->Polarity, + mis->TriggerMode, mis->InterruptType, + mis->IoSapicVector); + break; + default: + break; + } + + /* advance to next entry */ + madt_seen += ap->Length; + ap = (APIC_HEADER *)(((char *)ap) + ap->Length); + } + + apic_cpus_size = apic_nproc * sizeof (*apic_cpus); + if ((apic_cpus = kmem_zalloc(apic_cpus_size, KM_NOSLEEP)) == NULL) + goto cleanup; + + /* + * ACPI doesn't provide the local apic ver, get it directly from the + * local apic + */ + ver = apicadr[APIC_VERS_REG]; + for (i = 0; i < apic_nproc; i++) { + apic_cpus[i].aci_local_id = local_ids[i]; + apic_cpus[i].aci_local_ver = (uchar_t)(ver & 0xFF); + } + for (i = 0; i < apic_io_max; i++) { + apic_ix = i; + + /* + * need to check Sitka on the following acpi problem + * On the Sitka, the ioapic's apic_id field isn't reporting + * the actual io apic id. We have reported this problem + * to Intel. Until they fix the problem, we will get the + * actual id directly from the ioapic. + */ + id = ioapic_read(apic_ix, APIC_ID_CMD); + hid = (uchar_t)(id >> 24); + + if (hid != apic_io_id[i]) { + if (apic_io_id[i] == 0) + apic_io_id[i] = hid; + else { /* set ioapic id to whatever reported by ACPI */ + id = ((uint32_t)apic_io_id[i]) << 24; + ioapic_write(apic_ix, APIC_ID_CMD, id); + } + } + ver = ioapic_read(apic_ix, APIC_VERS_CMD); + apic_io_ver[i] = (uchar_t)(ver & 0xff); + intmax = (ver >> 16) & 0xff; + apic_io_vectend[i] = apic_io_vectbase[i] + intmax; + if (apic_first_avail_irq <= apic_io_vectend[i]) + apic_first_avail_irq = apic_io_vectend[i] + 1; + } + + + /* + * Process SCI configuration here + * An error may be returned here if + * acpi-user-options specifies legacy mode + * (no SCI, no ACPI mode) + */ + if (acpica_get_sci(&sci, &sci_flags) != AE_OK) + sci = -1; + + /* + * Now call acpi_init() to generate namespaces + * If this fails, we don't attempt to use ACPI + * even if we were able to get a MADT above + */ + if (acpica_init() != AE_OK) + goto cleanup; + + /* + * Squirrel away the SCI and flags for later on + * in apic_picinit() when we're ready + */ + apic_sci_vect = sci; + apic_sci_flags = sci_flags; + + if (apic_verbose & APIC_VERBOSE_IRQ_FLAG) + acpi_verboseflags |= PSM_VERBOSE_IRQ_FLAG; + + if (apic_verbose & APIC_VERBOSE_POWEROFF_FLAG) + acpi_verboseflags |= PSM_VERBOSE_POWEROFF_FLAG; + + if (apic_verbose & APIC_VERBOSE_POWEROFF_PAUSE_FLAG) + acpi_verboseflags |= PSM_VERBOSE_POWEROFF_PAUSE_FLAG; + + if (acpi_psm_init(modname, acpi_verboseflags) == ACPI_PSM_FAILURE) + goto cleanup; + + /* Enable ACPI APIC interrupt routing */ + arglist.Count = 1; + arglist.Pointer = &arg; + arg.Type = ACPI_TYPE_INTEGER; + arg.Integer.Value = ACPI_APIC_MODE; /* 1 */ + rv = AcpiEvaluateObject(NULL, "\\_PIC", &arglist, NULL); + if (rv == AE_OK) { + build_reserved_irqlist((uchar_t *)apic_reserved_irqlist); + apic_enable_acpi = 1; + if (apic_use_acpi_madt_only) { + cmn_err(CE_CONT, + "?Using ACPI for CPU/IOAPIC information ONLY\n"); + } + return (PSM_SUCCESS); + } + /* if setting APIC mode failed above, we fall through to cleanup */ + +cleanup: + if (apicadr != NULL) { + mapout_apic((caddr_t)apicadr, APIC_LOCAL_MEMLEN); + apicadr = NULL; + } + apic_nproc = 0; + for (i = 0; i < apic_io_max; i++) { + mapout_ioapic((caddr_t)apicioadr[i], APIC_IO_MEMLEN); + apicioadr[i] = NULL; + } + apic_io_max = 0; + acpi_isop = NULL; + acpi_iso_cnt = 0; + acpi_nmi_sp = NULL; + acpi_nmi_scnt = 0; + acpi_nmi_cp = NULL; + acpi_nmi_ccnt = 0; + return (PSM_FAILURE); +} + +/* + * Handle default configuration. Fill in reqd global variables & tables + * Fill all details as MP table does not give any more info + */ +static int +apic_handle_defconf() +{ + uint_t lid; + + /*LINTED: pointer cast may result in improper alignment */ + apicioadr[0] = mapin_ioapic(APIC_IO_ADDR, + APIC_IO_MEMLEN, PROT_READ | PROT_WRITE); + /*LINTED: pointer cast may result in improper alignment */ + apicadr = (uint32_t *)psm_map_phys(APIC_LOCAL_ADDR, + APIC_LOCAL_MEMLEN, PROT_READ); + apic_cpus_size = 2 * sizeof (*apic_cpus); + apic_cpus = (apic_cpus_info_t *) + kmem_zalloc(apic_cpus_size, KM_NOSLEEP); + if ((!apicadr) || (!apicioadr[0]) || (!apic_cpus)) + goto apic_handle_defconf_fail; + CPUSET_ONLY(apic_cpumask, 0); + CPUSET_ADD(apic_cpumask, 1); + apic_nproc = 2; + lid = apicadr[APIC_LID_REG]; + apic_cpus[0].aci_local_id = (uchar_t)(lid >> APIC_ID_BIT_OFFSET); + /* + * According to the PC+MP spec 1.1, the local ids + * for the default configuration has to be 0 or 1 + */ + if (apic_cpus[0].aci_local_id == 1) + apic_cpus[1].aci_local_id = 0; + else if (apic_cpus[0].aci_local_id == 0) + apic_cpus[1].aci_local_id = 1; + else + goto apic_handle_defconf_fail; + + apic_io_id[0] = 2; + apic_io_max = 1; + if (apic_defconf >= 5) { + apic_cpus[0].aci_local_ver = APIC_INTEGRATED_VERS; + apic_cpus[1].aci_local_ver = APIC_INTEGRATED_VERS; + apic_io_ver[0] = APIC_INTEGRATED_VERS; + } else { + apic_cpus[0].aci_local_ver = 0; /* 82489 DX */ + apic_cpus[1].aci_local_ver = 0; + apic_io_ver[0] = 0; + } + if (apic_defconf == 2 || apic_defconf == 3 || apic_defconf == 6) + eisa_level_intr_mask = (inb(EISA_LEVEL_CNTL + 1) << 8) | + inb(EISA_LEVEL_CNTL) | ((uint_t)INT32_MAX + 1); + return (PSM_SUCCESS); + +apic_handle_defconf_fail: + if (apic_cpus) + kmem_free(apic_cpus, apic_cpus_size); + if (apicadr) + mapout_apic((caddr_t)apicadr, APIC_LOCAL_MEMLEN); + if (apicioadr[0]) + mapout_ioapic((caddr_t)apicioadr[0], APIC_IO_MEMLEN); + return (PSM_FAILURE); +} + +/* Parse the entries in MP configuration table and collect info that we need */ +static int +apic_parse_mpct(caddr_t mpct, int bypass_cpus_and_ioapics) +{ + struct apic_procent *procp; + struct apic_bus *busp; + struct apic_io_entry *ioapicp; + struct apic_io_intr *intrp; + int apic_ix; + uint_t lid; + uint32_t id; + uchar_t hid; + + /*LINTED: pointer cast may result in improper alignment */ + procp = (struct apic_procent *)(mpct + sizeof (struct apic_mp_cnf_hdr)); + + /* No need to count cpu entries if we won't use them */ + if (!bypass_cpus_and_ioapics) { + + /* Find max # of CPUS and allocate structure accordingly */ + apic_nproc = 0; + CPUSET_ZERO(apic_cpumask); + while (procp->proc_entry == APIC_CPU_ENTRY) { + if (procp->proc_cpuflags & CPUFLAGS_EN) { + if (apic_nproc < NCPU) + CPUSET_ADD(apic_cpumask, apic_nproc); + apic_nproc++; + } + procp++; + } + if (apic_nproc > NCPU) + cmn_err(CE_WARN, "%s: exceeded " + "maximum no. of CPUs (= %d)", psm_name, NCPU); + apic_cpus_size = apic_nproc * sizeof (*apic_cpus); + if (!apic_nproc || !(apic_cpus = (apic_cpus_info_t *) + kmem_zalloc(apic_cpus_size, KM_NOSLEEP))) + return (PSM_FAILURE); + } + + /*LINTED: pointer cast may result in improper alignment */ + procp = (struct apic_procent *)(mpct + sizeof (struct apic_mp_cnf_hdr)); + + /* + * start with index 1 as 0 needs to be filled in with Boot CPU, but + * if we're bypassing this information, it has already been filled + * in by acpi_probe(), so don't overwrite it. + */ + if (!bypass_cpus_and_ioapics) + apic_nproc = 1; + + while (procp->proc_entry == APIC_CPU_ENTRY) { + /* check whether the cpu exists or not */ + if (!bypass_cpus_and_ioapics && + procp->proc_cpuflags & CPUFLAGS_EN) { + if (procp->proc_cpuflags & CPUFLAGS_BP) { /* Boot CPU */ + lid = apicadr[APIC_LID_REG]; + apic_cpus[0].aci_local_id = procp->proc_apicid; + if (apic_cpus[0].aci_local_id != + (uchar_t)(lid >> APIC_ID_BIT_OFFSET)) { + return (PSM_FAILURE); + } + apic_cpus[0].aci_local_ver = + procp->proc_version; + } else { + + apic_cpus[apic_nproc].aci_local_id = + procp->proc_apicid; + apic_cpus[apic_nproc].aci_local_ver = + procp->proc_version; + apic_nproc++; + + } + } + procp++; + } + + /* + * Save start of bus entries for later use. + * Get EISA level cntrl if EISA bus is present. + * Also get the CPI bus id for single CPI bus case + */ + apic_busp = busp = (struct apic_bus *)procp; + while (busp->bus_entry == APIC_BUS_ENTRY) { + lid = apic_find_bus_type((char *)&busp->bus_str1); + if (lid == BUS_EISA) { + eisa_level_intr_mask = (inb(EISA_LEVEL_CNTL + 1) << 8) | + inb(EISA_LEVEL_CNTL) | ((uint_t)INT32_MAX + 1); + } else if (lid == BUS_PCI) { + /* + * apic_single_pci_busid will be used only if + * apic_pic_bus_total is equal to 1 + */ + apic_pci_bus_total++; + apic_single_pci_busid = busp->bus_id; + } + busp++; + } + + ioapicp = (struct apic_io_entry *)busp; + + if (!bypass_cpus_and_ioapics) + apic_io_max = 0; + do { + if (!bypass_cpus_and_ioapics && apic_io_max < MAX_IO_APIC) { + if (ioapicp->io_flags & IOAPIC_FLAGS_EN) { + apic_io_id[apic_io_max] = ioapicp->io_apicid; + apic_io_ver[apic_io_max] = ioapicp->io_version; + /*LINTED: pointer cast may result in improper alignment */ + apicioadr[apic_io_max] = + mapin_ioapic( + (uint32_t)ioapicp->io_apic_addr, + APIC_IO_MEMLEN, PROT_READ | PROT_WRITE); + + if (!apicioadr[apic_io_max]) + return (PSM_FAILURE); + + apic_ix = apic_io_max; + id = ioapic_read(apic_ix, APIC_ID_CMD); + hid = (uchar_t)(id >> 24); + + if (hid != apic_io_id[apic_io_max]) { + if (apic_io_id[apic_io_max] == 0) + apic_io_id[apic_io_max] = hid; + else { + /* + * set ioapic id to whatever + * reported by MPS + * + * may not need to set index + * again ??? + * take it out and try + */ + + id = ((uint32_t) + apic_io_id[apic_io_max]) << + 24; + + ioapic_write(apic_ix, + APIC_ID_CMD, id); + } + } + apic_io_max++; + } + } + ioapicp++; + } while (ioapicp->io_entry == APIC_IO_ENTRY); + + apic_io_intrp = (struct apic_io_intr *)ioapicp; + + intrp = apic_io_intrp; + while (intrp->intr_entry == APIC_IO_INTR_ENTRY) { + if ((intrp->intr_irq > APIC_MAX_ISA_IRQ) || + (apic_find_bus(intrp->intr_busid) == BUS_PCI)) { + apic_irq_translate = 1; + break; + } + intrp++; + } + + return (PSM_SUCCESS); +} + +boolean_t +apic_cpu_in_range(int cpu) +{ + return ((cpu & ~IRQ_USER_BOUND) < apic_nproc); +} + +static struct apic_mpfps_hdr * +apic_find_fps_sig(caddr_t cptr, int len) +{ + int i; + + /* Look for the pattern "_MP_" */ + for (i = 0; i < len; i += 16) { + if ((*(cptr+i) == '_') && + (*(cptr+i+1) == 'M') && + (*(cptr+i+2) == 'P') && + (*(cptr+i+3) == '_')) + /*LINTED: pointer cast may result in improper alignment */ + return ((struct apic_mpfps_hdr *)(cptr + i)); + } + return (NULL); +} + +static int +apic_checksum(caddr_t bptr, int len) +{ + int i; + uchar_t cksum; + + cksum = 0; + for (i = 0; i < len; i++) + cksum += *bptr++; + return ((int)cksum); +} + + +/* + * Initialise vector->ipl and ipl->pri arrays. level_intr and irqtable + * are also set to NULL. vector->irq is set to a value which cannot map + * to a real irq to show that it is free. + */ +void +apic_init_common() +{ + int i; + int *iptr; + + /* cpu 0 is always up */ + apic_cpus[0].aci_status = APIC_CPU_ONLINE | APIC_CPU_INTR_ENABLE; + + iptr = (int *)&apic_irq_table[0]; + for (i = 0; i <= APIC_MAX_VECTOR; i++) { + apic_level_intr[i] = 0; + *iptr++ = NULL; + apic_vector_to_irq[i] = APIC_RESV_IRQ; + + /* These *must* be initted to B_TRUE! */ + apic_reprogram_info[i].done = B_TRUE; + apic_reprogram_info[i].irqp = NULL; + apic_reprogram_info[i].tries = 0; + apic_reprogram_info[i].bindcpu = 0; + } + + /* + * Allocate a dummy irq table entry for the reserved entry. + * This takes care of the race between removing an irq and + * clock detecting a CPU in that irq during interrupt load + * sampling. + */ + apic_irq_table[APIC_RESV_IRQ] = + kmem_zalloc(sizeof (apic_irq_t), KM_NOSLEEP); + + mutex_init(&airq_mutex, NULL, MUTEX_DEFAULT, NULL); +} + +void +ioapic_init_intr(int mask_apic) +{ + int apic_ix; + struct intrspec ispec; + apic_irq_t *irqptr; + int i, j; + ulong_t iflag; + + LOCK_INIT_CLEAR(&apic_revector_lock); + LOCK_INIT_CLEAR(&apic_defer_reprogram_lock); + + /* mask interrupt vectors */ + for (j = 0; j < apic_io_max && mask_apic; j++) { + int intin_max; + + apic_ix = j; + /* Bits 23-16 define the maximum redirection entries */ + intin_max = (ioapic_read(apic_ix, APIC_VERS_CMD) >> 16) & 0xff; + for (i = 0; i < intin_max; i++) + ioapic_write(apic_ix, APIC_RDT_CMD + 2 * i, AV_MASK); + } + + /* + * Hack alert: deal with ACPI SCI interrupt chicken/egg here + */ + if (apic_sci_vect > 0) { + /* + * acpica has already done add_avintr(); we just + * to finish the job by mimicing translate_irq() + * + * Fake up an intrspec and setup the tables + */ + ispec.intrspec_vec = apic_sci_vect; + ispec.intrspec_pri = SCI_IPL; + + if (apic_setup_irq_table(NULL, apic_sci_vect, NULL, + &ispec, &apic_sci_flags, DDI_INTR_TYPE_FIXED) < 0) { + cmn_err(CE_WARN, "!apic: SCI setup failed"); + return; + } + irqptr = apic_irq_table[apic_sci_vect]; + + iflag = intr_clear(); + lock_set(&apic_ioapic_lock); + + /* Program I/O APIC */ + (void) apic_setup_io_intr(irqptr, apic_sci_vect, B_FALSE); + + lock_clear(&apic_ioapic_lock); + intr_restore(iflag); + + irqptr->airq_share++; + } +} + +/* + * Add mask bits to disable interrupt vector from happening + * at or above IPL. In addition, it should remove mask bits + * to enable interrupt vectors below the given IPL. + * + * Both add and delspl are complicated by the fact that different interrupts + * may share IRQs. This can happen in two ways. + * 1. The same H/W line is shared by more than 1 device + * 1a. with interrupts at different IPLs + * 1b. with interrupts at same IPL + * 2. We ran out of vectors at a given IPL and started sharing vectors. + * 1b and 2 should be handled gracefully, except for the fact some ISRs + * will get called often when no interrupt is pending for the device. + * For 1a, we just hope that the machine blows up with the person who + * set it up that way!. In the meantime, we handle it at the higher IPL. + */ +/*ARGSUSED*/ +int +apic_addspl_common(int irqno, int ipl, int min_ipl, int max_ipl) +{ + uchar_t vector; + ulong_t iflag; + apic_irq_t *irqptr, *irqheadptr; + int irqindex; + + ASSERT(max_ipl <= UCHAR_MAX); + irqindex = IRQINDEX(irqno); + + if ((irqindex == -1) || (!apic_irq_table[irqindex])) + return (PSM_FAILURE); + + mutex_enter(&airq_mutex); + irqptr = irqheadptr = apic_irq_table[irqindex]; + + DDI_INTR_IMPLDBG((CE_CONT, "apic_addspl: dip=0x%p type=%d irqno=0x%x " + "vector=0x%x\n", (void *)irqptr->airq_dip, + irqptr->airq_mps_intr_index, irqno, irqptr->airq_vector)); + + while (irqptr) { + if (VIRTIRQ(irqindex, irqptr->airq_share_id) == irqno) + break; + irqptr = irqptr->airq_next; + } + irqptr->airq_share++; + + mutex_exit(&airq_mutex); + + /* return if it is not hardware interrupt */ + if (irqptr->airq_mps_intr_index == RESERVE_INDEX) + return (PSM_SUCCESS); + + /* Or if there are more interupts at a higher IPL */ + if (ipl != max_ipl) + return (PSM_SUCCESS); + + /* + * if apic_picinit() has not been called yet, just return. + * At the end of apic_picinit(), we will call setup_io_intr(). + */ + + if (!apic_flag) + return (PSM_SUCCESS); + + /* + * Upgrade vector if max_ipl is not earlier ipl. If we cannot allocate, + * return failure. Not very elegant, but then we hope the + * machine will blow up with ... + */ + if (irqptr->airq_ipl != max_ipl) { + vector = apic_allocate_vector(max_ipl, irqindex, 1); + if (vector == 0) { + irqptr->airq_share--; + return (PSM_FAILURE); + } + irqptr = irqheadptr; + apic_mark_vector(irqptr->airq_vector, vector); + while (irqptr) { + irqptr->airq_vector = vector; + irqptr->airq_ipl = (uchar_t)max_ipl; + /* + * reprogram irq being added and every one else + * who is not in the UNINIT state + */ + if ((VIRTIRQ(irqindex, irqptr->airq_share_id) == + irqno) || (irqptr->airq_temp_cpu != IRQ_UNINIT)) { + apic_record_rdt_entry(irqptr, irqindex); + + iflag = intr_clear(); + lock_set(&apic_ioapic_lock); + + (void) apic_setup_io_intr(irqptr, irqindex, + B_FALSE); + + lock_clear(&apic_ioapic_lock); + intr_restore(iflag); + } + irqptr = irqptr->airq_next; + } + return (PSM_SUCCESS); + } + + ASSERT(irqptr); + + iflag = intr_clear(); + lock_set(&apic_ioapic_lock); + + (void) apic_setup_io_intr(irqptr, irqindex, B_FALSE); + + lock_clear(&apic_ioapic_lock); + intr_restore(iflag); + + return (PSM_SUCCESS); +} + +/* + * Recompute mask bits for the given interrupt vector. + * If there is no interrupt servicing routine for this + * vector, this function should disable interrupt vector + * from happening at all IPLs. If there are still + * handlers using the given vector, this function should + * disable the given vector from happening below the lowest + * IPL of the remaining hadlers. + */ +/*ARGSUSED*/ +int +apic_delspl_common(int irqno, int ipl, int min_ipl, int max_ipl) +{ + uchar_t vector, bind_cpu; + int intin, irqindex; + int apic_ix; + apic_irq_t *irqptr, *irqheadptr; + ulong_t iflag; + + mutex_enter(&airq_mutex); + irqindex = IRQINDEX(irqno); + irqptr = irqheadptr = apic_irq_table[irqindex]; + + DDI_INTR_IMPLDBG((CE_CONT, "apic_delspl: dip=0x%p type=%d irqno=0x%x " + "vector=0x%x\n", (void *)irqptr->airq_dip, + irqptr->airq_mps_intr_index, irqno, irqptr->airq_vector)); + + while (irqptr) { + if (VIRTIRQ(irqindex, irqptr->airq_share_id) == irqno) + break; + irqptr = irqptr->airq_next; + } + ASSERT(irqptr); + + irqptr->airq_share--; + + mutex_exit(&airq_mutex); + + if (ipl < max_ipl) + return (PSM_SUCCESS); + + /* return if it is not hardware interrupt */ + if (irqptr->airq_mps_intr_index == RESERVE_INDEX) + return (PSM_SUCCESS); + + if (!apic_flag) { + /* + * Clear irq_struct. If two devices shared an intpt + * line & 1 unloaded before picinit, we are hosed. But, then + * we hope the machine will ... + */ + irqptr->airq_mps_intr_index = FREE_INDEX; + irqptr->airq_temp_cpu = IRQ_UNINIT; + apic_free_vector(irqptr->airq_vector); + return (PSM_SUCCESS); + } + /* + * Downgrade vector to new max_ipl if needed.If we cannot allocate, + * use old IPL. Not very elegant, but then we hope ... + */ + if ((irqptr->airq_ipl != max_ipl) && (max_ipl != PSM_INVALID_IPL)) { + apic_irq_t *irqp; + if (vector = apic_allocate_vector(max_ipl, irqno, 1)) { + apic_mark_vector(irqheadptr->airq_vector, vector); + irqp = irqheadptr; + while (irqp) { + irqp->airq_vector = vector; + irqp->airq_ipl = (uchar_t)max_ipl; + if (irqp->airq_temp_cpu != IRQ_UNINIT) { + apic_record_rdt_entry(irqp, irqindex); + + iflag = intr_clear(); + lock_set(&apic_ioapic_lock); + + (void) apic_setup_io_intr(irqp, + irqindex, B_FALSE); + + lock_clear(&apic_ioapic_lock); + intr_restore(iflag); + } + irqp = irqp->airq_next; + } + } + } + + if (irqptr->airq_share) + return (PSM_SUCCESS); + + iflag = intr_clear(); + lock_set(&apic_ioapic_lock); + + /* Disable the MSI/X vector */ + if (APIC_IS_MSI_OR_MSIX_INDEX(irqptr->airq_mps_intr_index)) { + int type = (irqptr->airq_mps_intr_index == MSI_INDEX) ? + DDI_INTR_TYPE_MSI : DDI_INTR_TYPE_MSIX; + + /* + * Make sure we only disable on the last + * of the multi-MSI support + */ + if (i_ddi_intr_get_current_nintrs(irqptr->airq_dip) == 1) { + (void) apic_pci_msi_unconfigure(irqptr->airq_dip, + type, irqptr->airq_ioapicindex); + + (void) apic_pci_msi_disable_mode(irqptr->airq_dip, + type, irqptr->airq_ioapicindex); + } + } else { + apic_ix = irqptr->airq_ioapicindex; + intin = irqptr->airq_intin_no; + ioapic_write(apic_ix, APIC_RDT_CMD + 2 * intin, AV_MASK); + } + + if (max_ipl == PSM_INVALID_IPL) { + ASSERT(irqheadptr == irqptr); + bind_cpu = irqptr->airq_temp_cpu; + if (((uchar_t)bind_cpu != IRQ_UNBOUND) && + ((uchar_t)bind_cpu != IRQ_UNINIT)) { + ASSERT((bind_cpu & ~IRQ_USER_BOUND) < apic_nproc); + if (bind_cpu & IRQ_USER_BOUND) { + /* If hardbound, temp_cpu == cpu */ + bind_cpu &= ~IRQ_USER_BOUND; + apic_cpus[bind_cpu].aci_bound--; + } else + apic_cpus[bind_cpu].aci_temp_bound--; + } + irqptr->airq_temp_cpu = IRQ_UNINIT; + irqptr->airq_mps_intr_index = FREE_INDEX; + lock_clear(&apic_ioapic_lock); + intr_restore(iflag); + apic_free_vector(irqptr->airq_vector); + return (PSM_SUCCESS); + } + lock_clear(&apic_ioapic_lock); + intr_restore(iflag); + + mutex_enter(&airq_mutex); + if ((irqptr == apic_irq_table[irqindex])) { + apic_irq_t *oldirqptr; + /* Move valid irq entry to the head */ + irqheadptr = oldirqptr = irqptr; + irqptr = irqptr->airq_next; + ASSERT(irqptr); + while (irqptr) { + if (irqptr->airq_mps_intr_index != FREE_INDEX) + break; + oldirqptr = irqptr; + irqptr = irqptr->airq_next; + } + /* remove all invalid ones from the beginning */ + apic_irq_table[irqindex] = irqptr; + /* + * and link them back after the head. The invalid ones + * begin with irqheadptr and end at oldirqptr + */ + oldirqptr->airq_next = irqptr->airq_next; + irqptr->airq_next = irqheadptr; + } + mutex_exit(&airq_mutex); + + irqptr->airq_temp_cpu = IRQ_UNINIT; + irqptr->airq_mps_intr_index = FREE_INDEX; + + return (PSM_SUCCESS); +} + +/* + * apic_introp_xlate() replaces apic_translate_irq() and is + * called only from apic_intr_ops(). With the new ADII framework, + * the priority can no longer be retrieved through i_ddi_get_intrspec(). + * It has to be passed in from the caller. + */ +int +apic_introp_xlate(dev_info_t *dip, struct intrspec *ispec, int type) +{ + char dev_type[16]; + int dev_len, pci_irq, newirq, bustype, devid, busid, i; + int irqno = ispec->intrspec_vec; + ddi_acc_handle_t cfg_handle; + uchar_t ipin; + struct apic_io_intr *intrp; + iflag_t intr_flag; + APIC_HEADER *hp; + MADT_INTERRUPT_OVERRIDE *isop; + apic_irq_t *airqp; + int parent_is_pci_or_pciex = 0; + int child_is_pciex = 0; + + DDI_INTR_IMPLDBG((CE_CONT, "apic_introp_xlate: dip=0x%p name=%s " + "type=%d irqno=0x%x\n", (void *)dip, ddi_get_name(dip), type, + irqno)); + + dev_len = sizeof (dev_type); + if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ddi_get_parent(dip), + DDI_PROP_DONTPASS, "device_type", (caddr_t)dev_type, + &dev_len) == DDI_PROP_SUCCESS) { + if ((strcmp(dev_type, "pci") == 0) || + (strcmp(dev_type, "pciex") == 0)) + parent_is_pci_or_pciex = 1; + } + + if (parent_is_pci_or_pciex && ddi_prop_get_int(DDI_DEV_T_ANY, dip, + DDI_PROP_DONTPASS, "pcie-capid-pointer", PCI_CAP_NEXT_PTR_NULL) != + PCI_CAP_NEXT_PTR_NULL) { + child_is_pciex = 1; + } + + if (DDI_INTR_IS_MSI_OR_MSIX(type)) { + if ((airqp = apic_find_irq(dip, ispec, type)) != NULL) { + airqp->airq_iflag.bustype = + child_is_pciex ? BUS_PCIE : BUS_PCI; + return (apic_vector_to_irq[airqp->airq_vector]); + } + return (apic_setup_irq_table(dip, irqno, NULL, ispec, + NULL, type)); + } + + bustype = 0; + + /* check if we have already translated this irq */ + mutex_enter(&airq_mutex); + newirq = apic_min_device_irq; + for (; newirq <= apic_max_device_irq; newirq++) { + airqp = apic_irq_table[newirq]; + while (airqp) { + if ((airqp->airq_dip == dip) && + (airqp->airq_origirq == irqno) && + (airqp->airq_mps_intr_index != FREE_INDEX)) { + + mutex_exit(&airq_mutex); + return (VIRTIRQ(newirq, airqp->airq_share_id)); + } + airqp = airqp->airq_next; + } + } + mutex_exit(&airq_mutex); + + if (apic_defconf) + goto defconf; + + if ((dip == NULL) || (!apic_irq_translate && !apic_enable_acpi)) + goto nonpci; + + if (parent_is_pci_or_pciex) { + /* pci device */ + if (acpica_get_bdf(dip, &busid, &devid, NULL) != 0) + goto nonpci; + if (busid == 0 && apic_pci_bus_total == 1) + busid = (int)apic_single_pci_busid; + + if (pci_config_setup(dip, &cfg_handle) != DDI_SUCCESS) + goto nonpci; + ipin = pci_config_get8(cfg_handle, PCI_CONF_IPIN) - PCI_INTA; + pci_config_teardown(&cfg_handle); + if (apic_enable_acpi && !apic_use_acpi_madt_only) { + if (apic_acpi_translate_pci_irq(dip, busid, devid, + ipin, &pci_irq, &intr_flag) != ACPI_PSM_SUCCESS) + goto nonpci; + + intr_flag.bustype = child_is_pciex ? BUS_PCIE : BUS_PCI; + if ((newirq = apic_setup_irq_table(dip, pci_irq, NULL, + ispec, &intr_flag, type)) == -1) + goto nonpci; + return (newirq); + } else { + pci_irq = ((devid & 0x1f) << 2) | (ipin & 0x3); + if ((intrp = apic_find_io_intr_w_busid(pci_irq, busid)) + == NULL) { + if ((pci_irq = apic_handle_pci_pci_bridge(dip, + devid, ipin, &intrp)) == -1) + goto nonpci; + } + if ((newirq = apic_setup_irq_table(dip, pci_irq, intrp, + ispec, NULL, type)) == -1) + goto nonpci; + return (newirq); + } + } else if (strcmp(dev_type, "isa") == 0) + bustype = BUS_ISA; + else if (strcmp(dev_type, "eisa") == 0) + bustype = BUS_EISA; + +nonpci: + if (apic_enable_acpi && !apic_use_acpi_madt_only) { + /* search iso entries first */ + if (acpi_iso_cnt != 0) { + hp = (APIC_HEADER *)acpi_isop; + i = 0; + while (i < acpi_iso_cnt) { + if (hp->Type == APIC_XRUPT_OVERRIDE) { + isop = (MADT_INTERRUPT_OVERRIDE *)hp; + if (isop->Bus == 0 && + isop->Source == irqno) { + newirq = isop->Interrupt; + intr_flag.intr_po = + isop->Polarity; + intr_flag.intr_el = + isop->TriggerMode; + intr_flag.bustype = BUS_ISA; + + return (apic_setup_irq_table( + dip, newirq, NULL, ispec, + &intr_flag, type)); + + } + i++; + } + hp = (APIC_HEADER *)(((char *)hp) + + hp->Length); + } + } + intr_flag.intr_po = INTR_PO_ACTIVE_HIGH; + intr_flag.intr_el = INTR_EL_EDGE; + intr_flag.bustype = BUS_ISA; + return (apic_setup_irq_table(dip, irqno, NULL, ispec, + &intr_flag, type)); + } else { + if (bustype == 0) + bustype = eisa_level_intr_mask ? BUS_EISA : BUS_ISA; + for (i = 0; i < 2; i++) { + if (((busid = apic_find_bus_id(bustype)) != -1) && + ((intrp = apic_find_io_intr_w_busid(irqno, busid)) + != NULL)) { + if ((newirq = apic_setup_irq_table(dip, irqno, + intrp, ispec, NULL, type)) != -1) { + return (newirq); + } + goto defconf; + } + bustype = (bustype == BUS_EISA) ? BUS_ISA : BUS_EISA; + } + } + +/* MPS default configuration */ +defconf: + newirq = apic_setup_irq_table(dip, irqno, NULL, ispec, NULL, type); + if (newirq == -1) + return (newirq); + ASSERT(IRQINDEX(newirq) == irqno); + ASSERT(apic_irq_table[irqno]); + return (newirq); +} + + + + + + +/* + * On machines with PCI-PCI bridges, a device behind a PCI-PCI bridge + * needs special handling. We may need to chase up the device tree, + * using the PCI-PCI Bridge specification's "rotating IPIN assumptions", + * to find the IPIN at the root bus that relates to the IPIN on the + * subsidiary bus (for ACPI or MP). We may, however, have an entry + * in the MP table or the ACPI namespace for this device itself. + * We handle both cases in the search below. + */ +/* this is the non-acpi version */ +static int +apic_handle_pci_pci_bridge(dev_info_t *idip, int child_devno, int child_ipin, + struct apic_io_intr **intrp) +{ + dev_info_t *dipp, *dip; + int pci_irq; + ddi_acc_handle_t cfg_handle; + int bridge_devno, bridge_bus; + int ipin; + + dip = idip; + + /*CONSTCOND*/ + while (1) { + if ((dipp = ddi_get_parent(dip)) == (dev_info_t *)NULL) + return (-1); + if ((pci_config_setup(dipp, &cfg_handle) == DDI_SUCCESS) && + (pci_config_get8(cfg_handle, PCI_CONF_BASCLASS) == + PCI_CLASS_BRIDGE) && (pci_config_get8(cfg_handle, + PCI_CONF_SUBCLASS) == PCI_BRIDGE_PCI)) { + pci_config_teardown(&cfg_handle); + if (acpica_get_bdf(dipp, &bridge_bus, &bridge_devno, + NULL) != 0) + return (-1); + /* + * This is the rotating scheme that Compaq is using + * and documented in the pci to pci spec. Also, if + * the pci to pci bridge is behind another pci to + * pci bridge, then it need to keep transversing + * up until an interrupt entry is found or reach + * the top of the tree + */ + ipin = (child_devno + child_ipin) % PCI_INTD; + if (bridge_bus == 0 && apic_pci_bus_total == 1) + bridge_bus = (int)apic_single_pci_busid; + pci_irq = ((bridge_devno & 0x1f) << 2) | + (ipin & 0x3); + if ((*intrp = apic_find_io_intr_w_busid(pci_irq, + bridge_bus)) != NULL) { + return (pci_irq); + } + dip = dipp; + child_devno = bridge_devno; + child_ipin = ipin; + } else + return (-1); + } + /*LINTED: function will not fall off the bottom */ +} + + + + +static uchar_t +acpi_find_ioapic(int irq) +{ + int i; + + for (i = 0; i < apic_io_max; i++) { + if (irq >= apic_io_vectbase[i] && irq <= apic_io_vectend[i]) + return (i); + } + return (0xFF); /* shouldn't happen */ +} + +/* + * See if two irqs are compatible for sharing a vector. + * Currently we only support sharing of PCI devices. + */ +static int +acpi_intr_compatible(iflag_t iflag1, iflag_t iflag2) +{ + uint_t level1, po1; + uint_t level2, po2; + + /* Assume active high by default */ + po1 = 0; + po2 = 0; + + if (iflag1.bustype != iflag2.bustype || iflag1.bustype != BUS_PCI) + return (0); + + if (iflag1.intr_el == INTR_EL_CONFORM) + level1 = AV_LEVEL; + else + level1 = (iflag1.intr_el == INTR_EL_LEVEL) ? AV_LEVEL : 0; + + if (level1 && ((iflag1.intr_po == INTR_PO_ACTIVE_LOW) || + (iflag1.intr_po == INTR_PO_CONFORM))) + po1 = AV_ACTIVE_LOW; + + if (iflag2.intr_el == INTR_EL_CONFORM) + level2 = AV_LEVEL; + else + level2 = (iflag2.intr_el == INTR_EL_LEVEL) ? AV_LEVEL : 0; + + if (level2 && ((iflag2.intr_po == INTR_PO_ACTIVE_LOW) || + (iflag2.intr_po == INTR_PO_CONFORM))) + po2 = AV_ACTIVE_LOW; + + if ((level1 == level2) && (po1 == po2)) + return (1); + + return (0); +} + +/* + * Attempt to share vector with someone else + */ +static int +apic_share_vector(int irqno, iflag_t *intr_flagp, short intr_index, int ipl, + uchar_t ioapicindex, uchar_t ipin, apic_irq_t **irqptrp) +{ +#ifdef DEBUG + apic_irq_t *tmpirqp = NULL; +#endif /* DEBUG */ + apic_irq_t *irqptr, dummyirq; + int newirq, chosen_irq = -1, share = 127; + int lowest, highest, i; + uchar_t share_id; + + DDI_INTR_IMPLDBG((CE_CONT, "apic_share_vector: irqno=0x%x " + "intr_index=0x%x ipl=0x%x\n", irqno, intr_index, ipl)); + + highest = apic_ipltopri[ipl] + APIC_VECTOR_MASK; + lowest = apic_ipltopri[ipl-1] + APIC_VECTOR_PER_IPL; + + if (highest < lowest) /* Both ipl and ipl-1 map to same pri */ + lowest -= APIC_VECTOR_PER_IPL; + dummyirq.airq_mps_intr_index = intr_index; + dummyirq.airq_ioapicindex = ioapicindex; + dummyirq.airq_intin_no = ipin; + if (intr_flagp) + dummyirq.airq_iflag = *intr_flagp; + apic_record_rdt_entry(&dummyirq, irqno); + for (i = lowest; i <= highest; i++) { + newirq = apic_vector_to_irq[i]; + if (newirq == APIC_RESV_IRQ) + continue; + irqptr = apic_irq_table[newirq]; + + if ((dummyirq.airq_rdt_entry & 0xFF00) != + (irqptr->airq_rdt_entry & 0xFF00)) + /* not compatible */ + continue; + + if (irqptr->airq_share < share) { + share = irqptr->airq_share; + chosen_irq = newirq; + } + } + if (chosen_irq != -1) { + /* + * Assign a share id which is free or which is larger + * than the largest one. + */ + share_id = 1; + mutex_enter(&airq_mutex); + irqptr = apic_irq_table[chosen_irq]; + while (irqptr) { + if (irqptr->airq_mps_intr_index == FREE_INDEX) { + share_id = irqptr->airq_share_id; + break; + } + if (share_id <= irqptr->airq_share_id) + share_id = irqptr->airq_share_id + 1; +#ifdef DEBUG + tmpirqp = irqptr; +#endif /* DEBUG */ + irqptr = irqptr->airq_next; + } + if (!irqptr) { + irqptr = kmem_zalloc(sizeof (apic_irq_t), KM_SLEEP); + irqptr->airq_temp_cpu = IRQ_UNINIT; + irqptr->airq_next = + apic_irq_table[chosen_irq]->airq_next; + apic_irq_table[chosen_irq]->airq_next = irqptr; +#ifdef DEBUG + tmpirqp = apic_irq_table[chosen_irq]; +#endif /* DEBUG */ + } + irqptr->airq_mps_intr_index = intr_index; + irqptr->airq_ioapicindex = ioapicindex; + irqptr->airq_intin_no = ipin; + if (intr_flagp) + irqptr->airq_iflag = *intr_flagp; + irqptr->airq_vector = apic_irq_table[chosen_irq]->airq_vector; + irqptr->airq_share_id = share_id; + apic_record_rdt_entry(irqptr, irqno); + *irqptrp = irqptr; +#ifdef DEBUG + /* shuffle the pointers to test apic_delspl path */ + if (tmpirqp) { + tmpirqp->airq_next = irqptr->airq_next; + irqptr->airq_next = apic_irq_table[chosen_irq]; + apic_irq_table[chosen_irq] = irqptr; + } +#endif /* DEBUG */ + mutex_exit(&airq_mutex); + return (VIRTIRQ(chosen_irq, share_id)); + } + return (-1); +} + +/* + * + */ +static int +apic_setup_irq_table(dev_info_t *dip, int irqno, struct apic_io_intr *intrp, + struct intrspec *ispec, iflag_t *intr_flagp, int type) +{ + int origirq = ispec->intrspec_vec; + uchar_t ipl = ispec->intrspec_pri; + int newirq, intr_index; + uchar_t ipin, ioapic, ioapicindex, vector; + apic_irq_t *irqptr; + major_t major; + dev_info_t *sdip; + + DDI_INTR_IMPLDBG((CE_CONT, "apic_setup_irq_table: dip=0x%p type=%d " + "irqno=0x%x origirq=0x%x\n", (void *)dip, type, irqno, origirq)); + + ASSERT(ispec != NULL); + + major = (dip != NULL) ? ddi_name_to_major(ddi_get_name(dip)) : 0; + + if (DDI_INTR_IS_MSI_OR_MSIX(type)) { + /* MSI/X doesn't need to setup ioapic stuffs */ + ioapicindex = 0xff; + ioapic = 0xff; + ipin = (uchar_t)0xff; + intr_index = (type == DDI_INTR_TYPE_MSI) ? MSI_INDEX : + MSIX_INDEX; + mutex_enter(&airq_mutex); + if ((irqno = apic_allocate_irq(apic_first_avail_irq)) == -1) { + mutex_exit(&airq_mutex); + /* need an irq for MSI/X to index into autovect[] */ + cmn_err(CE_WARN, "No interrupt irq: %s instance %d", + ddi_get_name(dip), ddi_get_instance(dip)); + return (-1); + } + mutex_exit(&airq_mutex); + + } else if (intrp != NULL) { + intr_index = (int)(intrp - apic_io_intrp); + ioapic = intrp->intr_destid; + ipin = intrp->intr_destintin; + /* Find ioapicindex. If destid was ALL, we will exit with 0. */ + for (ioapicindex = apic_io_max - 1; ioapicindex; ioapicindex--) + if (apic_io_id[ioapicindex] == ioapic) + break; + ASSERT((ioapic == apic_io_id[ioapicindex]) || + (ioapic == INTR_ALL_APIC)); + + /* check whether this intin# has been used by another irqno */ + if ((newirq = apic_find_intin(ioapicindex, ipin)) != -1) { + return (newirq); + } + + } else if (intr_flagp != NULL) { + /* ACPI case */ + intr_index = ACPI_INDEX; + ioapicindex = acpi_find_ioapic(irqno); + ASSERT(ioapicindex != 0xFF); + ioapic = apic_io_id[ioapicindex]; + ipin = irqno - apic_io_vectbase[ioapicindex]; + if (apic_irq_table[irqno] && + apic_irq_table[irqno]->airq_mps_intr_index == ACPI_INDEX) { + ASSERT(apic_irq_table[irqno]->airq_intin_no == ipin && + apic_irq_table[irqno]->airq_ioapicindex == + ioapicindex); + return (irqno); + } + + } else { + /* default configuration */ + ioapicindex = 0; + ioapic = apic_io_id[ioapicindex]; + ipin = (uchar_t)irqno; + intr_index = DEFAULT_INDEX; + } + + if (ispec == NULL) { + APIC_VERBOSE_IOAPIC((CE_WARN, "No intrspec for irqno = %x\n", + irqno)); + } else if ((vector = apic_allocate_vector(ipl, irqno, 0)) == 0) { + if ((newirq = apic_share_vector(irqno, intr_flagp, intr_index, + ipl, ioapicindex, ipin, &irqptr)) != -1) { + irqptr->airq_ipl = ipl; + irqptr->airq_origirq = (uchar_t)origirq; + irqptr->airq_dip = dip; + irqptr->airq_major = major; + sdip = apic_irq_table[IRQINDEX(newirq)]->airq_dip; + /* This is OK to do really */ + if (sdip == NULL) { + cmn_err(CE_WARN, "Sharing vectors: %s" + " instance %d and SCI", + ddi_get_name(dip), ddi_get_instance(dip)); + } else { + cmn_err(CE_WARN, "Sharing vectors: %s" + " instance %d and %s instance %d", + ddi_get_name(sdip), ddi_get_instance(sdip), + ddi_get_name(dip), ddi_get_instance(dip)); + } + return (newirq); + } + /* try high priority allocation now that share has failed */ + if ((vector = apic_allocate_vector(ipl, irqno, 1)) == 0) { + cmn_err(CE_WARN, "No interrupt vector: %s instance %d", + ddi_get_name(dip), ddi_get_instance(dip)); + return (-1); + } + } + + mutex_enter(&airq_mutex); + if (apic_irq_table[irqno] == NULL) { + irqptr = kmem_zalloc(sizeof (apic_irq_t), KM_SLEEP); + irqptr->airq_temp_cpu = IRQ_UNINIT; + apic_irq_table[irqno] = irqptr; + } else { + irqptr = apic_irq_table[irqno]; + if (irqptr->airq_mps_intr_index != FREE_INDEX) { + /* + * The slot is used by another irqno, so allocate + * a free irqno for this interrupt + */ + newirq = apic_allocate_irq(apic_first_avail_irq); + if (newirq == -1) { + mutex_exit(&airq_mutex); + return (-1); + } + irqno = newirq; + irqptr = apic_irq_table[irqno]; + if (irqptr == NULL) { + irqptr = kmem_zalloc(sizeof (apic_irq_t), + KM_SLEEP); + irqptr->airq_temp_cpu = IRQ_UNINIT; + apic_irq_table[irqno] = irqptr; + } + vector = apic_modify_vector(vector, newirq); + } + } + apic_max_device_irq = max(irqno, apic_max_device_irq); + apic_min_device_irq = min(irqno, apic_min_device_irq); + mutex_exit(&airq_mutex); + irqptr->airq_ioapicindex = ioapicindex; + irqptr->airq_intin_no = ipin; + irqptr->airq_ipl = ipl; + irqptr->airq_vector = vector; + irqptr->airq_origirq = (uchar_t)origirq; + irqptr->airq_share_id = 0; + irqptr->airq_mps_intr_index = (short)intr_index; + irqptr->airq_dip = dip; + irqptr->airq_major = major; + irqptr->airq_cpu = apic_bind_intr(dip, irqno, ioapic, ipin); + if (intr_flagp) + irqptr->airq_iflag = *intr_flagp; + + if (!DDI_INTR_IS_MSI_OR_MSIX(type)) { + /* setup I/O APIC entry for non-MSI/X interrupts */ + apic_record_rdt_entry(irqptr, irqno); + } + return (irqno); +} + +/* + * return the cpu to which this intr should be bound. + * Check properties or any other mechanism to see if user wants it + * bound to a specific CPU. If so, return the cpu id with high bit set. + * If not, use the policy to choose a cpu and return the id. + */ +uchar_t +apic_bind_intr(dev_info_t *dip, int irq, uchar_t ioapicid, uchar_t intin) +{ + int instance, instno, prop_len, bind_cpu, count; + uint_t i, rc; + uchar_t cpu; + major_t major; + char *name, *drv_name, *prop_val, *cptr; + char prop_name[32]; + + + if (apic_intr_policy == INTR_LOWEST_PRIORITY) + return (IRQ_UNBOUND); + + drv_name = NULL; + rc = DDI_PROP_NOT_FOUND; + major = (major_t)-1; + if (dip != NULL) { + name = ddi_get_name(dip); + major = ddi_name_to_major(name); + drv_name = ddi_major_to_name(major); + instance = ddi_get_instance(dip); + if (apic_intr_policy == INTR_ROUND_ROBIN_WITH_AFFINITY) { + i = apic_min_device_irq; + for (; i <= apic_max_device_irq; i++) { + + if ((i == irq) || (apic_irq_table[i] == NULL) || + (apic_irq_table[i]->airq_mps_intr_index + == FREE_INDEX)) + continue; + + if ((apic_irq_table[i]->airq_major == major) && + (!(apic_irq_table[i]->airq_cpu & + IRQ_USER_BOUND))) { + + cpu = apic_irq_table[i]->airq_cpu; + + cmn_err(CE_CONT, + "!%s: %s (%s) instance #%d " + "vector 0x%x ioapic 0x%x " + "intin 0x%x is bound to cpu %d\n", + psm_name, + name, drv_name, instance, irq, + ioapicid, intin, cpu); + return (cpu); + } + } + } + /* + * search for "drvname"_intpt_bind_cpus property first, the + * syntax of the property should be "a[,b,c,...]" where + * instance 0 binds to cpu a, instance 1 binds to cpu b, + * instance 3 binds to cpu c... + * ddi_getlongprop() will search /option first, then / + * if "drvname"_intpt_bind_cpus doesn't exist, then find + * intpt_bind_cpus property. The syntax is the same, and + * it applies to all the devices if its "drvname" specific + * property doesn't exist + */ + (void) strcpy(prop_name, drv_name); + (void) strcat(prop_name, "_intpt_bind_cpus"); + rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, 0, prop_name, + (caddr_t)&prop_val, &prop_len); + if (rc != DDI_PROP_SUCCESS) { + rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, 0, + "intpt_bind_cpus", (caddr_t)&prop_val, &prop_len); + } + } + if (rc == DDI_PROP_SUCCESS) { + for (i = count = 0; i < (prop_len - 1); i++) + if (prop_val[i] == ',') + count++; + if (prop_val[i-1] != ',') + count++; + /* + * if somehow the binding instances defined in the + * property are not enough for this instno., then + * reuse the pattern for the next instance until + * it reaches the requested instno + */ + instno = instance % count; + i = 0; + cptr = prop_val; + while (i < instno) + if (*cptr++ == ',') + i++; + bind_cpu = stoi(&cptr); + kmem_free(prop_val, prop_len); + /* if specific cpu is bogus, then default to cpu 0 */ + if (bind_cpu >= apic_nproc) { + cmn_err(CE_WARN, "%s: %s=%s: CPU %d not present", + psm_name, prop_name, prop_val, bind_cpu); + bind_cpu = 0; + } else { + /* indicate that we are bound at user request */ + bind_cpu |= IRQ_USER_BOUND; + } + /* + * no need to check apic_cpus[].aci_status, if specific cpu is + * not up, then post_cpu_start will handle it. + */ + } else { + bind_cpu = apic_next_bind_cpu++; + if (bind_cpu >= apic_nproc) { + apic_next_bind_cpu = 1; + bind_cpu = 0; + } + } + if (drv_name != NULL) + cmn_err(CE_CONT, "!%s: %s (%s) instance %d " + "vector 0x%x ioapic 0x%x intin 0x%x is bound to cpu %d\n", + psm_name, name, drv_name, instance, + irq, ioapicid, intin, bind_cpu & ~IRQ_USER_BOUND); + else + cmn_err(CE_CONT, "!%s: " + "vector 0x%x ioapic 0x%x intin 0x%x is bound to cpu %d\n", + psm_name, irq, ioapicid, intin, bind_cpu & ~IRQ_USER_BOUND); + + return ((uchar_t)bind_cpu); +} + +static struct apic_io_intr * +apic_find_io_intr_w_busid(int irqno, int busid) +{ + struct apic_io_intr *intrp; + + /* + * It can have more than 1 entry with same source bus IRQ, + * but unique with the source bus id + */ + intrp = apic_io_intrp; + if (intrp != NULL) { + while (intrp->intr_entry == APIC_IO_INTR_ENTRY) { + if (intrp->intr_irq == irqno && + intrp->intr_busid == busid && + intrp->intr_type == IO_INTR_INT) + return (intrp); + intrp++; + } + } + APIC_VERBOSE_IOAPIC((CE_NOTE, "Did not find io intr for irqno:" + "busid %x:%x\n", irqno, busid)); + return ((struct apic_io_intr *)NULL); +} + + +struct mps_bus_info { + char *bus_name; + int bus_id; +} bus_info_array[] = { + "ISA ", BUS_ISA, + "PCI ", BUS_PCI, + "EISA ", BUS_EISA, + "XPRESS", BUS_XPRESS, + "PCMCIA", BUS_PCMCIA, + "VL ", BUS_VL, + "CBUS ", BUS_CBUS, + "CBUSII", BUS_CBUSII, + "FUTURE", BUS_FUTURE, + "INTERN", BUS_INTERN, + "MBI ", BUS_MBI, + "MBII ", BUS_MBII, + "MPI ", BUS_MPI, + "MPSA ", BUS_MPSA, + "NUBUS ", BUS_NUBUS, + "TC ", BUS_TC, + "VME ", BUS_VME, + "PCI-E ", BUS_PCIE +}; + +static int +apic_find_bus_type(char *bus) +{ + int i = 0; + + for (; i < sizeof (bus_info_array)/sizeof (struct mps_bus_info); i++) + if (strncmp(bus, bus_info_array[i].bus_name, + strlen(bus_info_array[i].bus_name)) == 0) + return (bus_info_array[i].bus_id); + APIC_VERBOSE_IOAPIC((CE_WARN, "Did not find bus type for bus %s", bus)); + return (0); +} + +static int +apic_find_bus(int busid) +{ + struct apic_bus *busp; + + busp = apic_busp; + while (busp->bus_entry == APIC_BUS_ENTRY) { + if (busp->bus_id == busid) + return (apic_find_bus_type((char *)&busp->bus_str1)); + busp++; + } + APIC_VERBOSE_IOAPIC((CE_WARN, "Did not find bus for bus id %x", busid)); + return (0); +} + +static int +apic_find_bus_id(int bustype) +{ + struct apic_bus *busp; + + busp = apic_busp; + while (busp->bus_entry == APIC_BUS_ENTRY) { + if (apic_find_bus_type((char *)&busp->bus_str1) == bustype) + return (busp->bus_id); + busp++; + } + APIC_VERBOSE_IOAPIC((CE_WARN, "Did not find bus id for bustype %x", + bustype)); + return (-1); +} + +/* + * Check if a particular irq need to be reserved for any io_intr + */ +static struct apic_io_intr * +apic_find_io_intr(int irqno) +{ + struct apic_io_intr *intrp; + + intrp = apic_io_intrp; + if (intrp != NULL) { + while (intrp->intr_entry == APIC_IO_INTR_ENTRY) { + if (intrp->intr_irq == irqno && + intrp->intr_type == IO_INTR_INT) + return (intrp); + intrp++; + } + } + return ((struct apic_io_intr *)NULL); +} + +/* + * Check if the given ioapicindex intin combination has already been assigned + * an irq. If so return irqno. Else -1 + */ +static int +apic_find_intin(uchar_t ioapic, uchar_t intin) +{ + apic_irq_t *irqptr; + int i; + + /* find ioapic and intin in the apic_irq_table[] and return the index */ + for (i = apic_min_device_irq; i <= apic_max_device_irq; i++) { + irqptr = apic_irq_table[i]; + while (irqptr) { + if ((irqptr->airq_mps_intr_index >= 0) && + (irqptr->airq_intin_no == intin) && + (irqptr->airq_ioapicindex == ioapic)) { + APIC_VERBOSE_IOAPIC((CE_NOTE, "!Found irq " + "entry for ioapic:intin %x:%x " + "shared interrupts ?", ioapic, intin)); + return (i); + } + irqptr = irqptr->airq_next; + } + } + return (-1); +} + +int +apic_allocate_irq(int irq) +{ + int freeirq, i; + + if ((freeirq = apic_find_free_irq(irq, (APIC_RESV_IRQ - 1))) == -1) + if ((freeirq = apic_find_free_irq(APIC_FIRST_FREE_IRQ, + (irq - 1))) == -1) { + /* + * if BIOS really defines every single irq in the mps + * table, then don't worry about conflicting with + * them, just use any free slot in apic_irq_table + */ + for (i = APIC_FIRST_FREE_IRQ; i < APIC_RESV_IRQ; i++) { + if ((apic_irq_table[i] == NULL) || + apic_irq_table[i]->airq_mps_intr_index == + FREE_INDEX) { + freeirq = i; + break; + } + } + if (freeirq == -1) { + /* This shouldn't happen, but just in case */ + cmn_err(CE_WARN, "%s: NO available IRQ", psm_name); + return (-1); + } + } + if (apic_irq_table[freeirq] == NULL) { + apic_irq_table[freeirq] = + kmem_zalloc(sizeof (apic_irq_t), KM_NOSLEEP); + if (apic_irq_table[freeirq] == NULL) { + cmn_err(CE_WARN, "%s: NO memory to allocate IRQ", + psm_name); + return (-1); + } + apic_irq_table[freeirq]->airq_mps_intr_index = FREE_INDEX; + } + return (freeirq); +} + +static int +apic_find_free_irq(int start, int end) +{ + int i; + + for (i = start; i <= end; i++) + /* Check if any I/O entry needs this IRQ */ + if (apic_find_io_intr(i) == NULL) { + /* Then see if it is free */ + if ((apic_irq_table[i] == NULL) || + (apic_irq_table[i]->airq_mps_intr_index == + FREE_INDEX)) { + return (i); + } + } + return (-1); +} + + +/* + * Mark vector as being in the process of being deleted. Interrupts + * may still come in on some CPU. The moment an interrupt comes with + * the new vector, we know we can free the old one. Called only from + * addspl and delspl with interrupts disabled. Because an interrupt + * can be shared, but no interrupt from either device may come in, + * we also use a timeout mechanism, which we arbitrarily set to + * apic_revector_timeout microseconds. + */ +static void +apic_mark_vector(uchar_t oldvector, uchar_t newvector) +{ + ulong_t iflag; + + iflag = intr_clear(); + lock_set(&apic_revector_lock); + if (!apic_oldvec_to_newvec) { + apic_oldvec_to_newvec = + kmem_zalloc(sizeof (newvector) * APIC_MAX_VECTOR * 2, + KM_NOSLEEP); + + if (!apic_oldvec_to_newvec) { + /* + * This failure is not catastrophic. + * But, the oldvec will never be freed. + */ + apic_error |= APIC_ERR_MARK_VECTOR_FAIL; + lock_clear(&apic_revector_lock); + intr_restore(iflag); + return; + } + apic_newvec_to_oldvec = &apic_oldvec_to_newvec[APIC_MAX_VECTOR]; + } + + /* See if we already did this for drivers which do double addintrs */ + if (apic_oldvec_to_newvec[oldvector] != newvector) { + apic_oldvec_to_newvec[oldvector] = newvector; + apic_newvec_to_oldvec[newvector] = oldvector; + apic_revector_pending++; + } + lock_clear(&apic_revector_lock); + intr_restore(iflag); + (void) timeout(apic_xlate_vector_free_timeout_handler, + (void *)(uintptr_t)oldvector, drv_usectohz(apic_revector_timeout)); +} + +/* + * xlate_vector is called from intr_enter if revector_pending is set. + * It will xlate it if needed and mark the old vector as free. + */ +uchar_t +apic_xlate_vector(uchar_t vector) +{ + uchar_t newvector, oldvector = 0; + + lock_set(&apic_revector_lock); + /* Do we really need to do this ? */ + if (!apic_revector_pending) { + lock_clear(&apic_revector_lock); + return (vector); + } + if ((newvector = apic_oldvec_to_newvec[vector]) != 0) + oldvector = vector; + else { + /* + * The incoming vector is new . See if a stale entry is + * remaining + */ + if ((oldvector = apic_newvec_to_oldvec[vector]) != 0) + newvector = vector; + } + + if (oldvector) { + apic_revector_pending--; + apic_oldvec_to_newvec[oldvector] = 0; + apic_newvec_to_oldvec[newvector] = 0; + apic_free_vector(oldvector); + lock_clear(&apic_revector_lock); + /* There could have been more than one reprogramming! */ + return (apic_xlate_vector(newvector)); + } + lock_clear(&apic_revector_lock); + return (vector); +} + +void +apic_xlate_vector_free_timeout_handler(void *arg) +{ + ulong_t iflag; + uchar_t oldvector, newvector; + + oldvector = (uchar_t)(uintptr_t)arg; + iflag = intr_clear(); + lock_set(&apic_revector_lock); + if ((newvector = apic_oldvec_to_newvec[oldvector]) != 0) { + apic_free_vector(oldvector); + apic_oldvec_to_newvec[oldvector] = 0; + apic_newvec_to_oldvec[newvector] = 0; + apic_revector_pending--; + } + + lock_clear(&apic_revector_lock); + intr_restore(iflag); +} + + +/* + * compute the polarity, trigger mode and vector for programming into + * the I/O apic and record in airq_rdt_entry. + */ +static void +apic_record_rdt_entry(apic_irq_t *irqptr, int irq) +{ + int ioapicindex, bus_type, vector; + short intr_index; + uint_t level, po, io_po; + struct apic_io_intr *iointrp; + + intr_index = irqptr->airq_mps_intr_index; + DDI_INTR_IMPLDBG((CE_CONT, "apic_record_rdt_entry: intr_index=%d " + "irq = 0x%x dip = 0x%p vector = 0x%x\n", intr_index, irq, + (void *)irqptr->airq_dip, irqptr->airq_vector)); + + if (intr_index == RESERVE_INDEX) { + apic_error |= APIC_ERR_INVALID_INDEX; + return; + } else if (APIC_IS_MSI_OR_MSIX_INDEX(intr_index)) { + return; + } + + vector = irqptr->airq_vector; + ioapicindex = irqptr->airq_ioapicindex; + /* Assume edge triggered by default */ + level = 0; + /* Assume active high by default */ + po = 0; + + if (intr_index == DEFAULT_INDEX || intr_index == FREE_INDEX) { + ASSERT(irq < 16); + if (eisa_level_intr_mask & (1 << irq)) + level = AV_LEVEL; + if (intr_index == FREE_INDEX && apic_defconf == 0) + apic_error |= APIC_ERR_INVALID_INDEX; + } else if (intr_index == ACPI_INDEX) { + bus_type = irqptr->airq_iflag.bustype; + if (irqptr->airq_iflag.intr_el == INTR_EL_CONFORM) { + if (bus_type == BUS_PCI) + level = AV_LEVEL; + } else + level = (irqptr->airq_iflag.intr_el == INTR_EL_LEVEL) ? + AV_LEVEL : 0; + if (level && + ((irqptr->airq_iflag.intr_po == INTR_PO_ACTIVE_LOW) || + (irqptr->airq_iflag.intr_po == INTR_PO_CONFORM && + bus_type == BUS_PCI))) + po = AV_ACTIVE_LOW; + } else { + iointrp = apic_io_intrp + intr_index; + bus_type = apic_find_bus(iointrp->intr_busid); + if (iointrp->intr_el == INTR_EL_CONFORM) { + if ((irq < 16) && (eisa_level_intr_mask & (1 << irq))) + level = AV_LEVEL; + else if (bus_type == BUS_PCI) + level = AV_LEVEL; + } else + level = (iointrp->intr_el == INTR_EL_LEVEL) ? + AV_LEVEL : 0; + if (level && ((iointrp->intr_po == INTR_PO_ACTIVE_LOW) || + (iointrp->intr_po == INTR_PO_CONFORM && + bus_type == BUS_PCI))) + po = AV_ACTIVE_LOW; + } + if (level) + apic_level_intr[irq] = 1; + /* + * The 82489DX External APIC cannot do active low polarity interrupts. + */ + if (po && (apic_io_ver[ioapicindex] != IOAPIC_VER_82489DX)) + io_po = po; + else + io_po = 0; + + if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) + printf("setio: ioapic=%x intin=%x level=%x po=%x vector=%x\n", + ioapicindex, irqptr->airq_intin_no, level, io_po, vector); + + irqptr->airq_rdt_entry = level|io_po|vector; +} + +/* + * Bind interrupt corresponding to irq_ptr to bind_cpu. + * Must be called with interrupts disabled and apic_ioapic_lock held + */ +int +apic_rebind(apic_irq_t *irq_ptr, int bind_cpu, + struct ioapic_reprogram_data *drep) +{ + int ioapicindex, intin_no; + uchar_t airq_temp_cpu; + apic_cpus_info_t *cpu_infop; + uint32_t rdt_entry; + int which_irq; + + which_irq = apic_vector_to_irq[irq_ptr->airq_vector]; + + intin_no = irq_ptr->airq_intin_no; + ioapicindex = irq_ptr->airq_ioapicindex; + airq_temp_cpu = irq_ptr->airq_temp_cpu; + if (airq_temp_cpu != IRQ_UNINIT && airq_temp_cpu != IRQ_UNBOUND) { + if (airq_temp_cpu & IRQ_USER_BOUND) + /* Mask off high bit so it can be used as array index */ + airq_temp_cpu &= ~IRQ_USER_BOUND; + + ASSERT(airq_temp_cpu < apic_nproc); + } + + /* + * Can't bind to a CPU that's not accepting interrupts: + */ + cpu_infop = &apic_cpus[bind_cpu & ~IRQ_USER_BOUND]; + if (!(cpu_infop->aci_status & APIC_CPU_INTR_ENABLE)) + return (1); + + /* + * If we are about to change the interrupt vector for this interrupt, + * and this interrupt is level-triggered, attached to an IOAPIC, + * has been delivered to a CPU and that CPU has not handled it + * yet, we cannot reprogram the IOAPIC now. + */ + if (!APIC_IS_MSI_OR_MSIX_INDEX(irq_ptr->airq_mps_intr_index)) { + + rdt_entry = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapicindex, + intin_no); + + if ((irq_ptr->airq_vector != RDT_VECTOR(rdt_entry)) && + apic_check_stuck_interrupt(irq_ptr, airq_temp_cpu, + bind_cpu, ioapicindex, intin_no, which_irq, drep) != 0) { + + return (0); + } + } + + /* + * NOTE: We do not unmask the RDT here, as an interrupt MAY still + * come in before we have a chance to reprogram it below. The + * reprogramming below will simultaneously change and unmask the + * RDT entry. + */ + + if ((uchar_t)bind_cpu == IRQ_UNBOUND) { + + rdt_entry = AV_LDEST | AV_LOPRI | irq_ptr->airq_rdt_entry; + + /* Write the RDT entry -- no specific CPU binding */ + WRITE_IOAPIC_RDT_ENTRY_HIGH_DWORD(ioapicindex, intin_no, + AV_TOALL); + + if (airq_temp_cpu != IRQ_UNINIT && airq_temp_cpu != IRQ_UNBOUND) + apic_cpus[airq_temp_cpu].aci_temp_bound--; + + /* Write the vector, trigger, and polarity portion of the RDT */ + WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapicindex, intin_no, + rdt_entry); + + irq_ptr->airq_temp_cpu = IRQ_UNBOUND; + return (0); + } + + if (bind_cpu & IRQ_USER_BOUND) { + cpu_infop->aci_bound++; + } else { + cpu_infop->aci_temp_bound++; + } + ASSERT((bind_cpu & ~IRQ_USER_BOUND) < apic_nproc); + if (!APIC_IS_MSI_OR_MSIX_INDEX(irq_ptr->airq_mps_intr_index)) { + /* Write the RDT entry -- bind to a specific CPU: */ + WRITE_IOAPIC_RDT_ENTRY_HIGH_DWORD(ioapicindex, intin_no, + cpu_infop->aci_local_id << APIC_ID_BIT_OFFSET); + } + if ((airq_temp_cpu != IRQ_UNBOUND) && (airq_temp_cpu != IRQ_UNINIT)) { + apic_cpus[airq_temp_cpu].aci_temp_bound--; + } + if (!APIC_IS_MSI_OR_MSIX_INDEX(irq_ptr->airq_mps_intr_index)) { + + rdt_entry = AV_PDEST | AV_FIXED | irq_ptr->airq_rdt_entry; + + /* Write the vector, trigger, and polarity portion of the RDT */ + WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapicindex, intin_no, + rdt_entry); + + } else { + int type = (irq_ptr->airq_mps_intr_index == MSI_INDEX) ? + DDI_INTR_TYPE_MSI : DDI_INTR_TYPE_MSIX; + (void) apic_pci_msi_disable_mode(irq_ptr->airq_dip, type, + ioapicindex); + if (ioapicindex == irq_ptr->airq_origirq) { + /* first one */ + DDI_INTR_IMPLDBG((CE_CONT, "apic_rebind: call " + "apic_pci_msi_enable_vector\n")); + if (apic_pci_msi_enable_vector(irq_ptr->airq_dip, type, + which_irq, irq_ptr->airq_vector, + irq_ptr->airq_intin_no, + cpu_infop->aci_local_id) != PSM_SUCCESS) { + cmn_err(CE_WARN, "pcplusmp: " + "apic_pci_msi_enable_vector " + "returned PSM_FAILURE"); + } + } + if ((ioapicindex + irq_ptr->airq_intin_no - 1) == + irq_ptr->airq_origirq) { /* last one */ + DDI_INTR_IMPLDBG((CE_CONT, "apic_rebind: call " + "pci_msi_enable_mode\n")); + if (apic_pci_msi_enable_mode(irq_ptr->airq_dip, + type, which_irq) != PSM_SUCCESS) { + DDI_INTR_IMPLDBG((CE_CONT, "pcplusmp: " + "pci_msi_enable failed\n")); + (void) apic_pci_msi_unconfigure( + irq_ptr->airq_dip, type, which_irq); + } + } + } + irq_ptr->airq_temp_cpu = (uchar_t)bind_cpu; + apic_redist_cpu_skip &= ~(1 << (bind_cpu & ~IRQ_USER_BOUND)); + return (0); +} + +static void +apic_last_ditch_clear_remote_irr(int ioapic_ix, int intin_no) +{ + if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, intin_no) + & AV_REMOTE_IRR) != 0) { + /* + * Trying to clear the bit through normal + * channels has failed. So as a last-ditch + * effort, try to set the trigger mode to + * edge, then to level. This has been + * observed to work on many systems. + */ + WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, + intin_no, + READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, + intin_no) & ~AV_LEVEL); + + WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, + intin_no, + READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, + intin_no) | AV_LEVEL); + + /* + * If the bit's STILL set, this interrupt may + * be hosed. + */ + if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, + intin_no) & AV_REMOTE_IRR) != 0) { + + prom_printf("%s: Remote IRR still " + "not clear for IOAPIC %d intin %d.\n" + "\tInterrupts to this pin may cease " + "functioning.\n", psm_name, ioapic_ix, + intin_no); +#ifdef DEBUG + apic_last_ditch_reprogram_failures++; +#endif + } + } +} + +/* + * This function is protected by apic_ioapic_lock coupled with the + * fact that interrupts are disabled. + */ +static void +delete_defer_repro_ent(int which_irq) +{ + ASSERT(which_irq >= 0); + ASSERT(which_irq <= 255); + + if (apic_reprogram_info[which_irq].done) + return; + + apic_reprogram_info[which_irq].done = B_TRUE; + +#ifdef DEBUG + apic_defer_repro_total_retries += + apic_reprogram_info[which_irq].tries; + + apic_defer_repro_successes++; +#endif + + if (--apic_reprogram_outstanding == 0) { + + setlvlx = apic_intr_exit; + } +} + + +/* + * Interrupts must be disabled during this function to prevent + * self-deadlock. Interrupts are disabled because this function + * is called from apic_check_stuck_interrupt(), which is called + * from apic_rebind(), which requires its caller to disable interrupts. + */ +static void +add_defer_repro_ent(apic_irq_t *irq_ptr, int which_irq, int new_bind_cpu) +{ + ASSERT(which_irq >= 0); + ASSERT(which_irq <= 255); + + /* + * On the off-chance that there's already a deferred + * reprogramming on this irq, check, and if so, just update the + * CPU and irq pointer to which the interrupt is targeted, then return. + */ + if (!apic_reprogram_info[which_irq].done) { + apic_reprogram_info[which_irq].bindcpu = new_bind_cpu; + apic_reprogram_info[which_irq].irqp = irq_ptr; + return; + } + + apic_reprogram_info[which_irq].irqp = irq_ptr; + apic_reprogram_info[which_irq].bindcpu = new_bind_cpu; + apic_reprogram_info[which_irq].tries = 0; + /* + * This must be the last thing set, since we're not + * grabbing any locks, apic_try_deferred_reprogram() will + * make its decision about using this entry iff done + * is false. + */ + apic_reprogram_info[which_irq].done = B_FALSE; + + /* + * If there were previously no deferred reprogrammings, change + * setlvlx to call apic_try_deferred_reprogram() + */ + if (++apic_reprogram_outstanding == 1) { + + setlvlx = apic_try_deferred_reprogram; + } +} + +static void +apic_try_deferred_reprogram(int prev_ipl, int irq) +{ + int reproirq, iflag; + struct ioapic_reprogram_data *drep; + + apic_intr_exit(prev_ipl, irq); + + if (!lock_try(&apic_defer_reprogram_lock)) { + return; + } + + /* + * Acquire the apic_ioapic_lock so that any other operations that + * may affect the apic_reprogram_info state are serialized. + * It's still possible for the last deferred reprogramming to clear + * between the time we entered this function and the time we get to + * the for loop below. In that case, *setlvlx will have been set + * back to apic_intr_exit and drep will be NULL. (There's no way to + * stop that from happening -- we would need to grab a lock before + * calling *setlvlx, which is neither realistic nor prudent). + */ + iflag = intr_clear(); + lock_set(&apic_ioapic_lock); + + /* + * For each deferred RDT entry, try to reprogram it now. Note that + * there is no lock acquisition to read apic_reprogram_info because + * '.done' is set only after the other fields in the structure are set. + */ + + drep = NULL; + for (reproirq = 0; reproirq <= APIC_MAX_VECTOR; reproirq++) { + if (apic_reprogram_info[reproirq].done == B_FALSE) { + drep = &apic_reprogram_info[reproirq]; + break; + } + } + + /* + * Either we found a deferred action to perform, or + * we entered this function spuriously, after *setlvlx + * was restored to point to apic_intr_enter. Any other + * permutation is invalid. + */ + ASSERT(drep != NULL || *setlvlx == apic_intr_exit); + + /* + * Though we can't really do anything about errors + * at this point, keep track of them for reporting. + * Note that it is very possible for apic_setup_io_intr + * to re-register this very timeout if the Remote IRR bit + * has not yet cleared. + */ + +#ifdef DEBUG + if (drep != NULL) { + if (apic_setup_io_intr(drep, reproirq, B_TRUE) != 0) { + apic_deferred_setup_failures++; + } + } else { + apic_deferred_spurious_enters++; + } +#else + if (drep != NULL) + (void) apic_setup_io_intr(drep, reproirq, B_TRUE); +#endif + + lock_clear(&apic_ioapic_lock); + intr_restore(iflag); + + lock_clear(&apic_defer_reprogram_lock); +} + +static void +apic_ioapic_wait_pending_clear(int ioapic_ix, int intin_no) +{ + int waited; + + /* + * Wait for the delivery pending bit to clear. + */ + if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, intin_no) & + (AV_LEVEL|AV_PENDING)) == (AV_LEVEL|AV_PENDING)) { + + /* + * If we're still waiting on the delivery of this interrupt, + * continue to wait here until it is delivered (this should be + * a very small amount of time, but include a timeout just in + * case). + */ + for (waited = 0; waited < apic_max_reps_clear_pending; + waited++) { + if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, + intin_no) & AV_PENDING) == 0) { + break; + } + } + } +} + + +/* + * Checks to see if the IOAPIC interrupt entry specified has its Remote IRR + * bit set. Calls functions that modify the function that setlvlx points to, + * so that the reprogramming can be retried very shortly. + * + * This function will mask the RDT entry if the interrupt is level-triggered. + * (The caller is responsible for unmasking the RDT entry.) + * + * Returns non-zero if the caller should defer IOAPIC reprogramming. + */ +static int +apic_check_stuck_interrupt(apic_irq_t *irq_ptr, int old_bind_cpu, + int new_bind_cpu, int ioapic_ix, int intin_no, int which_irq, + struct ioapic_reprogram_data *drep) +{ + int32_t rdt_entry; + int waited; + int reps = 0; + + /* + * Wait for the delivery pending bit to clear. + */ + do { + ++reps; + + apic_ioapic_wait_pending_clear(ioapic_ix, intin_no); + + /* + * Mask the RDT entry, but only if it's a level-triggered + * interrupt + */ + rdt_entry = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, + intin_no); + if ((rdt_entry & (AV_LEVEL|AV_MASK)) == AV_LEVEL) { + + /* Mask it */ + WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, intin_no, + AV_MASK | rdt_entry); + } + + if ((rdt_entry & AV_LEVEL) == AV_LEVEL) { + /* + * If there was a race and an interrupt was injected + * just before we masked, check for that case here. + * Then, unmask the RDT entry and try again. If we're + * on our last try, don't unmask (because we want the + * RDT entry to remain masked for the rest of the + * function). + */ + rdt_entry = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, + intin_no); + if ((rdt_entry & AV_PENDING) && + (reps < apic_max_reps_clear_pending)) { + /* Unmask it */ + WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, + intin_no, rdt_entry & ~AV_MASK); + } + } + + } while ((rdt_entry & AV_PENDING) && + (reps < apic_max_reps_clear_pending)); + +#ifdef DEBUG + if (rdt_entry & AV_PENDING) + apic_intr_deliver_timeouts++; +#endif + + /* + * If the remote IRR bit is set, then the interrupt has been sent + * to a CPU for processing. We have no choice but to wait for + * that CPU to process the interrupt, at which point the remote IRR + * bit will be cleared. + */ + if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, intin_no) & + (AV_LEVEL|AV_REMOTE_IRR)) == (AV_LEVEL|AV_REMOTE_IRR)) { + + /* + * If the CPU that this RDT is bound to is NOT the current + * CPU, wait until that CPU handles the interrupt and ACKs + * it. If this interrupt is not bound to any CPU (that is, + * if it's bound to the logical destination of "anyone"), it + * may have been delivered to the current CPU so handle that + * case by deferring the reprogramming (below). + */ + if ((old_bind_cpu != IRQ_UNBOUND) && + (old_bind_cpu != IRQ_UNINIT) && + (old_bind_cpu != psm_get_cpu_id())) { + for (waited = 0; waited < apic_max_reps_clear_pending; + waited++) { + if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, + intin_no) & AV_REMOTE_IRR) == 0) { + + delete_defer_repro_ent(which_irq); + + /* Remote IRR has cleared! */ + return (0); + } + } + } + + /* + * If we waited and the Remote IRR bit is still not cleared, + * AND if we've invoked the timeout APIC_REPROGRAM_MAX_TIMEOUTS + * times for this interrupt, try the last-ditch workaround: + */ + if (drep && drep->tries >= APIC_REPROGRAM_MAX_TRIES) { + + apic_last_ditch_clear_remote_irr(ioapic_ix, intin_no); + + /* Mark this one as reprogrammed: */ + delete_defer_repro_ent(which_irq); + + return (0); + } else { +#ifdef DEBUG + apic_intr_deferrals++; +#endif + + /* + * If waiting for the Remote IRR bit (above) didn't + * allow it to clear, defer the reprogramming. + * Add a new deferred-programming entry if the + * caller passed a NULL one (and update the existing one + * in case anything changed). + */ + add_defer_repro_ent(irq_ptr, which_irq, new_bind_cpu); + if (drep) + drep->tries++; + + /* Inform caller to defer IOAPIC programming: */ + return (1); + } + + } + + /* Remote IRR is clear */ + delete_defer_repro_ent(which_irq); + + return (0); +} + +/* + * Called to migrate all interrupts at an irq to another cpu. + * Must be called with interrupts disabled and apic_ioapic_lock held + */ +int +apic_rebind_all(apic_irq_t *irq_ptr, int bind_cpu) +{ + apic_irq_t *irqptr = irq_ptr; + int retval = 0; + + while (irqptr) { + if (irqptr->airq_temp_cpu != IRQ_UNINIT) + retval |= apic_rebind(irqptr, bind_cpu, NULL); + irqptr = irqptr->airq_next; + } + + return (retval); +} + +/* + * apic_intr_redistribute does all the messy computations for identifying + * which interrupt to move to which CPU. Currently we do just one interrupt + * at a time. This reduces the time we spent doing all this within clock + * interrupt. When it is done in idle, we could do more than 1. + * First we find the most busy and the most free CPU (time in ISR only) + * skipping those CPUs that has been identified as being ineligible (cpu_skip) + * Then we look for IRQs which are closest to the difference between the + * most busy CPU and the average ISR load. We try to find one whose load + * is less than difference.If none exists, then we chose one larger than the + * difference, provided it does not make the most idle CPU worse than the + * most busy one. In the end, we clear all the busy fields for CPUs. For + * IRQs, they are cleared as they are scanned. + */ +void +apic_intr_redistribute() +{ + int busiest_cpu, most_free_cpu; + int cpu_free, cpu_busy, max_busy, min_busy; + int min_free, diff; + int average_busy, cpus_online; + int i, busy, iflag; + apic_cpus_info_t *cpu_infop; + apic_irq_t *min_busy_irq = NULL; + apic_irq_t *max_busy_irq = NULL; + + busiest_cpu = most_free_cpu = -1; + cpu_free = cpu_busy = max_busy = average_busy = 0; + min_free = apic_sample_factor_redistribution; + cpus_online = 0; + /* + * Below we will check for CPU_INTR_ENABLE, bound, temp_bound, temp_cpu + * without ioapic_lock. That is OK as we are just doing statistical + * sampling anyway and any inaccuracy now will get corrected next time + * The call to rebind which actually changes things will make sure + * we are consistent. + */ + for (i = 0; i < apic_nproc; i++) { + if (!(apic_redist_cpu_skip & (1 << i)) && + (apic_cpus[i].aci_status & APIC_CPU_INTR_ENABLE)) { + + cpu_infop = &apic_cpus[i]; + /* + * If no unbound interrupts or only 1 total on this + * CPU, skip + */ + if (!cpu_infop->aci_temp_bound || + (cpu_infop->aci_bound + cpu_infop->aci_temp_bound) + == 1) { + apic_redist_cpu_skip |= 1 << i; + continue; + } + + busy = cpu_infop->aci_busy; + average_busy += busy; + cpus_online++; + if (max_busy < busy) { + max_busy = busy; + busiest_cpu = i; + } + if (min_free > busy) { + min_free = busy; + most_free_cpu = i; + } + if (busy > apic_int_busy_mark) { + cpu_busy |= 1 << i; + } else { + if (busy < apic_int_free_mark) + cpu_free |= 1 << i; + } + } + } + if ((cpu_busy && cpu_free) || + (max_busy >= (min_free + apic_diff_for_redistribution))) { + + apic_num_imbalance++; +#ifdef DEBUG + if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) { + prom_printf( + "redistribute busy=%x free=%x max=%x min=%x", + cpu_busy, cpu_free, max_busy, min_free); + } +#endif /* DEBUG */ + + + average_busy /= cpus_online; + + diff = max_busy - average_busy; + min_busy = max_busy; /* start with the max possible value */ + max_busy = 0; + min_busy_irq = max_busy_irq = NULL; + i = apic_min_device_irq; + for (; i < apic_max_device_irq; i++) { + apic_irq_t *irq_ptr; + /* Change to linked list per CPU ? */ + if ((irq_ptr = apic_irq_table[i]) == NULL) + continue; + /* Check for irq_busy & decide which one to move */ + /* Also zero them for next round */ + if ((irq_ptr->airq_temp_cpu == busiest_cpu) && + irq_ptr->airq_busy) { + if (irq_ptr->airq_busy < diff) { + /* + * Check for least busy CPU, + * best fit or what ? + */ + if (max_busy < irq_ptr->airq_busy) { + /* + * Most busy within the + * required differential + */ + max_busy = irq_ptr->airq_busy; + max_busy_irq = irq_ptr; + } + } else { + if (min_busy > irq_ptr->airq_busy) { + /* + * least busy, but more than + * the reqd diff + */ + if (min_busy < + (diff + average_busy - + min_free)) { + /* + * Making sure new cpu + * will not end up + * worse + */ + min_busy = + irq_ptr->airq_busy; + + min_busy_irq = irq_ptr; + } + } + } + } + irq_ptr->airq_busy = 0; + } + + if (max_busy_irq != NULL) { +#ifdef DEBUG + if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) { + prom_printf("rebinding %x to %x", + max_busy_irq->airq_vector, most_free_cpu); + } +#endif /* DEBUG */ + iflag = intr_clear(); + if (lock_try(&apic_ioapic_lock)) { + if (apic_rebind_all(max_busy_irq, + most_free_cpu) == 0) { + /* Make change permenant */ + max_busy_irq->airq_cpu = + (uchar_t)most_free_cpu; + } + lock_clear(&apic_ioapic_lock); + } + intr_restore(iflag); + + } else if (min_busy_irq != NULL) { +#ifdef DEBUG + if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) { + prom_printf("rebinding %x to %x", + min_busy_irq->airq_vector, most_free_cpu); + } +#endif /* DEBUG */ + + iflag = intr_clear(); + if (lock_try(&apic_ioapic_lock)) { + if (apic_rebind_all(min_busy_irq, + most_free_cpu) == 0) { + /* Make change permenant */ + min_busy_irq->airq_cpu = + (uchar_t)most_free_cpu; + } + lock_clear(&apic_ioapic_lock); + } + intr_restore(iflag); + + } else { + if (cpu_busy != (1 << busiest_cpu)) { + apic_redist_cpu_skip |= 1 << busiest_cpu; + /* + * We leave cpu_skip set so that next time we + * can choose another cpu + */ + } + } + apic_num_rebind++; + } else { + /* + * found nothing. Could be that we skipped over valid CPUs + * or we have balanced everything. If we had a variable + * ticks_for_redistribution, it could be increased here. + * apic_int_busy, int_free etc would also need to be + * changed. + */ + if (apic_redist_cpu_skip) + apic_redist_cpu_skip = 0; + } + for (i = 0; i < apic_nproc; i++) { + apic_cpus[i].aci_busy = 0; + } +} + +void +apic_cleanup_busy() +{ + int i; + apic_irq_t *irq_ptr; + + for (i = 0; i < apic_nproc; i++) { + apic_cpus[i].aci_busy = 0; + } + + for (i = apic_min_device_irq; i < apic_max_device_irq; i++) { + if ((irq_ptr = apic_irq_table[i]) != NULL) + irq_ptr->airq_busy = 0; + } +} + + +static int +apic_acpi_translate_pci_irq(dev_info_t *dip, int busid, int devid, + int ipin, int *pci_irqp, iflag_t *intr_flagp) +{ + + int status; + acpi_psm_lnk_t acpipsmlnk; + + if ((status = acpi_get_irq_cache_ent(busid, devid, ipin, pci_irqp, + intr_flagp)) == ACPI_PSM_SUCCESS) { + APIC_VERBOSE_IRQ((CE_CONT, "!%s: Found irqno %d " + "from cache for device %s, instance #%d\n", psm_name, + *pci_irqp, ddi_get_name(dip), ddi_get_instance(dip))); + return (status); + } + + bzero(&acpipsmlnk, sizeof (acpi_psm_lnk_t)); + + if ((status = acpi_translate_pci_irq(dip, ipin, pci_irqp, intr_flagp, + &acpipsmlnk)) == ACPI_PSM_FAILURE) { + APIC_VERBOSE_IRQ((CE_WARN, "%s: " + " acpi_translate_pci_irq failed for device %s, instance" + " #%d", psm_name, ddi_get_name(dip), + ddi_get_instance(dip))); + return (status); + } + + if (status == ACPI_PSM_PARTIAL && acpipsmlnk.lnkobj != NULL) { + status = apic_acpi_irq_configure(&acpipsmlnk, dip, pci_irqp, + intr_flagp); + if (status != ACPI_PSM_SUCCESS) { + status = acpi_get_current_irq_resource(&acpipsmlnk, + pci_irqp, intr_flagp); + } + } + + if (status == ACPI_PSM_SUCCESS) { + acpi_new_irq_cache_ent(busid, devid, ipin, *pci_irqp, + intr_flagp, &acpipsmlnk); + + APIC_VERBOSE_IRQ((CE_CONT, "%s: [ACPI] " + "new irq %d for device %s, instance #%d\n", psm_name, + *pci_irqp, ddi_get_name(dip), ddi_get_instance(dip))); + } + + return (status); +} + +/* + * Adds an entry to the irq list passed in, and returns the new list. + * Entries are added in priority order (lower numerical priorities are + * placed closer to the head of the list) + */ +static prs_irq_list_t * +acpi_insert_prs_irq_ent(prs_irq_list_t *listp, int priority, int irq, + iflag_t *iflagp, acpi_prs_private_t *prsprvp) +{ + struct prs_irq_list_ent *newent, *prevp = NULL, *origlistp; + + newent = kmem_zalloc(sizeof (struct prs_irq_list_ent), KM_SLEEP); + + newent->list_prio = priority; + newent->irq = irq; + newent->intrflags = *iflagp; + newent->prsprv = *prsprvp; + /* ->next is NULL from kmem_zalloc */ + + /* + * New list -- return the new entry as the list. + */ + if (listp == NULL) + return (newent); + + /* + * Save original list pointer for return (since we're not modifying + * the head) + */ + origlistp = listp; + + /* + * Insertion sort, with entries with identical keys stored AFTER + * existing entries (the less-than-or-equal test of priority does + * this for us). + */ + while (listp != NULL && listp->list_prio <= priority) { + prevp = listp; + listp = listp->next; + } + + newent->next = listp; + + if (prevp == NULL) { /* Add at head of list (newent is the new head) */ + return (newent); + } else { + prevp->next = newent; + return (origlistp); + } +} + +/* + * Frees the list passed in, deallocating all memory and leaving *listpp + * set to NULL. + */ +static void +acpi_destroy_prs_irq_list(prs_irq_list_t **listpp) +{ + struct prs_irq_list_ent *nextp; + + ASSERT(listpp != NULL); + + while (*listpp != NULL) { + nextp = (*listpp)->next; + kmem_free(*listpp, sizeof (struct prs_irq_list_ent)); + *listpp = nextp; + } +} + +/* + * apic_choose_irqs_from_prs returns a list of irqs selected from the list of + * irqs returned by the link device's _PRS method. The irqs are chosen + * to minimize contention in situations where the interrupt link device + * can be programmed to steer interrupts to different interrupt controller + * inputs (some of which may already be in use). The list is sorted in order + * of irqs to use, with the highest priority given to interrupt controller + * inputs that are not shared. When an interrupt controller input + * must be shared, apic_choose_irqs_from_prs adds the possible irqs to the + * returned list in the order that minimizes sharing (thereby ensuring lowest + * possible latency from interrupt trigger time to ISR execution time). + */ +static prs_irq_list_t * +apic_choose_irqs_from_prs(acpi_irqlist_t *irqlistent, dev_info_t *dip, + int crs_irq) +{ + int32_t irq; + int i; + prs_irq_list_t *prsirqlistp = NULL; + iflag_t iflags; + + while (irqlistent != NULL) { + irqlistent->intr_flags.bustype = BUS_PCI; + + for (i = 0; i < irqlistent->num_irqs; i++) { + + irq = irqlistent->irqs[i]; + + if (irq <= 0) { + /* invalid irq number */ + continue; + } + + if ((irq < 16) && (apic_reserved_irqlist[irq])) + continue; + + if ((apic_irq_table[irq] == NULL) || + (apic_irq_table[irq]->airq_dip == dip)) { + + prsirqlistp = acpi_insert_prs_irq_ent( + prsirqlistp, 0 /* Highest priority */, irq, + &irqlistent->intr_flags, + &irqlistent->acpi_prs_prv); + + /* + * If we do not prefer the current irq from _CRS + * or if we do and this irq is the same as the + * current irq from _CRS, this is the one + * to pick. + */ + if (!(apic_prefer_crs) || (irq == crs_irq)) { + return (prsirqlistp); + } + continue; + } + + /* + * Edge-triggered interrupts cannot be shared + */ + if (irqlistent->intr_flags.intr_el == INTR_EL_EDGE) + continue; + + /* + * To work around BIOSes that contain incorrect + * interrupt polarity information in interrupt + * descriptors returned by _PRS, we assume that + * the polarity of the other device sharing this + * interrupt controller input is compatible. + * If it's not, the caller will catch it when + * the caller invokes the link device's _CRS method + * (after invoking its _SRS method). + */ + iflags = irqlistent->intr_flags; + iflags.intr_po = + apic_irq_table[irq]->airq_iflag.intr_po; + + if (!acpi_intr_compatible(iflags, + apic_irq_table[irq]->airq_iflag)) { + APIC_VERBOSE_IRQ((CE_CONT, "!%s: irq %d " + "not compatible [%x:%x:%x !~ %x:%x:%x]", + psm_name, irq, + iflags.intr_po, + iflags.intr_el, + iflags.bustype, + apic_irq_table[irq]->airq_iflag.intr_po, + apic_irq_table[irq]->airq_iflag.intr_el, + apic_irq_table[irq]->airq_iflag.bustype)); + continue; + } + + /* + * If we prefer the irq from _CRS, no need + * to search any further (and make sure + * to add this irq with the highest priority + * so it's tried first). + */ + if (crs_irq == irq && apic_prefer_crs) { + + return (acpi_insert_prs_irq_ent( + prsirqlistp, + 0 /* Highest priority */, + irq, &iflags, + &irqlistent->acpi_prs_prv)); + } + + /* + * Priority is equal to the share count (lower + * share count is higher priority). Note that + * the intr flags passed in here are the ones we + * changed above -- if incorrect, it will be + * caught by the caller's _CRS flags comparison. + */ + prsirqlistp = acpi_insert_prs_irq_ent( + prsirqlistp, + apic_irq_table[irq]->airq_share, irq, + &iflags, &irqlistent->acpi_prs_prv); + } + + /* Go to the next irqlist entry */ + irqlistent = irqlistent->next; + } + + return (prsirqlistp); +} + +/* + * Configures the irq for the interrupt link device identified by + * acpipsmlnkp. + * + * Gets the current and the list of possible irq settings for the + * device. If apic_unconditional_srs is not set, and the current + * resource setting is in the list of possible irq settings, + * current irq resource setting is passed to the caller. + * + * Otherwise, picks an irq number from the list of possible irq + * settings, and sets the irq of the device to this value. + * If prefer_crs is set, among a set of irq numbers in the list that have + * the least number of devices sharing the interrupt, we pick current irq + * resource setting if it is a member of this set. + * + * Passes the irq number in the value pointed to by pci_irqp, and + * polarity and sensitivity in the structure pointed to by dipintrflagp + * to the caller. + * + * Note that if setting the irq resource failed, but successfuly obtained + * the current irq resource settings, passes the current irq resources + * and considers it a success. + * + * Returns: + * ACPI_PSM_SUCCESS on success. + * + * ACPI_PSM_FAILURE if an error occured during the configuration or + * if a suitable irq was not found for this device, or if setting the + * irq resource and obtaining the current resource fails. + * + */ +static int +apic_acpi_irq_configure(acpi_psm_lnk_t *acpipsmlnkp, dev_info_t *dip, + int *pci_irqp, iflag_t *dipintr_flagp) +{ + int32_t irq; + int cur_irq = -1; + acpi_irqlist_t *irqlistp; + prs_irq_list_t *prs_irq_listp, *prs_irq_entp; + boolean_t found_irq = B_FALSE; + + dipintr_flagp->bustype = BUS_PCI; + + if ((acpi_get_possible_irq_resources(acpipsmlnkp, &irqlistp)) + == ACPI_PSM_FAILURE) { + APIC_VERBOSE_IRQ((CE_WARN, "!%s: Unable to determine " + "or assign IRQ for device %s, instance #%d: The system was " + "unable to get the list of potential IRQs from ACPI.", + psm_name, ddi_get_name(dip), ddi_get_instance(dip))); + + return (ACPI_PSM_FAILURE); + } + + if ((acpi_get_current_irq_resource(acpipsmlnkp, &cur_irq, + dipintr_flagp) == ACPI_PSM_SUCCESS) && (!apic_unconditional_srs) && + (cur_irq > 0)) { + /* + * If an IRQ is set in CRS and that IRQ exists in the set + * returned from _PRS, return that IRQ, otherwise print + * a warning + */ + + if (acpi_irqlist_find_irq(irqlistp, cur_irq, NULL) + == ACPI_PSM_SUCCESS) { + + ASSERT(pci_irqp != NULL); + *pci_irqp = cur_irq; + acpi_free_irqlist(irqlistp); + return (ACPI_PSM_SUCCESS); + } + + APIC_VERBOSE_IRQ((CE_WARN, "!%s: Could not find the " + "current irq %d for device %s, instance #%d in ACPI's " + "list of possible irqs for this device. Picking one from " + " the latter list.", psm_name, cur_irq, ddi_get_name(dip), + ddi_get_instance(dip))); + } + + if ((prs_irq_listp = apic_choose_irqs_from_prs(irqlistp, dip, + cur_irq)) == NULL) { + + APIC_VERBOSE_IRQ((CE_WARN, "!%s: Could not find a " + "suitable irq from the list of possible irqs for device " + "%s, instance #%d in ACPI's list of possible irqs", + psm_name, ddi_get_name(dip), ddi_get_instance(dip))); + + acpi_free_irqlist(irqlistp); + return (ACPI_PSM_FAILURE); + } + + acpi_free_irqlist(irqlistp); + + for (prs_irq_entp = prs_irq_listp; + prs_irq_entp != NULL && found_irq == B_FALSE; + prs_irq_entp = prs_irq_entp->next) { + + acpipsmlnkp->acpi_prs_prv = prs_irq_entp->prsprv; + irq = prs_irq_entp->irq; + + APIC_VERBOSE_IRQ((CE_CONT, "!%s: Setting irq %d for " + "device %s instance #%d\n", psm_name, irq, + ddi_get_name(dip), ddi_get_instance(dip))); + + if ((acpi_set_irq_resource(acpipsmlnkp, irq)) + == ACPI_PSM_SUCCESS) { + /* + * setting irq was successful, check to make sure CRS + * reflects that. If CRS does not agree with what we + * set, return the irq that was set. + */ + + if (acpi_get_current_irq_resource(acpipsmlnkp, &cur_irq, + dipintr_flagp) == ACPI_PSM_SUCCESS) { + + if (cur_irq != irq) + APIC_VERBOSE_IRQ((CE_WARN, + "!%s: IRQ resource set " + "(irqno %d) for device %s " + "instance #%d, differs from " + "current setting irqno %d", + psm_name, irq, ddi_get_name(dip), + ddi_get_instance(dip), cur_irq)); + } else { + /* + * On at least one system, there was a bug in + * a DSDT method called by _STA, causing _STA to + * indicate that the link device was disabled + * (when, in fact, it was enabled). Since _SRS + * succeeded, assume that _CRS is lying and use + * the iflags from this _PRS interrupt choice. + * If we're wrong about the flags, the polarity + * will be incorrect and we may get an interrupt + * storm, but there's not much else we can do + * at this point. + */ + *dipintr_flagp = prs_irq_entp->intrflags; + } + + /* + * Return the irq that was set, and not what _CRS + * reports, since _CRS has been seen to return + * different IRQs than what was passed to _SRS on some + * systems (and just not return successfully on others). + */ + cur_irq = irq; + found_irq = B_TRUE; + } else { + APIC_VERBOSE_IRQ((CE_WARN, "!%s: set resource " + "irq %d failed for device %s instance #%d", + psm_name, irq, ddi_get_name(dip), + ddi_get_instance(dip))); + + if (cur_irq == -1) { + acpi_destroy_prs_irq_list(&prs_irq_listp); + return (ACPI_PSM_FAILURE); + } + } + } + + acpi_destroy_prs_irq_list(&prs_irq_listp); + + if (!found_irq) + return (ACPI_PSM_FAILURE); + + ASSERT(pci_irqp != NULL); + *pci_irqp = cur_irq; + return (ACPI_PSM_SUCCESS); +} + +void +ioapic_disable_redirection() +{ + int ioapic_ix; + int intin_max; + int intin_ix; + + /* Disable the I/O APIC redirection entries */ + for (ioapic_ix = 0; ioapic_ix < apic_io_max; ioapic_ix++) { + + /* Bits 23-16 define the maximum redirection entries */ + intin_max = (ioapic_read(ioapic_ix, APIC_VERS_CMD) >> 16) + & 0xff; + + for (intin_ix = 0; intin_ix < intin_max; intin_ix++) + ioapic_write(ioapic_ix, APIC_RDT_CMD + 2 * intin_ix, + AV_MASK); + } +} diff --git a/usr/src/uts/i86pc/io/pci/pci_common.c b/usr/src/uts/i86pc/io/pci/pci_common.c index f97c7539d4..f432b85130 100644 --- a/usr/src/uts/i86pc/io/pci/pci_common.c +++ b/usr/src/uts/i86pc/io/pci/pci_common.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -45,7 +45,7 @@ #include <sys/policy.h> #include <sys/sysmacros.h> #include <sys/clock.h> -#include <io/pcplusmp/apic.h> +#include <sys/apic.h> #include <sys/pci_tools.h> #include <io/pci/pci_var.h> #include <io/pci/pci_tools_ext.h> diff --git a/usr/src/uts/i86pc/io/pci/pci_kstats.c b/usr/src/uts/i86pc/io/pci/pci_kstats.c index ce0780bf34..c8032f1286 100644 --- a/usr/src/uts/i86pc/io/pci/pci_kstats.c +++ b/usr/src/uts/i86pc/io/pci/pci_kstats.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,7 +33,7 @@ #include <sys/mach_intr.h> #include <sys/psm.h> #include <sys/clock.h> -#include <io/pcplusmp/apic.h> +#include <sys/apic.h> #include <io/pci/pci_var.h> typedef struct pci_kstat_private { diff --git a/usr/src/uts/i86pc/io/pci/pci_tools.c b/usr/src/uts/i86pc/io/pci/pci_tools.c index a08bfc9b91..7e4c90c432 100644 --- a/usr/src/uts/i86pc/io/pci/pci_tools.c +++ b/usr/src/uts/i86pc/io/pci/pci_tools.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -39,7 +39,7 @@ #include <sys/pci_cfgspace.h> #include <sys/pci_tools.h> #include <io/pci/pci_tools_ext.h> -#include <io/pcplusmp/apic.h> +#include <sys/apic.h> #include <io/pci/pci_var.h> #include <sys/promif.h> #include <sys/x86_archext.h> @@ -741,6 +741,7 @@ pcitool_map(uint64_t phys_addr, size_t size, size_t *num_pages) uint64_t offset = phys_addr & MMU_PAGEOFFSET; void *virt_base; uint64_t returned_addr; + pfn_t pfn; if (pcitool_debug) prom_printf("pcitool_map: Called with PA:0x%p\n", @@ -771,9 +772,11 @@ pcitool_map(uint64_t phys_addr, size_t size, size_t *num_pages) if (pcitool_debug) prom_printf("Got base virtual address:0x%p\n", virt_base); + pfn = btop(page_base); + /* Now map the allocated virtual space to the physical address. */ - hat_devload(kas.a_hat, virt_base, mmu_ptob(*num_pages), - mmu_btop(page_base), PROT_READ | PROT_WRITE | HAT_STRICTORDER, + hat_devload(kas.a_hat, virt_base, mmu_ptob(*num_pages), pfn, + PROT_READ | PROT_WRITE | HAT_STRICTORDER, HAT_LOAD_LOCK); returned_addr = ((uintptr_t)(virt_base)) + offset; diff --git a/usr/src/uts/i86pc/io/pciex/inc.flg b/usr/src/uts/i86pc/io/pciex/inc.flg index 4379616c55..7d4ab20ccf 100644 --- a/usr/src/uts/i86pc/io/pciex/inc.flg +++ b/usr/src/uts/i86pc/io/pciex/inc.flg @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -56,9 +55,9 @@ find_files "s.*" \ # to compile the drivers/modules find_files "s.*" \ usr/src/uts/i86pc/npe \ - usr/src/uts/i86pc/pcie_pci \ - usr/src/uts/i86pc/pciehpc \ - usr/src/uts/i86pc/pci_autoconfig \ + usr/src/uts/intel/pci_autoconfig \ + usr/src/uts/intel/pcie_pci \ + usr/src/uts/intel/pciehpc \ usr/src/uts/intel/pcicfg # packaging files @@ -75,9 +74,11 @@ find_files "s.*" \ usr/src/uts/common/rpc \ usr/src/uts/intel/asm \ usr/src/uts/intel/amd64 \ + usr/src/uts/intel/io/pci \ + usr/src/uts/intel/io/pciex \ usr/src/uts/i86pc/io/pci \ usr/src/uts/i86pc/io/pcplusmp \ - usr/src/uts/i86pc/io/acpica + usr/src/uts/intel/io/acpica # makefiles echo_file usr/src/Makefile.master diff --git a/usr/src/uts/i86pc/io/pcplusmp/apic.c b/usr/src/uts/i86pc/io/pcplusmp/apic.c index 1305e8ccde..0f30ffa9c8 100644 --- a/usr/src/uts/i86pc/io/pcplusmp/apic.c +++ b/usr/src/uts/i86pc/io/pcplusmp/apic.c @@ -18,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,7 +42,7 @@ #include <sys/acpi/acpi.h> #include <sys/acpica.h> #include <sys/psm_common.h> -#include "apic.h" +#include <sys/apic.h> #include <sys/pit.h> #include <sys/ddi.h> #include <sys/sunddi.h> @@ -56,78 +57,23 @@ #include <sys/archsystm.h> #include <sys/trap.h> #include <sys/machsystm.h> +#include <sys/sysmacros.h> #include <sys/cpuvar.h> #include <sys/rm_platter.h> #include <sys/privregs.h> #include <sys/cyclic.h> #include <sys/note.h> #include <sys/pci_intr_lib.h> -#include <sys/sunndi.h> - -struct ioapic_reprogram_data; +#include <sys/spl.h> /* * Local Function Prototypes */ static void apic_init_intr(); static void apic_ret(); -static int apic_handle_defconf(); -static int apic_parse_mpct(caddr_t mpct, int bypass); -static struct apic_mpfps_hdr *apic_find_fps_sig(caddr_t fptr, int size); -static int apic_checksum(caddr_t bptr, int len); static int get_apic_cmd1(); static int get_apic_pri(); -static int apic_find_bus_type(char *bus); -static int apic_find_bus(int busid); -static int apic_find_bus_id(int bustype); -static struct apic_io_intr *apic_find_io_intr(int irqno); -int apic_allocate_irq(int irq); -static int apic_find_free_irq(int start, int end); -static uchar_t apic_allocate_vector(int ipl, int irq, int pri); -static void apic_modify_vector(uchar_t vector, int irq); -static void apic_mark_vector(uchar_t oldvector, uchar_t newvector); -static uchar_t apic_xlate_vector(uchar_t oldvector); -static void apic_xlate_vector_free_timeout_handler(void *arg); -static void apic_free_vector(uchar_t vector); -static void apic_reprogram_timeout_handler(void *arg); -static int apic_check_stuck_interrupt(apic_irq_t *irq_ptr, int old_bind_cpu, - int new_bind_cpu, volatile int32_t *ioapic, int intin_no, int which_irq, - struct ioapic_reprogram_data *drep); -static int apic_setup_io_intr(void *p, int irq, boolean_t deferred); -static void apic_record_rdt_entry(apic_irq_t *irqptr, int irq); -static struct apic_io_intr *apic_find_io_intr_w_busid(int irqno, int busid); -static int apic_find_intin(uchar_t ioapic, uchar_t intin); -static int apic_handle_pci_pci_bridge(dev_info_t *idip, int child_devno, - int child_ipin, struct apic_io_intr **intrp); -static int apic_setup_irq_table(dev_info_t *dip, int irqno, - struct apic_io_intr *intrp, struct intrspec *ispec, iflag_t *intr_flagp, - int type); -static int apic_setup_sci_irq_table(int irqno, uchar_t ipl, - iflag_t *intr_flagp); static void apic_nmi_intr(caddr_t arg); -uchar_t apic_bind_intr(dev_info_t *dip, int irq, uchar_t ioapicid, - uchar_t intin); -static int apic_rebind(apic_irq_t *irq_ptr, int bind_cpu, - struct ioapic_reprogram_data *drep); -int apic_rebind_all(apic_irq_t *irq_ptr, int bind_cpu); -static void apic_intr_redistribute(); -static void apic_cleanup_busy(); -static void apic_set_pwroff_method_from_mpcnfhdr(struct apic_mp_cnf_hdr *hdrp); -int apic_introp_xlate(dev_info_t *dip, struct intrspec *ispec, int type); -static void apic_try_deferred_reprogram(int ipl, int vect); -static void delete_defer_repro_ent(int which_irq); -static void apic_ioapic_wait_pending_clear(volatile int32_t *ioapic, - int intin_no); - -/* ACPI support routines */ -static int acpi_probe(void); -static int apic_acpi_irq_configure(acpi_psm_lnk_t *acpipsmlnkp, dev_info_t *dip, - int *pci_irqp, iflag_t *intr_flagp); - -static int apic_acpi_translate_pci_irq(dev_info_t *dip, int busid, int devid, - int ipin, int *pci_irqp, iflag_t *intr_flagp); -static uchar_t acpi_find_ioapic(int irq); -static int acpi_intr_compatible(iflag_t iflag1, iflag_t iflag2); /* * standard MP entries @@ -141,7 +87,7 @@ static hrtime_t apic_gettime(); static hrtime_t apic_gethrtime(); static void apic_init(); static void apic_picinit(void); -static void apic_cpu_start(processorid_t cpun, caddr_t rm_code); +static int apic_cpu_start(processorid_t, caddr_t); static int apic_post_cpu_start(void); static void apic_send_ipi(int cpun, int ipl); static void apic_set_softintr(int softintr); @@ -149,7 +95,6 @@ static void apic_set_idlecpu(processorid_t cpun); static void apic_unset_idlecpu(processorid_t cpun); static int apic_softlvl_to_irq(int ipl); static int apic_intr_enter(int ipl, int *vect); -static void apic_intr_exit(int ipl, int vect); static void apic_setspl(int ipl); static int apic_addspl(int ipl, int vector, int min_ipl, int max_ipl); static int apic_delspl(int ipl, int vector, int min_ipl, int max_ipl); @@ -163,12 +108,14 @@ static void apic_timer_reprogram(hrtime_t time); static void apic_timer_enable(void); static void apic_timer_disable(void); static void apic_post_cyclic_setup(void *arg); -extern int apic_intr_ops(dev_info_t *, ddi_intr_handle_impl_t *, - psm_intr_op_t, int *); static int apic_oneshot = 0; int apic_oneshot_enable = 1; /* to allow disabling one-shot capability */ +/* Now the ones for Dynamic Interrupt distribution */ +int apic_enable_dynamic_migration = 0; + + /* * These variables are frequently accessed in apic_intr_enter(), * apic_intr_exit and apic_setspl, so group them together @@ -177,10 +124,6 @@ volatile uint32_t *apicadr = NULL; /* virtual addr of local APIC */ int apic_setspl_delay = 1; /* apic_setspl - delay enable */ int apic_clkvect; -/* ACPI SCI interrupt configuration; -1 if SCI not used */ -int apic_sci_vect = -1; -iflag_t apic_sci_flags; - /* vector at which error interrupts come in */ int apic_errvect; int apic_enable_error_intr = 1; @@ -190,19 +133,6 @@ int apic_error_display_delay = 100; int apic_cpcovf_vect; int apic_enable_cpcovf_intr = 1; -/* Max wait time (in repetitions) for flags to clear in an RDT entry. */ -static int apic_max_reps_clear_pending = 1000; - -/* Maximum number of times to retry reprogramming at apic_intr_exit time */ -#define APIC_REPROGRAM_MAX_TRIES 10000 - -/* - * number of bits per byte, from <sys/param.h> - */ -#define UCHAR_MAX ((1 << NBBY) - 1) - -uchar_t apic_reserved_irqlist[MAX_ISA_IRQ + 1]; - /* * The following vector assignments influence the value of ipltopri and * vectortoipl. Note that vectors 0 - 0x1f are not used. We can program @@ -243,15 +173,6 @@ uchar_t apic_cr8pri[MAXIPL + 1]; /* unix ipl to cr8 pri */ */ int apic_forceload = 0; -#define INTR_ROUND_ROBIN_WITH_AFFINITY 0 -#define INTR_ROUND_ROBIN 1 -#define INTR_LOWEST_PRIORITY 2 - -int apic_intr_policy = INTR_ROUND_ROBIN_WITH_AFFINITY; - -static int apic_next_bind_cpu = 1; /* For round robin assignment */ - /* start with cpu 1 */ - int apic_coarse_hrtime = 1; /* 0 - use accurate slow gethrtime() */ /* 1 - use gettime() for performance */ int apic_flat_model = 0; /* 0 - clustered. 1 - flat */ @@ -262,102 +183,6 @@ int apic_panic_on_apic_error = 0; int apic_verbose = 0; -/* Flag definitions for apic_verbose */ -#define APIC_VERBOSE_IOAPIC_FLAG 0x00000001 -#define APIC_VERBOSE_IRQ_FLAG 0x00000002 -#define APIC_VERBOSE_POWEROFF_FLAG 0x00000004 -#define APIC_VERBOSE_POWEROFF_PAUSE_FLAG 0x00000008 - - -#define APIC_VERBOSE_IOAPIC(fmt) \ - if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) \ - cmn_err fmt; - -#define APIC_VERBOSE_IRQ(fmt) \ - if (apic_verbose & APIC_VERBOSE_IRQ_FLAG) \ - cmn_err fmt; - -#define APIC_VERBOSE_POWEROFF(fmt) \ - if (apic_verbose & APIC_VERBOSE_POWEROFF_FLAG) \ - prom_printf fmt; - - -/* Now the ones for Dynamic Interrupt distribution */ -int apic_enable_dynamic_migration = 0; - -/* - * If enabled, the distribution works as follows: - * On every interrupt entry, the current ipl for the CPU is set in cpu_info - * and the irq corresponding to the ipl is also set in the aci_current array. - * interrupt exit and setspl (due to soft interrupts) will cause the current - * ipl to be be changed. This is cache friendly as these frequently used - * paths write into a per cpu structure. - * - * Sampling is done by checking the structures for all CPUs and incrementing - * the busy field of the irq (if any) executing on each CPU and the busy field - * of the corresponding CPU. - * In periodic mode this is done on every clock interrupt. - * In one-shot mode, this is done thru a cyclic with an interval of - * apic_redistribute_sample_interval (default 10 milli sec). - * - * Every apic_sample_factor_redistribution times we sample, we do computations - * to decide which interrupt needs to be migrated (see comments - * before apic_intr_redistribute(). - */ - -/* - * Following 3 variables start as % and can be patched or set using an - * API to be defined in future. They will be scaled to - * sample_factor_redistribution which is in turn set to hertz+1 (in periodic - * mode), or 101 in one-shot mode to stagger it away from one sec processing - */ - -int apic_int_busy_mark = 60; -int apic_int_free_mark = 20; -int apic_diff_for_redistribution = 10; - -/* sampling interval for interrupt redistribution for dynamic migration */ -int apic_redistribute_sample_interval = NANOSEC / 100; /* 10 millisec */ - -/* - * number of times we sample before deciding to redistribute interrupts - * for dynamic migration - */ -int apic_sample_factor_redistribution = 101; - -/* timeout for xlate_vector, mark_vector */ -int apic_revector_timeout = 16 * 10000; /* 160 millisec */ - -int apic_redist_cpu_skip = 0; -int apic_num_imbalance = 0; -int apic_num_rebind = 0; - -int apic_nproc = 0; -int apic_defconf = 0; -int apic_irq_translate = 0; -int apic_spec_rev = 0; -int apic_imcrp = 0; - -int apic_use_acpi = 1; /* 1 = use ACPI, 0 = don't use ACPI */ -int apic_use_acpi_madt_only = 0; /* 1=ONLY use MADT from ACPI */ - -/* - * For interrupt link devices, if apic_unconditional_srs is set, an irq resource - * will be assigned (via _SRS). If it is not set, use the current - * irq setting (via _CRS), but only if that irq is in the set of possible - * irqs (returned by _PRS) for the device. - */ -int apic_unconditional_srs = 1; - -/* - * For interrupt link devices, if apic_prefer_crs is set when we are - * assigning an IRQ resource to a device, prefer the current IRQ setting - * over other possible irq settings under same conditions. - */ - -int apic_prefer_crs = 1; - - /* minimum number of timer ticks to program to */ int apic_min_timer_ticks = 1; /* @@ -394,8 +219,6 @@ static struct psm_ops apic_ops = { apic_send_ipi, (int (*)(dev_info_t *, int))NULL, /* psm_translate_irq */ - (int (*)(todinfo_t *))NULL, /* psm_tod_get */ - (int (*)(todinfo_t *))NULL, /* psm_tod_set */ (void (*)(int, char *))NULL, /* psm_notify_error */ (void (*)(int))NULL, /* psm_notify_func */ apic_timer_reprogram, @@ -418,33 +241,18 @@ static struct psm_info apic_psm_info = { static void *apic_hdlp; #ifdef DEBUG -#define DENT 0x0001 int apic_debug = 0; -/* - * set apic_restrict_vector to the # of vectors we want to allow per range - * useful in testing shared interrupt logic by setting it to 2 or 3 - */ int apic_restrict_vector = 0; -#define APIC_DEBUG_MSGBUFSIZE 2048 int apic_debug_msgbuf[APIC_DEBUG_MSGBUFSIZE]; int apic_debug_msgbufindex = 0; -/* - * Put "int" info into debug buffer. No MP consistency, but light weight. - * Good enough for most debugging. - */ -#define APIC_DEBUG_BUF_PUT(x) \ - apic_debug_msgbuf[apic_debug_msgbufindex++] = x; \ - if (apic_debug_msgbufindex >= (APIC_DEBUG_MSGBUFSIZE - NCPU)) \ - apic_debug_msgbufindex = 0; - #endif /* DEBUG */ apic_cpus_info_t *apic_cpus; -static cpuset_t apic_cpumask; -static uint_t apic_flag; +cpuset_t apic_cpumask; +uint_t apic_flag; /* Flag to indicate that we need to shut down all processors */ static uint_t apic_shutdown_processors; @@ -482,148 +290,14 @@ int apic_apic_error = 0; int apic_num_apic_errors = 0; int apic_num_cksum_errors = 0; -static uchar_t apic_io_id[MAX_IO_APIC]; -static uchar_t apic_io_ver[MAX_IO_APIC]; -static uchar_t apic_io_vectbase[MAX_IO_APIC]; -static uchar_t apic_io_vectend[MAX_IO_APIC]; -volatile int32_t *apicioadr[MAX_IO_APIC]; - -/* - * First available slot to be used as IRQ index into the apic_irq_table - * for those interrupts (like MSI/X) that don't have a physical IRQ. - */ -int apic_first_avail_irq = APIC_FIRST_FREE_IRQ; - -/* - * apic_ioapic_lock protects the ioapics (reg select), the status, temp_bound - * and bound elements of cpus_info and the temp_cpu element of irq_struct - */ -lock_t apic_ioapic_lock; - -/* - * apic_defer_reprogram_lock ensures that only one processor is handling - * deferred interrupt programming at apic_intr_exit time. - */ -static lock_t apic_defer_reprogram_lock; - -/* - * The current number of deferred reprogrammings outstanding - */ -uint_t apic_reprogram_outstanding = 0; - -#ifdef DEBUG -/* - * Counters that keep track of deferred reprogramming stats - */ -uint_t apic_intr_deferrals = 0; -uint_t apic_intr_deliver_timeouts = 0; -uint_t apic_last_ditch_reprogram_failures = 0; -uint_t apic_deferred_setup_failures = 0; -uint_t apic_defer_repro_total_retries = 0; -uint_t apic_defer_repro_successes = 0; -uint_t apic_deferred_spurious_enters = 0; -#endif - -static int apic_io_max = 0; /* no. of i/o apics enabled */ - -static struct apic_io_intr *apic_io_intrp = 0; -static struct apic_bus *apic_busp; - -uchar_t apic_vector_to_irq[APIC_MAX_VECTOR+1]; -static uchar_t apic_resv_vector[MAXIPL+1]; - -static char apic_level_intr[APIC_MAX_VECTOR+1]; -static int apic_error = 0; -/* values which apic_error can take. Not catastrophic, but may help debug */ -#define APIC_ERR_BOOT_EOI 0x1 -#define APIC_ERR_GET_IPIVECT_FAIL 0x2 -#define APIC_ERR_INVALID_INDEX 0x4 -#define APIC_ERR_MARK_VECTOR_FAIL 0x8 -#define APIC_ERR_APIC_ERROR 0x40000000 -#define APIC_ERR_NMI 0x80000000 - +int apic_error = 0; static int apic_cmos_ssb_set = 0; -static uint32_t eisa_level_intr_mask = 0; - /* At least MSB will be set if EISA bus */ - -static int apic_pci_bus_total = 0; -static uchar_t apic_single_pci_busid = 0; - - -/* - * airq_mutex protects additions to the apic_irq_table - the first - * pointer and any airq_nexts off of that one. It also protects - * apic_max_device_irq & apic_min_device_irq. It also guarantees - * that share_id is unique as new ids are generated only when new - * irq_t structs are linked in. Once linked in the structs are never - * deleted. temp_cpu & mps_intr_index field indicate if it is programmed - * or allocated. Note that there is a slight gap between allocating in - * apic_introp_xlate and programming in addspl. - */ -kmutex_t airq_mutex; -apic_irq_t *apic_irq_table[APIC_MAX_VECTOR+1]; -int apic_max_device_irq = 0; -int apic_min_device_irq = APIC_MAX_VECTOR; - /* use to make sure only one cpu handles the nmi */ static lock_t apic_nmi_lock; /* use to make sure only one cpu handles the error interrupt */ static lock_t apic_error_lock; -/* - * Following declarations are for revectoring; used when ISRs at different - * IPLs share an irq. - */ -static lock_t apic_revector_lock; -static int apic_revector_pending = 0; -static uchar_t *apic_oldvec_to_newvec; -static uchar_t *apic_newvec_to_oldvec; - -static struct ioapic_reprogram_data { - boolean_t done; - apic_irq_t *irqp; - /* The CPU to which the int will be bound */ - int bindcpu; - /* # times the reprogram timeout was called */ - unsigned tries; - -/* The irq # is implicit in the array index: */ -} apic_reprogram_info[APIC_MAX_VECTOR + 1]; - -/* - * APIC_MAX_VECTOR + 1 is the maximum # of IRQs as well. apic_reprogram_info - * is indexed by IRQ number, NOT by vector number. - */ - -typedef struct prs_irq_list_ent { - int list_prio; - int32_t irq; - iflag_t intrflags; - acpi_prs_private_t prsprv; - struct prs_irq_list_ent *next; -} prs_irq_list_t; - -/* - * The following added to identify a software poweroff method if available. - */ - -static struct { - int poweroff_method; - char oem_id[APIC_MPS_OEM_ID_LEN + 1]; /* MAX + 1 for NULL */ - char prod_id[APIC_MPS_PROD_ID_LEN + 1]; /* MAX + 1 for NULL */ -} apic_mps_ids[] = { - { APIC_POWEROFF_VIA_RTC, "INTEL", "ALDER" }, /* 4300 */ - { APIC_POWEROFF_VIA_RTC, "NCR", "AMC" }, /* 4300 */ - { APIC_POWEROFF_VIA_ASPEN_BMC, "INTEL", "A450NX" }, /* 4400? */ - { APIC_POWEROFF_VIA_ASPEN_BMC, "INTEL", "AD450NX" }, /* 4400 */ - { APIC_POWEROFF_VIA_ASPEN_BMC, "INTEL", "AC450NX" }, /* 4400R */ - { APIC_POWEROFF_VIA_SITKA_BMC, "INTEL", "S450NX" }, /* S50 */ - { APIC_POWEROFF_VIA_SITKA_BMC, "INTEL", "SC450NX" } /* S50? */ -}; - -int apic_poweroff_method = APIC_POWEROFF_NONE; - static struct { uchar_t cntl; uchar_t data; @@ -662,60 +336,11 @@ static struct { { SMS_DATA_REGISTER, 0x22 } /* Cmd RESET_WATCHDOG_TIMER */ }; - /* Patchable global variables. */ int apic_kmdb_on_nmi = 0; /* 0 - no, 1 - yes enter kmdb */ -int apic_debug_mps_id = 0; /* 1 - print MPS ID strings */ uint32_t apic_divide_reg_init = 0; /* 0 - divide by 2 */ /* - * ACPI definitions - */ -/* _PIC method arguments */ -#define ACPI_PIC_MODE 0 -#define ACPI_APIC_MODE 1 - -/* APIC error flags we care about */ -#define APIC_SEND_CS_ERROR 0x01 -#define APIC_RECV_CS_ERROR 0x02 -#define APIC_CS_ERRORS (APIC_SEND_CS_ERROR|APIC_RECV_CS_ERROR) - -/* - * ACPI variables - */ -/* 1 = acpi is enabled & working, 0 = acpi is not enabled or not there */ -static int apic_enable_acpi = 0; - -/* ACPI Multiple APIC Description Table ptr */ -static MULTIPLE_APIC_TABLE *acpi_mapic_dtp = NULL; - -/* ACPI Interrupt Source Override Structure ptr */ -static MADT_INTERRUPT_OVERRIDE *acpi_isop = NULL; -static int acpi_iso_cnt = 0; - -/* ACPI Non-maskable Interrupt Sources ptr */ -static MADT_NMI_SOURCE *acpi_nmi_sp = NULL; -static int acpi_nmi_scnt = 0; -static MADT_LOCAL_APIC_NMI *acpi_nmi_cp = NULL; -static int acpi_nmi_ccnt = 0; - -/* - * extern declarations - */ -extern int intr_clear(void); -extern void intr_restore(uint_t); -#if defined(__amd64) -extern int intpri_use_cr8; -#endif /* __amd64 */ - -extern int apic_pci_msi_enable_vector(dev_info_t *, int, int, - int, int, int); -extern apic_irq_t *apic_find_irq(dev_info_t *, struct intrspec *, int); -extern int apic_pci_msi_unconfigure(dev_info_t *, int, int); -extern int apic_pci_msi_disable_mode(dev_info_t *, int, int); -extern int apic_pci_msi_enable_mode(dev_info_t *, int, int); - -/* * This is the loadable module wrapper */ @@ -739,788 +364,19 @@ _info(struct modinfo *modinfop) return (psm_mod_info(&apic_hdlp, &apic_psm_info, modinfop)); } -/* - * Auto-configuration routines - */ -/* - * Look at MPSpec 1.4 (Intel Order # 242016-005) for details of what we do here - * May work with 1.1 - but not guaranteed. - * According to the MP Spec, the MP floating pointer structure - * will be searched in the order described below: - * 1. In the first kilobyte of Extended BIOS Data Area (EBDA) - * 2. Within the last kilobyte of system base memory - * 3. In the BIOS ROM address space between 0F0000h and 0FFFFh - * Once we find the right signature with proper checksum, we call - * either handle_defconf or parse_mpct to get all info necessary for - * subsequent operations. - */ static int apic_probe() { - uint32_t mpct_addr, ebda_start = 0, base_mem_end; - caddr_t biosdatap; - caddr_t mpct; - caddr_t fptr; - int i, mpct_size, mapsize, retval = PSM_FAILURE; - ushort_t ebda_seg, base_mem_size; - struct apic_mpfps_hdr *fpsp; - struct apic_mp_cnf_hdr *hdrp; - int bypass_cpu_and_ioapics_in_mptables; - int acpi_user_options; - - if (apic_forceload < 0) - return (retval); - - /* Allow override for MADT-only mode */ - acpi_user_options = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(), 0, - "acpi-user-options", 0); - apic_use_acpi_madt_only = ((acpi_user_options & ACPI_OUSER_MADT) != 0); - - /* Allow apic_use_acpi to override MADT-only mode */ - if (!apic_use_acpi) - apic_use_acpi_madt_only = 0; - - retval = acpi_probe(); - - /* - * mapin the bios data area 40:0 - * 40:13h - two-byte location reports the base memory size - * 40:0Eh - two-byte location for the exact starting address of - * the EBDA segment for EISA - */ - biosdatap = psm_map_phys(0x400, 0x20, PROT_READ); - if (!biosdatap) - return (retval); - fpsp = (struct apic_mpfps_hdr *)NULL; - mapsize = MPFPS_RAM_WIN_LEN; - /*LINTED: pointer cast may result in improper alignment */ - ebda_seg = *((ushort_t *)(biosdatap+0xe)); - /* check the 1k of EBDA */ - if (ebda_seg) { - ebda_start = ((uint32_t)ebda_seg) << 4; - fptr = psm_map_phys(ebda_start, MPFPS_RAM_WIN_LEN, PROT_READ); - if (fptr) { - if (!(fpsp = - apic_find_fps_sig(fptr, MPFPS_RAM_WIN_LEN))) - psm_unmap_phys(fptr, MPFPS_RAM_WIN_LEN); - } - } - /* If not in EBDA, check the last k of system base memory */ - if (!fpsp) { - /*LINTED: pointer cast may result in improper alignment */ - base_mem_size = *((ushort_t *)(biosdatap + 0x13)); - - if (base_mem_size > 512) - base_mem_end = 639 * 1024; - else - base_mem_end = 511 * 1024; - /* if ebda == last k of base mem, skip to check BIOS ROM */ - if (base_mem_end != ebda_start) { - - fptr = psm_map_phys(base_mem_end, MPFPS_RAM_WIN_LEN, - PROT_READ); - - if (fptr) { - if (!(fpsp = apic_find_fps_sig(fptr, - MPFPS_RAM_WIN_LEN))) - psm_unmap_phys(fptr, MPFPS_RAM_WIN_LEN); - } - } - } - psm_unmap_phys(biosdatap, 0x20); - - /* If still cannot find it, check the BIOS ROM space */ - if (!fpsp) { - mapsize = MPFPS_ROM_WIN_LEN; - fptr = psm_map_phys(MPFPS_ROM_WIN_START, - MPFPS_ROM_WIN_LEN, PROT_READ); - if (fptr) { - if (!(fpsp = - apic_find_fps_sig(fptr, MPFPS_ROM_WIN_LEN))) { - psm_unmap_phys(fptr, MPFPS_ROM_WIN_LEN); - return (retval); - } - } - } - - if (apic_checksum((caddr_t)fpsp, fpsp->mpfps_length * 16) != 0) { - psm_unmap_phys(fptr, MPFPS_ROM_WIN_LEN); - return (retval); - } - - apic_spec_rev = fpsp->mpfps_spec_rev; - if ((apic_spec_rev != 04) && (apic_spec_rev != 01)) { - psm_unmap_phys(fptr, MPFPS_ROM_WIN_LEN); - return (retval); - } - - /* check IMCR is present or not */ - apic_imcrp = fpsp->mpfps_featinfo2 & MPFPS_FEATINFO2_IMCRP; - - /* check default configuration (dual CPUs) */ - if ((apic_defconf = fpsp->mpfps_featinfo1) != 0) { - psm_unmap_phys(fptr, mapsize); - return (apic_handle_defconf()); - } - - /* MP Configuration Table */ - mpct_addr = (uint32_t)(fpsp->mpfps_mpct_paddr); - - psm_unmap_phys(fptr, mapsize); /* unmap floating ptr struct */ - - /* - * Map in enough memory for the MP Configuration Table Header. - * Use this table to read the total length of the BIOS data and - * map in all the info - */ - /*LINTED: pointer cast may result in improper alignment */ - hdrp = (struct apic_mp_cnf_hdr *)psm_map_phys(mpct_addr, - sizeof (struct apic_mp_cnf_hdr), PROT_READ); - if (!hdrp) - return (retval); - - /* check mp configuration table signature PCMP */ - if (hdrp->mpcnf_sig != 0x504d4350) { - psm_unmap_phys((caddr_t)hdrp, sizeof (struct apic_mp_cnf_hdr)); - return (retval); - } - mpct_size = (int)hdrp->mpcnf_tbl_length; - - apic_set_pwroff_method_from_mpcnfhdr(hdrp); - - psm_unmap_phys((caddr_t)hdrp, sizeof (struct apic_mp_cnf_hdr)); - - if ((retval == PSM_SUCCESS) && !apic_use_acpi_madt_only) { - /* This is an ACPI machine No need for further checks */ - return (retval); - } - - /* - * Map in the entries for this machine, ie. Processor - * Entry Tables, Bus Entry Tables, etc. - * They are in fixed order following one another - */ - mpct = psm_map_phys(mpct_addr, mpct_size, PROT_READ); - if (!mpct) - return (retval); - - if (apic_checksum(mpct, mpct_size) != 0) - goto apic_fail1; - - - /*LINTED: pointer cast may result in improper alignment */ - hdrp = (struct apic_mp_cnf_hdr *)mpct; - /*LINTED: pointer cast may result in improper alignment */ - apicadr = (uint32_t *)psm_map_phys((uint32_t)hdrp->mpcnf_local_apic, - APIC_LOCAL_MEMLEN, PROT_READ | PROT_WRITE); - if (!apicadr) - goto apic_fail1; - - /* Parse all information in the tables */ - bypass_cpu_and_ioapics_in_mptables = (retval == PSM_SUCCESS); - if (apic_parse_mpct(mpct, bypass_cpu_and_ioapics_in_mptables) == - PSM_SUCCESS) - return (PSM_SUCCESS); - - for (i = 0; i < apic_io_max; i++) - psm_unmap_phys((caddr_t)apicioadr[i], APIC_IO_MEMLEN); - if (apic_cpus) - kmem_free(apic_cpus, sizeof (*apic_cpus) * apic_nproc); - if (apicadr) - psm_unmap_phys((caddr_t)apicadr, APIC_LOCAL_MEMLEN); -apic_fail1: - psm_unmap_phys(mpct, mpct_size); - return (retval); -} - -static void -apic_set_pwroff_method_from_mpcnfhdr(struct apic_mp_cnf_hdr *hdrp) -{ - int i; - - for (i = 0; i < (sizeof (apic_mps_ids) / sizeof (apic_mps_ids[0])); - i++) { - if ((strncmp(hdrp->mpcnf_oem_str, apic_mps_ids[i].oem_id, - strlen(apic_mps_ids[i].oem_id)) == 0) && - (strncmp(hdrp->mpcnf_prod_str, apic_mps_ids[i].prod_id, - strlen(apic_mps_ids[i].prod_id)) == 0)) { - - apic_poweroff_method = apic_mps_ids[i].poweroff_method; - break; - } - } - - if (apic_debug_mps_id != 0) { - cmn_err(CE_CONT, "pcplusmp: MPS OEM ID = '%c%c%c%c%c%c%c%c'" - "Product ID = '%c%c%c%c%c%c%c%c%c%c%c%c'\n", - hdrp->mpcnf_oem_str[0], - hdrp->mpcnf_oem_str[1], - hdrp->mpcnf_oem_str[2], - hdrp->mpcnf_oem_str[3], - hdrp->mpcnf_oem_str[4], - hdrp->mpcnf_oem_str[5], - hdrp->mpcnf_oem_str[6], - hdrp->mpcnf_oem_str[7], - hdrp->mpcnf_prod_str[0], - hdrp->mpcnf_prod_str[1], - hdrp->mpcnf_prod_str[2], - hdrp->mpcnf_prod_str[3], - hdrp->mpcnf_prod_str[4], - hdrp->mpcnf_prod_str[5], - hdrp->mpcnf_prod_str[6], - hdrp->mpcnf_prod_str[7], - hdrp->mpcnf_prod_str[8], - hdrp->mpcnf_prod_str[9], - hdrp->mpcnf_prod_str[10], - hdrp->mpcnf_prod_str[11]); - } -} - -static int -acpi_probe(void) -{ - int i, id, intmax, ver, index, rv; - int acpi_verboseflags = 0; - int madt_seen, madt_size; - APIC_HEADER *ap; - MADT_PROCESSOR_APIC *mpa; - MADT_IO_APIC *mia; - MADT_IO_SAPIC *misa; - MADT_INTERRUPT_OVERRIDE *mio; - MADT_NMI_SOURCE *mns; - MADT_INTERRUPT_SOURCE *mis; - MADT_LOCAL_APIC_NMI *mlan; - MADT_ADDRESS_OVERRIDE *mao; - ACPI_OBJECT_LIST arglist; - ACPI_OBJECT arg; - int sci; - iflag_t sci_flags; - volatile int32_t *ioapic; - char local_ids[NCPU]; - char proc_ids[NCPU]; - uchar_t hid; - - if (!apic_use_acpi) - return (PSM_FAILURE); - - if (AcpiGetFirmwareTable(APIC_SIG, 1, ACPI_LOGICAL_ADDRESSING, - (ACPI_TABLE_HEADER **) &acpi_mapic_dtp) != AE_OK) - return (PSM_FAILURE); - - apicadr = (uint32_t *)psm_map_phys( - (uint32_t)acpi_mapic_dtp->LocalApicAddress, - APIC_LOCAL_MEMLEN, PROT_READ | PROT_WRITE); - if (!apicadr) - return (PSM_FAILURE); - - id = apicadr[APIC_LID_REG]; - local_ids[0] = (uchar_t)(((uint_t)id) >> 24); - apic_nproc = index = 1; - CPUSET_ONLY(apic_cpumask, 0); - apic_io_max = 0; - - ap = (APIC_HEADER *) (acpi_mapic_dtp + 1); - madt_size = acpi_mapic_dtp->Length; - madt_seen = sizeof (*acpi_mapic_dtp); - - while (madt_seen < madt_size) { - switch (ap->Type) { - case APIC_PROCESSOR: - mpa = (MADT_PROCESSOR_APIC *) ap; - if (mpa->ProcessorEnabled) { - if (mpa->LocalApicId == local_ids[0]) - proc_ids[0] = mpa->ProcessorId; - else if (apic_nproc < NCPU) { - local_ids[index] = mpa->LocalApicId; - proc_ids[index] = mpa->ProcessorId; - CPUSET_ADD(apic_cpumask, index); - index++; - apic_nproc++; - } else - cmn_err(CE_WARN, "pcplusmp: exceeded " - "maximum no. of CPUs (= %d)", NCPU); - } - break; - - case APIC_IO: - mia = (MADT_IO_APIC *) ap; - if (apic_io_max < MAX_IO_APIC) { - apic_io_id[apic_io_max] = mia->IoApicId; - apic_io_vectbase[apic_io_max] = - mia->Interrupt; - ioapic = apicioadr[apic_io_max] = - (int32_t *)psm_map_phys( - (uint32_t)mia->Address, - APIC_IO_MEMLEN, PROT_READ | PROT_WRITE); - if (!ioapic) - goto cleanup; - apic_io_max++; - } - break; - - case APIC_XRUPT_OVERRIDE: - mio = (MADT_INTERRUPT_OVERRIDE *) ap; - if (acpi_isop == NULL) - acpi_isop = mio; - acpi_iso_cnt++; - break; - - case APIC_NMI: - /* UNIMPLEMENTED */ - mns = (MADT_NMI_SOURCE *) ap; - if (acpi_nmi_sp == NULL) - acpi_nmi_sp = mns; - acpi_nmi_scnt++; - - cmn_err(CE_NOTE, "!apic: nmi source: %d %d %d\n", - mns->Interrupt, mns->Polarity, - mns->TriggerMode); - break; - - case APIC_LOCAL_NMI: - /* UNIMPLEMENTED */ - mlan = (MADT_LOCAL_APIC_NMI *) ap; - if (acpi_nmi_cp == NULL) - acpi_nmi_cp = mlan; - acpi_nmi_ccnt++; - - cmn_err(CE_NOTE, "!apic: local nmi: %d %d %d %d\n", - mlan->ProcessorId, mlan->Polarity, - mlan->TriggerMode, mlan->Lint); - break; - - case APIC_ADDRESS_OVERRIDE: - /* UNIMPLEMENTED */ - mao = (MADT_ADDRESS_OVERRIDE *) ap; - cmn_err(CE_NOTE, "!apic: address override: %lx\n", - (long)mao->Address); - break; - - case APIC_IO_SAPIC: - /* UNIMPLEMENTED */ - misa = (MADT_IO_SAPIC *) ap; - - cmn_err(CE_NOTE, "!apic: io sapic: %d %d %lx\n", - misa->IoSapicId, misa->InterruptBase, - (long)misa->Address); - break; - - case APIC_XRUPT_SOURCE: - /* UNIMPLEMENTED */ - mis = (MADT_INTERRUPT_SOURCE *) ap; - - cmn_err(CE_NOTE, - "!apic: irq source: %d %d %d %d %d %d %d\n", - mis->ProcessorId, mis->ProcessorEid, - mis->Interrupt, mis->Polarity, - mis->TriggerMode, mis->InterruptType, - mis->IoSapicVector); - break; - case APIC_RESERVED: - default: - break; /* ignore unknown items as per ACPI spec */ - } - - /* advance to next entry */ - madt_seen += ap->Length; - ap = (APIC_HEADER *)(((char *)ap) + ap->Length); - } - - if ((apic_cpus = kmem_zalloc(sizeof (*apic_cpus) * apic_nproc, - KM_NOSLEEP)) == NULL) - goto cleanup; - - /* - * ACPI doesn't provide the local apic ver, get it directly from the - * local apic - */ - ver = apicadr[APIC_VERS_REG]; - for (i = 0; i < apic_nproc; i++) { - apic_cpus[i].aci_local_id = local_ids[i]; - apic_cpus[i].aci_local_ver = (uchar_t)(ver & 0xFF); - } - for (i = 0; i < apic_io_max; i++) { - ioapic = apicioadr[i]; - - /* - * need to check Sitka on the following acpi problem - * On the Sitka, the ioapic's apic_id field isn't reporting - * the actual io apic id. We have reported this problem - * to Intel. Until they fix the problem, we will get the - * actual id directly from the ioapic. - */ - ioapic[APIC_IO_REG] = APIC_ID_CMD; - id = ioapic[APIC_IO_DATA]; - hid = (uchar_t)(((uint_t)id) >> 24); - - if (hid != apic_io_id[i]) { - if (apic_io_id[i] == 0) - apic_io_id[i] = hid; - else { /* set ioapic id to whatever reported by ACPI */ - id = ((int32_t)apic_io_id[i]) << 24; - ioapic[APIC_IO_REG] = APIC_ID_CMD; - ioapic[APIC_IO_DATA] = id; - } - } - ioapic[APIC_IO_REG] = APIC_VERS_CMD; - ver = ioapic[APIC_IO_DATA]; - apic_io_ver[i] = (uchar_t)(ver & 0xff); - intmax = (ver >> 16) & 0xff; - apic_io_vectend[i] = apic_io_vectbase[i] + intmax; - if (apic_first_avail_irq <= apic_io_vectend[i]) - apic_first_avail_irq = apic_io_vectend[i] + 1; - } - - - /* - * Process SCI configuration here - * An error may be returned here if - * acpi-user-options specifies legacy mode - * (no SCI, no ACPI mode) - */ - if (acpica_get_sci(&sci, &sci_flags) != AE_OK) - sci = -1; - - /* - * Now call acpi_init() to generate namespaces - * If this fails, we don't attempt to use ACPI - * even if we were able to get a MADT above - */ - if (acpica_init() != AE_OK) - goto cleanup; - - /* - * Squirrel away the SCI and flags for later on - * in apic_picinit() when we're ready - */ - apic_sci_vect = sci; - apic_sci_flags = sci_flags; - - if (apic_verbose & APIC_VERBOSE_IRQ_FLAG) - acpi_verboseflags |= PSM_VERBOSE_IRQ_FLAG; - - if (apic_verbose & APIC_VERBOSE_POWEROFF_FLAG) - acpi_verboseflags |= PSM_VERBOSE_POWEROFF_FLAG; - - if (apic_verbose & APIC_VERBOSE_POWEROFF_PAUSE_FLAG) - acpi_verboseflags |= PSM_VERBOSE_POWEROFF_PAUSE_FLAG; - - if (acpi_psm_init(apic_psm_info.p_mach_idstring, acpi_verboseflags) == - ACPI_PSM_FAILURE) - goto cleanup; - - /* Enable ACPI APIC interrupt routing */ - arglist.Count = 1; - arglist.Pointer = &arg; - arg.Type = ACPI_TYPE_INTEGER; - arg.Integer.Value = ACPI_APIC_MODE; /* 1 */ - rv = AcpiEvaluateObject(NULL, "\\_PIC", &arglist, NULL); - if (rv == AE_OK) { - build_reserved_irqlist((uchar_t *)apic_reserved_irqlist); - apic_enable_acpi = 1; - if (apic_use_acpi_madt_only) { - cmn_err(CE_CONT, - "?Using ACPI for CPU/IOAPIC information ONLY\n"); - } - return (PSM_SUCCESS); - } - /* if setting APIC mode failed above, we fall through to cleanup */ - -cleanup: - if (apicadr != NULL) { - psm_unmap_phys((caddr_t)apicadr, APIC_LOCAL_MEMLEN); - apicadr = NULL; - } - apic_nproc = 0; - for (i = 0; i < apic_io_max; i++) { - psm_unmap_phys((caddr_t)apicioadr[i], APIC_IO_MEMLEN); - apicioadr[i] = NULL; - } - apic_io_max = 0; - acpi_isop = NULL; - acpi_iso_cnt = 0; - acpi_nmi_sp = NULL; - acpi_nmi_scnt = 0; - acpi_nmi_cp = NULL; - acpi_nmi_ccnt = 0; - return (PSM_FAILURE); + return (apic_probe_common(apic_psm_info.p_mach_idstring)); } -/* - * Handle default configuration. Fill in reqd global variables & tables - * Fill all details as MP table does not give any more info - */ -static int -apic_handle_defconf() -{ - uint_t lid; - - /*LINTED: pointer cast may result in improper alignment */ - apicioadr[0] = (int32_t *)psm_map_phys(APIC_IO_ADDR, - APIC_IO_MEMLEN, PROT_READ | PROT_WRITE); - /*LINTED: pointer cast may result in improper alignment */ - apicadr = (uint32_t *)psm_map_phys(APIC_LOCAL_ADDR, - APIC_LOCAL_MEMLEN, PROT_READ | PROT_WRITE); - apic_cpus = (apic_cpus_info_t *) - kmem_zalloc(sizeof (*apic_cpus) * 2, KM_NOSLEEP); - if ((!apicadr) || (!apicioadr[0]) || (!apic_cpus)) - goto apic_handle_defconf_fail; - CPUSET_ONLY(apic_cpumask, 0); - CPUSET_ADD(apic_cpumask, 1); - apic_nproc = 2; - lid = apicadr[APIC_LID_REG]; - apic_cpus[0].aci_local_id = (uchar_t)(lid >> APIC_ID_BIT_OFFSET); - /* - * According to the PC+MP spec 1.1, the local ids - * for the default configuration has to be 0 or 1 - */ - if (apic_cpus[0].aci_local_id == 1) - apic_cpus[1].aci_local_id = 0; - else if (apic_cpus[0].aci_local_id == 0) - apic_cpus[1].aci_local_id = 1; - else - goto apic_handle_defconf_fail; - - apic_io_id[0] = 2; - apic_io_max = 1; - if (apic_defconf >= 5) { - apic_cpus[0].aci_local_ver = APIC_INTEGRATED_VERS; - apic_cpus[1].aci_local_ver = APIC_INTEGRATED_VERS; - apic_io_ver[0] = APIC_INTEGRATED_VERS; - } else { - apic_cpus[0].aci_local_ver = 0; /* 82489 DX */ - apic_cpus[1].aci_local_ver = 0; - apic_io_ver[0] = 0; - } - if (apic_defconf == 2 || apic_defconf == 3 || apic_defconf == 6) - eisa_level_intr_mask = (inb(EISA_LEVEL_CNTL + 1) << 8) | - inb(EISA_LEVEL_CNTL) | ((uint_t)INT32_MAX + 1); - return (PSM_SUCCESS); - -apic_handle_defconf_fail: - if (apic_cpus) - kmem_free(apic_cpus, sizeof (*apic_cpus) * 2); - if (apicadr) - psm_unmap_phys((caddr_t)apicadr, APIC_LOCAL_MEMLEN); - if (apicioadr[0]) - psm_unmap_phys((caddr_t)apicioadr[0], APIC_IO_MEMLEN); - return (PSM_FAILURE); -} - -/* Parse the entries in MP configuration table and collect info that we need */ -static int -apic_parse_mpct(caddr_t mpct, int bypass_cpus_and_ioapics) -{ - struct apic_procent *procp; - struct apic_bus *busp; - struct apic_io_entry *ioapicp; - struct apic_io_intr *intrp; - volatile int32_t *ioapic; - uint_t lid; - int id; - uchar_t hid; - - /*LINTED: pointer cast may result in improper alignment */ - procp = (struct apic_procent *)(mpct + sizeof (struct apic_mp_cnf_hdr)); - - /* No need to count cpu entries if we won't use them */ - if (!bypass_cpus_and_ioapics) { - - /* Find max # of CPUS and allocate structure accordingly */ - apic_nproc = 0; - CPUSET_ZERO(apic_cpumask); - while (procp->proc_entry == APIC_CPU_ENTRY) { - if (procp->proc_cpuflags & CPUFLAGS_EN) { - if (apic_nproc < NCPU) - CPUSET_ADD(apic_cpumask, apic_nproc); - apic_nproc++; - } - procp++; - } - if (apic_nproc > NCPU) - cmn_err(CE_WARN, "pcplusmp: exceeded " - "maximum no. of CPUs (= %d)", NCPU); - if (!apic_nproc || !(apic_cpus = (apic_cpus_info_t *) - kmem_zalloc(sizeof (*apic_cpus)*apic_nproc, KM_NOSLEEP))) - return (PSM_FAILURE); - } - - /*LINTED: pointer cast may result in improper alignment */ - procp = (struct apic_procent *)(mpct + sizeof (struct apic_mp_cnf_hdr)); - - /* - * start with index 1 as 0 needs to be filled in with Boot CPU, but - * if we're bypassing this information, it has already been filled - * in by acpi_probe(), so don't overwrite it. - */ - if (!bypass_cpus_and_ioapics) - apic_nproc = 1; - - while (procp->proc_entry == APIC_CPU_ENTRY) { - /* check whether the cpu exists or not */ - if (!bypass_cpus_and_ioapics && - procp->proc_cpuflags & CPUFLAGS_EN) { - if (procp->proc_cpuflags & CPUFLAGS_BP) { /* Boot CPU */ - lid = apicadr[APIC_LID_REG]; - apic_cpus[0].aci_local_id = procp->proc_apicid; - if (apic_cpus[0].aci_local_id != - (uchar_t)(lid >> APIC_ID_BIT_OFFSET)) { - return (PSM_FAILURE); - } - apic_cpus[0].aci_local_ver = - procp->proc_version; - } else { - - apic_cpus[apic_nproc].aci_local_id = - procp->proc_apicid; - apic_cpus[apic_nproc].aci_local_ver = - procp->proc_version; - apic_nproc++; - - } - } - procp++; - } - - /* - * Save start of bus entries for later use. - * Get EISA level cntrl if EISA bus is present. - * Also get the CPI bus id for single CPI bus case - */ - apic_busp = busp = (struct apic_bus *)procp; - while (busp->bus_entry == APIC_BUS_ENTRY) { - lid = apic_find_bus_type((char *)&busp->bus_str1); - if (lid == BUS_EISA) { - eisa_level_intr_mask = (inb(EISA_LEVEL_CNTL + 1) << 8) | - inb(EISA_LEVEL_CNTL) | ((uint_t)INT32_MAX + 1); - } else if (lid == BUS_PCI) { - /* - * apic_single_pci_busid will be used only if - * apic_pic_bus_total is equal to 1 - */ - apic_pci_bus_total++; - apic_single_pci_busid = busp->bus_id; - } - busp++; - } - - ioapicp = (struct apic_io_entry *)busp; - - if (!bypass_cpus_and_ioapics) - apic_io_max = 0; - do { - if (!bypass_cpus_and_ioapics && apic_io_max < MAX_IO_APIC) { - if (ioapicp->io_flags & IOAPIC_FLAGS_EN) { - apic_io_id[apic_io_max] = ioapicp->io_apicid; - apic_io_ver[apic_io_max] = ioapicp->io_version; - /*LINTED: pointer cast may result in improper alignment */ - apicioadr[apic_io_max] = - (int32_t *)psm_map_phys( - (uint32_t)ioapicp->io_apic_addr, - APIC_IO_MEMLEN, PROT_READ | PROT_WRITE); - - if (!apicioadr[apic_io_max]) - return (PSM_FAILURE); - - ioapic = apicioadr[apic_io_max]; - ioapic[APIC_IO_REG] = APIC_ID_CMD; - id = ioapic[APIC_IO_DATA]; - hid = (uchar_t)(((uint_t)id) >> 24); - - if (hid != apic_io_id[apic_io_max]) { - if (apic_io_id[apic_io_max] == 0) - apic_io_id[apic_io_max] = hid; - else { - /* - * set ioapic id to whatever - * reported by MPS - * - * may not need to set index - * again ??? - * take it out and try - */ - - id = ((int32_t) - apic_io_id[apic_io_max]) << - 24; - - ioapic[APIC_IO_REG] = - APIC_ID_CMD; - - ioapic[APIC_IO_DATA] = id; - - } - } - apic_io_max++; - } - } - ioapicp++; - } while (ioapicp->io_entry == APIC_IO_ENTRY); - - apic_io_intrp = (struct apic_io_intr *)ioapicp; - - intrp = apic_io_intrp; - while (intrp->intr_entry == APIC_IO_INTR_ENTRY) { - if ((intrp->intr_irq > APIC_MAX_ISA_IRQ) || - (apic_find_bus(intrp->intr_busid) == BUS_PCI)) { - apic_irq_translate = 1; - break; - } - intrp++; - } - - return (PSM_SUCCESS); -} - -boolean_t -apic_cpu_in_range(int cpu) -{ - return ((cpu & ~IRQ_USER_BOUND) < apic_nproc); -} - -static struct apic_mpfps_hdr * -apic_find_fps_sig(caddr_t cptr, int len) -{ - int i; - - /* Look for the pattern "_MP_" */ - for (i = 0; i < len; i += 16) { - if ((*(cptr+i) == '_') && - (*(cptr+i+1) == 'M') && - (*(cptr+i+2) == 'P') && - (*(cptr+i+3) == '_')) - /*LINTED: pointer cast may result in improper alignment */ - return ((struct apic_mpfps_hdr *)(cptr + i)); - } - return (NULL); -} - -static int -apic_checksum(caddr_t bptr, int len) -{ - int i; - uchar_t cksum; - - cksum = 0; - for (i = 0; i < len; i++) - cksum += *bptr++; - return ((int)cksum); -} - - -/* - * Initialise vector->ipl and ipl->pri arrays. level_intr and irqtable - * are also set to NULL. vector->irq is set to a value which cannot map - * to a real irq to show that it is free. - */ void apic_init() { - int i; - int *iptr; - + int i; int j = 1; + apic_ipltopri[0] = APIC_VECTOR_PER_IPL; /* leave 0 for idle */ for (i = 0; i < (APIC_AVAIL_VECTOR / APIC_VECTOR_PER_IPL); i++) { if ((i < ((APIC_AVAIL_VECTOR / APIC_VECTOR_PER_IPL) - 1)) && @@ -1535,33 +391,7 @@ apic_init() for (; j < MAXIPL + 1; j++) /* fill up any empty ipltopri slots */ apic_ipltopri[j] = (i << APIC_IPL_SHIFT) + APIC_BASE_VECT; - - /* cpu 0 is always up */ - apic_cpus[0].aci_status = APIC_CPU_ONLINE | APIC_CPU_INTR_ENABLE; - - iptr = (int *)&apic_irq_table[0]; - for (i = 0; i <= APIC_MAX_VECTOR; i++) { - apic_level_intr[i] = 0; - *iptr++ = NULL; - apic_vector_to_irq[i] = APIC_RESV_IRQ; - - /* These *must* be initted to B_TRUE! */ - apic_reprogram_info[i].done = B_TRUE; - apic_reprogram_info[i].irqp = NULL; - apic_reprogram_info[i].tries = 0; - apic_reprogram_info[i].bindcpu = 0; - } - - /* - * Allocate a dummy irq table entry for the reserved entry. - * This takes care of the race between removing an irq and - * clock detecting a CPU in that irq during interrupt load - * sampling. - */ - apic_irq_table[APIC_RESV_IRQ] = - kmem_zalloc(sizeof (apic_irq_t), KM_NOSLEEP); - - mutex_init(&airq_mutex, NULL, MUTEX_DEFAULT, NULL); + apic_init_common(); #if defined(__amd64) /* * Make cpu-specific interrupt info point to cr8pri vector @@ -1569,7 +399,6 @@ apic_init() for (i = 0; i <= MAXIPL; i++) apic_cr8pri[i] = apic_ipltopri[i] >> APIC_IPL_SHIFT; CPU->cpu_pri_data = apic_cr8pri; - intpri_use_cr8 = 1; #endif /* __amd64 */ } @@ -1750,11 +579,8 @@ apic_disable_local_apic() static void apic_picinit(void) { - int i, j, iflag; + int i, j; uint_t isr; - volatile int32_t *ioapic; - apic_irq_t *irqptr; - struct intrspec ispec; /* * On UniSys Model 6520, the BIOS leaves vector 0x20 isr @@ -1778,8 +604,6 @@ apic_picinit(void) apic_flag = 1; LOCK_INIT_CLEAR(&apic_gethrtime_lock); LOCK_INIT_CLEAR(&apic_ioapic_lock); - LOCK_INIT_CLEAR(&apic_revector_lock); - LOCK_INIT_CLEAR(&apic_defer_reprogram_lock); LOCK_INIT_CLEAR(&apic_error_lock); picsetup(); /* initialise the 8259 */ @@ -1799,59 +623,18 @@ apic_picinit(void) outb(APIC_IMCR_P2, (uchar_t)APIC_IMCR_APIC); } - /* mask interrupt vectors */ - for (j = 0; j < apic_io_max; j++) { - int intin_max; - ioapic = apicioadr[j]; - ioapic[APIC_IO_REG] = APIC_VERS_CMD; - /* Bits 23-16 define the maximum redirection entries */ - intin_max = (ioapic[APIC_IO_DATA] >> 16) & 0xff; - for (i = 0; i < intin_max; i++) { - ioapic[APIC_IO_REG] = APIC_RDT_CMD + 2 * i; - ioapic[APIC_IO_DATA] = AV_MASK; - } - } - - /* - * Hack alert: deal with ACPI SCI interrupt chicken/egg here - */ - if (apic_sci_vect > 0) { - /* - * acpica has already done add_avintr(); we just - * to finish the job by mimicing translate_irq() - * - * Fake up an intrspec and setup the tables - */ - ispec.intrspec_vec = apic_sci_vect; - ispec.intrspec_pri = SCI_IPL; - - if (apic_setup_irq_table(NULL, apic_sci_vect, NULL, - &ispec, &apic_sci_flags, DDI_INTR_TYPE_FIXED) < 0) { - cmn_err(CE_WARN, "!apic: SCI setup failed"); - return; - } - irqptr = apic_irq_table[apic_sci_vect]; - - iflag = intr_clear(); - lock_set(&apic_ioapic_lock); - - /* Program I/O APIC */ - (void) apic_setup_io_intr(irqptr, apic_sci_vect, B_FALSE); - - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - - irqptr->airq_share++; - } + ioapic_init_intr(IOAPIC_MASK); } -static void -apic_cpu_start(processorid_t cpun, caddr_t rm_code) +/*ARGSUSED1*/ +static int +apic_cpu_start(processorid_t cpun, caddr_t arg) { int loop_count; uint32_t vector; - uint_t cpu_id, iflag; + uint_t cpu_id; + ulong_t iflag; cpu_id = apic_cpus[cpun].aci_local_id; @@ -1890,7 +673,6 @@ apic_cpu_start(processorid_t cpun, caddr_t rm_code) if (apic_cpus[cpun].aci_local_ver >= APIC_INTEGRATED_VERS) { /* integrated apic */ - rm_code = (caddr_t)(uintptr_t)rm_platter_pa; vector = (rm_platter_pa >> MMU_PAGESHIFT) & (APIC_VECTOR_MASK | APIC_IPL_MASK); @@ -1906,6 +688,7 @@ apic_cpu_start(processorid_t cpun, caddr_t rm_code) drv_usecwait(200); /* 20 micro sec */ } intr_restore(iflag); + return (0); } @@ -1937,7 +720,8 @@ apic_intr_enter(int ipl, int *vectorp) { uchar_t vector; int nipl; - int irq, iflag; + int irq; + ulong_t iflag; apic_cpus_info_t *cpu_infop; /* @@ -2029,7 +813,7 @@ apic_intr_enter(int ipl, int *vectorp) return (nipl); } -static void +void apic_intr_exit(int prev_ipl, int irq) { apic_cpus_info_t *cpu_infop; @@ -2080,7 +864,7 @@ static void apic_set_softintr(int ipl) { int vector; - uint_t flag; + ulong_t flag; vector = apic_resv_vector[ipl]; @@ -2102,7 +886,7 @@ static void apic_send_ipi(int cpun, int ipl) { int vector; - uint_t flag; + ulong_t flag; vector = apic_resv_vector[ipl]; @@ -2196,11 +980,11 @@ gettime_again: static hrtime_t apic_gethrtime() { - int curr_timeval, countval, elapsed_ticks, oflags; + int curr_timeval, countval, elapsed_ticks; int old_hrtime_stamp, status; hrtime_t temp; uchar_t cpun; - + ulong_t oflags; /* * In one-shot mode, we do not keep time, so if anyone @@ -2326,283 +1110,17 @@ apic_nmi_intr(caddr_t arg) } } -/* - * Add mask bits to disable interrupt vector from happening - * at or above IPL. In addition, it should remove mask bits - * to enable interrupt vectors below the given IPL. - * - * Both add and delspl are complicated by the fact that different interrupts - * may share IRQs. This can happen in two ways. - * 1. The same H/W line is shared by more than 1 device - * 1a. with interrupts at different IPLs - * 1b. with interrupts at same IPL - * 2. We ran out of vectors at a given IPL and started sharing vectors. - * 1b and 2 should be handled gracefully, except for the fact some ISRs - * will get called often when no interrupt is pending for the device. - * For 1a, we just hope that the machine blows up with the person who - * set it up that way!. In the meantime, we handle it at the higher IPL. - */ /*ARGSUSED*/ static int apic_addspl(int irqno, int ipl, int min_ipl, int max_ipl) { - uchar_t vector; - int iflag; - apic_irq_t *irqptr, *irqheadptr; - int irqindex; - - ASSERT(max_ipl <= UCHAR_MAX); - irqindex = IRQINDEX(irqno); - - if ((irqindex == -1) || (!apic_irq_table[irqindex])) - return (PSM_FAILURE); - - mutex_enter(&airq_mutex); - irqptr = irqheadptr = apic_irq_table[irqindex]; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_addspl: dip=0x%p type=%d irqno=0x%x " - "vector=0x%x\n", (void *)irqptr->airq_dip, - irqptr->airq_mps_intr_index, irqno, irqptr->airq_vector)); - - while (irqptr) { - if (VIRTIRQ(irqindex, irqptr->airq_share_id) == irqno) - break; - irqptr = irqptr->airq_next; - } - irqptr->airq_share++; - - mutex_exit(&airq_mutex); - - /* return if it is not hardware interrupt */ - if (irqptr->airq_mps_intr_index == RESERVE_INDEX) - return (PSM_SUCCESS); - - /* Or if there are more interupts at a higher IPL */ - if (ipl != max_ipl) - return (PSM_SUCCESS); - - /* - * if apic_picinit() has not been called yet, just return. - * At the end of apic_picinit(), we will call setup_io_intr(). - */ - - if (!apic_flag) - return (PSM_SUCCESS); - - /* - * Upgrade vector if max_ipl is not earlier ipl. If we cannot allocate, - * return failure. Not very elegant, but then we hope the - * machine will blow up with ... - */ - if (irqptr->airq_ipl != max_ipl) { - vector = apic_allocate_vector(max_ipl, irqindex, 1); - if (vector == 0) { - irqptr->airq_share--; - return (PSM_FAILURE); - } - irqptr = irqheadptr; - apic_mark_vector(irqptr->airq_vector, vector); - while (irqptr) { - irqptr->airq_vector = vector; - irqptr->airq_ipl = (uchar_t)max_ipl; - /* - * reprogram irq being added and every one else - * who is not in the UNINIT state - */ - if ((VIRTIRQ(irqindex, irqptr->airq_share_id) == - irqno) || (irqptr->airq_temp_cpu != IRQ_UNINIT)) { - apic_record_rdt_entry(irqptr, irqindex); - - iflag = intr_clear(); - lock_set(&apic_ioapic_lock); - - (void) apic_setup_io_intr(irqptr, irqindex, - B_FALSE); - - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - } - irqptr = irqptr->airq_next; - } - return (PSM_SUCCESS); - } - - ASSERT(irqptr); - - iflag = intr_clear(); - lock_set(&apic_ioapic_lock); - - (void) apic_setup_io_intr(irqptr, irqindex, B_FALSE); - - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - - return (PSM_SUCCESS); + return (apic_addspl_common(irqno, ipl, min_ipl, max_ipl)); } -/* - * Recompute mask bits for the given interrupt vector. - * If there is no interrupt servicing routine for this - * vector, this function should disable interrupt vector - * from happening at all IPLs. If there are still - * handlers using the given vector, this function should - * disable the given vector from happening below the lowest - * IPL of the remaining hadlers. - */ -/*ARGSUSED*/ static int apic_delspl(int irqno, int ipl, int min_ipl, int max_ipl) { - uchar_t vector, bind_cpu; - int iflag, intin, irqindex; - volatile int32_t *ioapic; - apic_irq_t *irqptr, *irqheadptr; - - mutex_enter(&airq_mutex); - irqindex = IRQINDEX(irqno); - irqptr = irqheadptr = apic_irq_table[irqindex]; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_delspl: dip=0x%p type=%d irqno=0x%x " - "vector=0x%x\n", (void *)irqptr->airq_dip, - irqptr->airq_mps_intr_index, irqno, irqptr->airq_vector)); - - while (irqptr) { - if (VIRTIRQ(irqindex, irqptr->airq_share_id) == irqno) - break; - irqptr = irqptr->airq_next; - } - ASSERT(irqptr); - - irqptr->airq_share--; - - mutex_exit(&airq_mutex); - - if (ipl < max_ipl) - return (PSM_SUCCESS); - - /* return if it is not hardware interrupt */ - if (irqptr->airq_mps_intr_index == RESERVE_INDEX) - return (PSM_SUCCESS); - - if (!apic_flag) { - /* - * Clear irq_struct. If two devices shared an intpt - * line & 1 unloaded before picinit, we are hosed. But, then - * we hope the machine will ... - */ - irqptr->airq_mps_intr_index = FREE_INDEX; - irqptr->airq_temp_cpu = IRQ_UNINIT; - apic_free_vector(irqptr->airq_vector); - return (PSM_SUCCESS); - } - /* - * Downgrade vector to new max_ipl if needed.If we cannot allocate, - * use old IPL. Not very elegant, but then we hope ... - */ - if ((irqptr->airq_ipl != max_ipl) && (max_ipl != PSM_INVALID_IPL)) { - apic_irq_t *irqp; - if (vector = apic_allocate_vector(max_ipl, irqno, 1)) { - apic_mark_vector(irqheadptr->airq_vector, vector); - irqp = irqheadptr; - while (irqp) { - irqp->airq_vector = vector; - irqp->airq_ipl = (uchar_t)max_ipl; - if (irqp->airq_temp_cpu != IRQ_UNINIT) { - apic_record_rdt_entry(irqp, irqindex); - - iflag = intr_clear(); - lock_set(&apic_ioapic_lock); - - (void) apic_setup_io_intr(irqp, - irqindex, B_FALSE); - - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - } - irqp = irqp->airq_next; - } - } - } - - if (irqptr->airq_share) - return (PSM_SUCCESS); - - iflag = intr_clear(); - lock_set(&apic_ioapic_lock); - - /* Disable the MSI/X vector */ - if (APIC_IS_MSI_OR_MSIX_INDEX(irqptr->airq_mps_intr_index)) { - int type = (irqptr->airq_mps_intr_index == MSI_INDEX) ? - DDI_INTR_TYPE_MSI : DDI_INTR_TYPE_MSIX; - - /* - * Make sure we only disable on the last - * of the multi-MSI support - */ - if (i_ddi_intr_get_current_nintrs(irqptr->airq_dip) == 1) { - (void) apic_pci_msi_unconfigure(irqptr->airq_dip, - type, irqptr->airq_ioapicindex); - (void) apic_pci_msi_disable_mode(irqptr->airq_dip, - type, irqptr->airq_ioapicindex); - } - } else { - ioapic = apicioadr[irqptr->airq_ioapicindex]; - intin = irqptr->airq_intin_no; - ioapic[APIC_IO_REG] = APIC_RDT_CMD + 2 * intin; - ioapic[APIC_IO_DATA] = AV_MASK; - } - - if (max_ipl == PSM_INVALID_IPL) { - ASSERT(irqheadptr == irqptr); - bind_cpu = irqptr->airq_temp_cpu; - if (((uchar_t)bind_cpu != IRQ_UNBOUND) && - ((uchar_t)bind_cpu != IRQ_UNINIT)) { - ASSERT((bind_cpu & ~IRQ_USER_BOUND) < apic_nproc); - if (bind_cpu & IRQ_USER_BOUND) { - /* If hardbound, temp_cpu == cpu */ - bind_cpu &= ~IRQ_USER_BOUND; - apic_cpus[bind_cpu].aci_bound--; - } else - apic_cpus[bind_cpu].aci_temp_bound--; - } - irqptr->airq_temp_cpu = IRQ_UNINIT; - irqptr->airq_mps_intr_index = FREE_INDEX; - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - apic_free_vector(irqptr->airq_vector); - return (PSM_SUCCESS); - } - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - - mutex_enter(&airq_mutex); - if ((irqptr == apic_irq_table[irqindex])) { - apic_irq_t *oldirqptr; - /* Move valid irq entry to the head */ - irqheadptr = oldirqptr = irqptr; - irqptr = irqptr->airq_next; - ASSERT(irqptr); - while (irqptr) { - if (irqptr->airq_mps_intr_index != FREE_INDEX) - break; - oldirqptr = irqptr; - irqptr = irqptr->airq_next; - } - /* remove all invalid ones from the beginning */ - apic_irq_table[irqindex] = irqptr; - /* - * and link them back after the head. The invalid ones - * begin with irqheadptr and end at oldirqptr - */ - oldirqptr->airq_next = irqptr->airq_next; - irqptr->airq_next = irqheadptr; - } - mutex_exit(&airq_mutex); - - irqptr->airq_temp_cpu = IRQ_UNINIT; - irqptr->airq_mps_intr_index = FREE_INDEX; - - return (PSM_SUCCESS); + return (apic_delspl_common(irqno, ipl, min_ipl, max_ipl)); } /* @@ -2627,22 +1145,23 @@ apic_softlvl_to_irq(int ipl) static int apic_post_cpu_start() { - int i, cpun, iflag; + int i, cpun; + ulong_t iflag; apic_irq_t *irq_ptr; + splx(ipltospl(LOCK_LEVEL)); apic_init_intr(); /* * since some systems don't enable the internal cache on the non-boot * cpus, so we have to enable them here */ - setcr0(getcr0() & ~(0x60000000)); + setcr0(getcr0() & ~(CR0_CD | CR0_NW)); while (get_apic_cmd1() & AV_PENDING) apic_ret(); cpun = psm_get_cpu_id(); - apic_cpus[cpun].aci_status = APIC_CPU_ONLINE | APIC_CPU_INTR_ENABLE; for (i = apic_min_device_irq; i <= apic_max_device_irq; i++) { @@ -2665,7 +1184,6 @@ apic_post_cpu_start() } } - apicadr[APIC_DIVIDE_REG] = apic_divide_reg_init; return (PSM_SUCCESS); } @@ -2740,7 +1258,7 @@ apic_calibrate(volatile uint32_t *addr, uint16_t *pit_ticks_adj) uint8_t pit_tick_lo; uint16_t pit_tick, target_pit_tick; uint32_t start_apic_tick, end_apic_tick; - int iflag; + ulong_t iflag; addr += APIC_CURR_COUNT; @@ -2813,7 +1331,7 @@ apic_clkinit(int hertz) /* first time calibrate on CPU0 only */ apicadr[APIC_DIVIDE_REG] = apic_divide_reg_init; - apicadr[APIC_INIT_COUNT] = APIC_MAXVAL; /* start counting */ + apicadr[APIC_INIT_COUNT] = APIC_MAXVAL; apic_ticks = apic_calibrate(apicadr, &pit_ticks_adj); /* total number of PIT ticks corresponding to apic_ticks */ @@ -2826,7 +1344,7 @@ apic_clkinit(int hertz) * apic_ticks / (pitticks / PIT_HZ) = apic_ticks_per_s * (apic_ticks * PIT_HZ) / pitticks = apic_ticks_per_s * apic_ticks_per_ns = (apic_ticks * PIT_HZ) / (pitticks * 10^9) - * apic_ticks_per_SFns = + * pic_ticks_per_SFns = * (SF * apic_ticks * PIT_HZ) / (pitticks * 10^9) */ apic_ticks_per_SFnsecs = @@ -2890,10 +1408,10 @@ apic_preshutdown(int cmd, int fcn) static void apic_shutdown(int cmd, int fcn) { - int iflag, restarts, attempts; - int i, j; - volatile int32_t *ioapic; + int restarts, attempts; + int i; uchar_t byte; + ulong_t iflag; /* Send NMI to all CPUs except self to do per processor shutdown */ iflag = intr_clear(); @@ -2907,18 +1425,8 @@ apic_shutdown(int cmd, int fcn) outb(CMOS_ADDR, SSB); outb(CMOS_DATA, 0); } - /* Disable the I/O APIC redirection entries */ - for (j = 0; j < apic_io_max; j++) { - int intin_max; - ioapic = apicioadr[j]; - ioapic[APIC_IO_REG] = APIC_VERS_CMD; - /* Bits 23-16 define the maximum redirection entries */ - intin_max = (ioapic[APIC_IO_DATA] >> 16) & 0xff; - for (i = 0; i < intin_max; i++) { - ioapic[APIC_IO_REG] = APIC_RDT_CMD + 2 * i; - ioapic[APIC_IO_DATA] = AV_MASK; - } - } + + ioapic_disable_redirection(); /* disable apic mode if imcr present */ if (apic_imcrp) { @@ -3077,8 +1585,9 @@ restart_sitka_bmc: static int apic_disable_intr(processorid_t cpun) { - int bind_cpu = 0, i, hardbound = 0, iflag; + int bind_cpu = 0, i, hardbound = 0; apic_irq_t *irq_ptr; + ulong_t iflag; iflag = intr_clear(); lock_set(&apic_ioapic_lock); @@ -3120,8 +1629,7 @@ apic_disable_intr(processorid_t cpun) if (irq_ptr->airq_temp_cpu == cpun) { do { - apic_next_bind_cpu += 2; - bind_cpu = apic_next_bind_cpu / 2; + bind_cpu = apic_next_bind_cpu++; if (bind_cpu >= apic_nproc) { apic_next_bind_cpu = 1; bind_cpu = 0; @@ -3147,8 +1655,9 @@ apic_disable_intr(processorid_t cpun) static void apic_enable_intr(processorid_t cpun) { - int i, iflag; + int i; apic_irq_t *irq_ptr; + ulong_t iflag; iflag = intr_clear(); lock_set(&apic_ioapic_lock); @@ -3169,1912 +1678,6 @@ apic_enable_intr(processorid_t cpun) intr_restore(iflag); } -/* - * apic_introp_xlate() replaces apic_translate_irq() and is - * called only from apic_intr_ops(). With the new ADII framework, - * the priority can no longer be retrieved through i_ddi_get_intrspec(). - * It has to be passed in from the caller. - */ -int -apic_introp_xlate(dev_info_t *dip, struct intrspec *ispec, int type) -{ - char dev_type[16]; - int dev_len, pci_irq, newirq, bustype, devid, busid, i; - int irqno = ispec->intrspec_vec; - ddi_acc_handle_t cfg_handle; - uchar_t ipin; - struct apic_io_intr *intrp; - iflag_t intr_flag; - APIC_HEADER *hp; - MADT_INTERRUPT_OVERRIDE *isop; - apic_irq_t *airqp; - int parent_is_pci_or_pciex = 0; - int child_is_pciex = 0; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_introp_xlate: dip=0x%p name=%s " - "type=%d irqno=0x%x\n", (void *)dip, ddi_get_name(dip), type, - irqno)); - - dev_len = sizeof (dev_type); - if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ddi_get_parent(dip), - DDI_PROP_DONTPASS, "device_type", (caddr_t)dev_type, - &dev_len) == DDI_PROP_SUCCESS) { - if ((strcmp(dev_type, "pci") == 0) || - (strcmp(dev_type, "pciex") == 0)) - parent_is_pci_or_pciex = 1; - } - - if (parent_is_pci_or_pciex && ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "pcie-capid-pointer", PCI_CAP_NEXT_PTR_NULL) != - PCI_CAP_NEXT_PTR_NULL) { - child_is_pciex = 1; - } - - if (DDI_INTR_IS_MSI_OR_MSIX(type)) { - if ((airqp = apic_find_irq(dip, ispec, type)) != NULL) { - airqp->airq_iflag.bustype = - child_is_pciex ? BUS_PCIE : BUS_PCI; - return (apic_vector_to_irq[airqp->airq_vector]); - } - return (apic_setup_irq_table(dip, irqno, NULL, ispec, - NULL, type)); - } - - bustype = 0; - - /* check if we have already translated this irq */ - mutex_enter(&airq_mutex); - newirq = apic_min_device_irq; - for (; newirq <= apic_max_device_irq; newirq++) { - airqp = apic_irq_table[newirq]; - while (airqp) { - if ((airqp->airq_dip == dip) && - (airqp->airq_origirq == irqno) && - (airqp->airq_mps_intr_index != FREE_INDEX)) { - - mutex_exit(&airq_mutex); - return (VIRTIRQ(newirq, airqp->airq_share_id)); - } - airqp = airqp->airq_next; - } - } - mutex_exit(&airq_mutex); - - if (apic_defconf) - goto defconf; - - if ((dip == NULL) || (!apic_irq_translate && !apic_enable_acpi)) - goto nonpci; - - if (parent_is_pci_or_pciex) { - /* pci device */ - if (acpica_get_bdf(dip, &busid, &devid, NULL) != 0) - goto nonpci; - if (busid == 0 && apic_pci_bus_total == 1) - busid = (int)apic_single_pci_busid; - - if (pci_config_setup(dip, &cfg_handle) != DDI_SUCCESS) - goto nonpci; - ipin = pci_config_get8(cfg_handle, PCI_CONF_IPIN) - PCI_INTA; - pci_config_teardown(&cfg_handle); - if (apic_enable_acpi && !apic_use_acpi_madt_only) { - if (apic_acpi_translate_pci_irq(dip, busid, devid, - ipin, &pci_irq, &intr_flag) != ACPI_PSM_SUCCESS) - goto nonpci; - - intr_flag.bustype = child_is_pciex ? BUS_PCIE : BUS_PCI; - if ((newirq = apic_setup_irq_table(dip, pci_irq, NULL, - ispec, &intr_flag, type)) == -1) - goto nonpci; - return (newirq); - } else { - pci_irq = ((devid & 0x1f) << 2) | (ipin & 0x3); - if ((intrp = apic_find_io_intr_w_busid(pci_irq, busid)) - == NULL) { - if ((pci_irq = apic_handle_pci_pci_bridge(dip, - devid, ipin, &intrp)) == -1) - goto nonpci; - } - if ((newirq = apic_setup_irq_table(dip, pci_irq, intrp, - ispec, NULL, type)) == -1) - goto nonpci; - return (newirq); - } - } else if (strcmp(dev_type, "isa") == 0) - bustype = BUS_ISA; - else if (strcmp(dev_type, "eisa") == 0) - bustype = BUS_EISA; - -nonpci: - if (apic_enable_acpi && !apic_use_acpi_madt_only) { - /* search iso entries first */ - if (acpi_iso_cnt != 0) { - hp = (APIC_HEADER *)acpi_isop; - i = 0; - while (i < acpi_iso_cnt) { - if (hp->Type == APIC_XRUPT_OVERRIDE) { - isop = (MADT_INTERRUPT_OVERRIDE *)hp; - if (isop->Bus == 0 && - isop->Source == irqno) { - newirq = isop->Interrupt; - intr_flag.intr_po = - isop->Polarity; - intr_flag.intr_el = - isop->TriggerMode; - intr_flag.bustype = BUS_ISA; - - return (apic_setup_irq_table( - dip, newirq, NULL, ispec, - &intr_flag, type)); - - } - i++; - } - hp = (APIC_HEADER *)(((char *)hp) + - hp->Length); - } - } - intr_flag.intr_po = INTR_PO_ACTIVE_HIGH; - intr_flag.intr_el = INTR_EL_EDGE; - intr_flag.bustype = BUS_ISA; - return (apic_setup_irq_table(dip, irqno, NULL, ispec, - &intr_flag, type)); - } else { - if (bustype == 0) - bustype = eisa_level_intr_mask ? BUS_EISA : BUS_ISA; - for (i = 0; i < 2; i++) { - if (((busid = apic_find_bus_id(bustype)) != -1) && - ((intrp = apic_find_io_intr_w_busid(irqno, busid)) - != NULL)) { - if ((newirq = apic_setup_irq_table(dip, irqno, - intrp, ispec, NULL, type)) != -1) { - return (newirq); - } - goto defconf; - } - bustype = (bustype == BUS_EISA) ? BUS_ISA : BUS_EISA; - } - } - -/* MPS default configuration */ -defconf: - newirq = apic_setup_irq_table(dip, irqno, NULL, ispec, NULL, type); - if (newirq == -1) - return (newirq); - ASSERT(IRQINDEX(newirq) == irqno); - ASSERT(apic_irq_table[irqno]); - return (newirq); -} - - - - - - -/* - * On machines with PCI-PCI bridges, a device behind a PCI-PCI bridge - * needs special handling. We may need to chase up the device tree, - * using the PCI-PCI Bridge specification's "rotating IPIN assumptions", - * to find the IPIN at the root bus that relates to the IPIN on the - * subsidiary bus (for ACPI or MP). We may, however, have an entry - * in the MP table or the ACPI namespace for this device itself. - * We handle both cases in the search below. - */ -/* this is the non-acpi version */ -static int -apic_handle_pci_pci_bridge(dev_info_t *idip, int child_devno, int child_ipin, - struct apic_io_intr **intrp) -{ - dev_info_t *dipp, *dip; - int pci_irq; - ddi_acc_handle_t cfg_handle; - int bridge_devno, bridge_bus; - int ipin; - - dip = idip; - - /*CONSTCOND*/ - while (1) { - if ((dipp = ddi_get_parent(dip)) == (dev_info_t *)NULL) - return (-1); - if ((pci_config_setup(dipp, &cfg_handle) == DDI_SUCCESS) && - (pci_config_get8(cfg_handle, PCI_CONF_BASCLASS) == - PCI_CLASS_BRIDGE) && (pci_config_get8(cfg_handle, - PCI_CONF_SUBCLASS) == PCI_BRIDGE_PCI)) { - pci_config_teardown(&cfg_handle); - if (acpica_get_bdf(dipp, &bridge_bus, &bridge_devno, - NULL) != 0) - return (-1); - /* - * This is the rotating scheme that Compaq is using - * and documented in the pci to pci spec. Also, if - * the pci to pci bridge is behind another pci to - * pci bridge, then it need to keep transversing - * up until an interrupt entry is found or reach - * the top of the tree - */ - ipin = (child_devno + child_ipin) % PCI_INTD; - if (bridge_bus == 0 && apic_pci_bus_total == 1) - bridge_bus = (int)apic_single_pci_busid; - pci_irq = ((bridge_devno & 0x1f) << 2) | - (ipin & 0x3); - if ((*intrp = apic_find_io_intr_w_busid(pci_irq, - bridge_bus)) != NULL) { - return (pci_irq); - } - dip = dipp; - child_devno = bridge_devno; - child_ipin = ipin; - } else - return (-1); - } - /*LINTED: function will not fall off the bottom */ -} - - - - -static uchar_t -acpi_find_ioapic(int irq) -{ - int i; - - for (i = 0; i < apic_io_max; i++) { - if (irq >= apic_io_vectbase[i] && irq <= apic_io_vectend[i]) - return (i); - } - return (0xFF); /* shouldn't happen */ -} - -/* - * See if two irqs are compatible for sharing a vector. - * Currently we only support sharing of PCI devices. - */ -static int -acpi_intr_compatible(iflag_t iflag1, iflag_t iflag2) -{ - uint_t level1, po1; - uint_t level2, po2; - - /* Assume active high by default */ - po1 = 0; - po2 = 0; - - if (iflag1.bustype != iflag2.bustype || iflag1.bustype != BUS_PCI) - return (0); - - if (iflag1.intr_el == INTR_EL_CONFORM) - level1 = AV_LEVEL; - else - level1 = (iflag1.intr_el == INTR_EL_LEVEL) ? AV_LEVEL : 0; - - if (level1 && ((iflag1.intr_po == INTR_PO_ACTIVE_LOW) || - (iflag1.intr_po == INTR_PO_CONFORM))) - po1 = AV_ACTIVE_LOW; - - if (iflag2.intr_el == INTR_EL_CONFORM) - level2 = AV_LEVEL; - else - level2 = (iflag2.intr_el == INTR_EL_LEVEL) ? AV_LEVEL : 0; - - if (level2 && ((iflag2.intr_po == INTR_PO_ACTIVE_LOW) || - (iflag2.intr_po == INTR_PO_CONFORM))) - po2 = AV_ACTIVE_LOW; - - if ((level1 == level2) && (po1 == po2)) - return (1); - - return (0); -} - -/* - * Attempt to share vector with someone else - */ -static int -apic_share_vector(int irqno, iflag_t *intr_flagp, short intr_index, int ipl, - uchar_t ioapicindex, uchar_t ipin, apic_irq_t **irqptrp) -{ -#ifdef DEBUG - apic_irq_t *tmpirqp = NULL; -#endif /* DEBUG */ - apic_irq_t *irqptr, dummyirq; - int newirq, chosen_irq = -1, share = 127; - int lowest, highest, i; - uchar_t share_id; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_share_vector: irqno=0x%x " - "intr_index=0x%x ipl=0x%x\n", irqno, intr_index, ipl)); - - highest = apic_ipltopri[ipl] + APIC_VECTOR_MASK; - lowest = apic_ipltopri[ipl-1] + APIC_VECTOR_PER_IPL; - - if (highest < lowest) /* Both ipl and ipl-1 map to same pri */ - lowest -= APIC_VECTOR_PER_IPL; - dummyirq.airq_mps_intr_index = intr_index; - dummyirq.airq_ioapicindex = ioapicindex; - dummyirq.airq_intin_no = ipin; - if (intr_flagp) - dummyirq.airq_iflag = *intr_flagp; - apic_record_rdt_entry(&dummyirq, irqno); - for (i = lowest; i <= highest; i++) { - newirq = apic_vector_to_irq[i]; - if (newirq == APIC_RESV_IRQ) - continue; - irqptr = apic_irq_table[newirq]; - - if ((dummyirq.airq_rdt_entry & 0xFF00) != - (irqptr->airq_rdt_entry & 0xFF00)) - /* not compatible */ - continue; - - if (irqptr->airq_share < share) { - share = irqptr->airq_share; - chosen_irq = newirq; - } - } - if (chosen_irq != -1) { - /* - * Assign a share id which is free or which is larger - * than the largest one. - */ - share_id = 1; - mutex_enter(&airq_mutex); - irqptr = apic_irq_table[chosen_irq]; - while (irqptr) { - if (irqptr->airq_mps_intr_index == FREE_INDEX) { - share_id = irqptr->airq_share_id; - break; - } - if (share_id <= irqptr->airq_share_id) - share_id = irqptr->airq_share_id + 1; -#ifdef DEBUG - tmpirqp = irqptr; -#endif /* DEBUG */ - irqptr = irqptr->airq_next; - } - if (!irqptr) { - irqptr = kmem_zalloc(sizeof (apic_irq_t), KM_SLEEP); - irqptr->airq_temp_cpu = IRQ_UNINIT; - irqptr->airq_next = - apic_irq_table[chosen_irq]->airq_next; - apic_irq_table[chosen_irq]->airq_next = irqptr; -#ifdef DEBUG - tmpirqp = apic_irq_table[chosen_irq]; -#endif /* DEBUG */ - } - irqptr->airq_mps_intr_index = intr_index; - irqptr->airq_ioapicindex = ioapicindex; - irqptr->airq_intin_no = ipin; - if (intr_flagp) - irqptr->airq_iflag = *intr_flagp; - irqptr->airq_vector = apic_irq_table[chosen_irq]->airq_vector; - irqptr->airq_share_id = share_id; - apic_record_rdt_entry(irqptr, irqno); - *irqptrp = irqptr; -#ifdef DEBUG - /* shuffle the pointers to test apic_delspl path */ - if (tmpirqp) { - tmpirqp->airq_next = irqptr->airq_next; - irqptr->airq_next = apic_irq_table[chosen_irq]; - apic_irq_table[chosen_irq] = irqptr; - } -#endif /* DEBUG */ - mutex_exit(&airq_mutex); - return (VIRTIRQ(chosen_irq, share_id)); - } - return (-1); -} - -/* - * - */ -static int -apic_setup_irq_table(dev_info_t *dip, int irqno, struct apic_io_intr *intrp, - struct intrspec *ispec, iflag_t *intr_flagp, int type) -{ - int origirq = ispec->intrspec_vec; - uchar_t ipl = ispec->intrspec_pri; - int newirq, intr_index; - uchar_t ipin, ioapic, ioapicindex, vector; - apic_irq_t *irqptr; - major_t major; - dev_info_t *sdip; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_setup_irq_table: dip=0x%p type=%d " - "irqno=0x%x origirq=0x%x\n", (void *)dip, type, irqno, origirq)); - - ASSERT(ispec != NULL); - - major = (dip != NULL) ? ddi_name_to_major(ddi_get_name(dip)) : 0; - - if (DDI_INTR_IS_MSI_OR_MSIX(type)) { - /* MSI/X doesn't need to setup ioapic stuffs */ - ioapicindex = 0xff; - ioapic = 0xff; - ipin = (uchar_t)0xff; - intr_index = (type == DDI_INTR_TYPE_MSI) ? MSI_INDEX : - MSIX_INDEX; - mutex_enter(&airq_mutex); - if ((irqno = apic_allocate_irq(apic_first_avail_irq)) == -1) { - mutex_exit(&airq_mutex); - /* need an irq for MSI/X to index into autovect[] */ - cmn_err(CE_WARN, "No interrupt irq: %s instance %d", - ddi_get_name(dip), ddi_get_instance(dip)); - return (-1); - } - mutex_exit(&airq_mutex); - - } else if (intrp != NULL) { - intr_index = (int)(intrp - apic_io_intrp); - ioapic = intrp->intr_destid; - ipin = intrp->intr_destintin; - /* Find ioapicindex. If destid was ALL, we will exit with 0. */ - for (ioapicindex = apic_io_max - 1; ioapicindex; ioapicindex--) - if (apic_io_id[ioapicindex] == ioapic) - break; - ASSERT((ioapic == apic_io_id[ioapicindex]) || - (ioapic == INTR_ALL_APIC)); - - /* check whether this intin# has been used by another irqno */ - if ((newirq = apic_find_intin(ioapicindex, ipin)) != -1) { - return (newirq); - } - - } else if (intr_flagp != NULL) { - /* ACPI case */ - intr_index = ACPI_INDEX; - ioapicindex = acpi_find_ioapic(irqno); - ASSERT(ioapicindex != 0xFF); - ioapic = apic_io_id[ioapicindex]; - ipin = irqno - apic_io_vectbase[ioapicindex]; - if (apic_irq_table[irqno] && - apic_irq_table[irqno]->airq_mps_intr_index == ACPI_INDEX) { - ASSERT(apic_irq_table[irqno]->airq_intin_no == ipin && - apic_irq_table[irqno]->airq_ioapicindex == - ioapicindex); - return (irqno); - } - - } else { - /* default configuration */ - ioapicindex = 0; - ioapic = apic_io_id[ioapicindex]; - ipin = (uchar_t)irqno; - intr_index = DEFAULT_INDEX; - } - - if (ispec == NULL) { - APIC_VERBOSE_IOAPIC((CE_WARN, "No intrspec for irqno = %x\n", - irqno)); - } else if ((vector = apic_allocate_vector(ipl, irqno, 0)) == 0) { - if ((newirq = apic_share_vector(irqno, intr_flagp, intr_index, - ipl, ioapicindex, ipin, &irqptr)) != -1) { - irqptr->airq_ipl = ipl; - irqptr->airq_origirq = (uchar_t)origirq; - irqptr->airq_dip = dip; - irqptr->airq_major = major; - sdip = apic_irq_table[IRQINDEX(newirq)]->airq_dip; - /* This is OK to do really */ - if (sdip == NULL) { - cmn_err(CE_WARN, "Sharing vectors: %s" - " instance %d and SCI", - ddi_get_name(dip), ddi_get_instance(dip)); - } else { - cmn_err(CE_WARN, "Sharing vectors: %s" - " instance %d and %s instance %d", - ddi_get_name(sdip), ddi_get_instance(sdip), - ddi_get_name(dip), ddi_get_instance(dip)); - } - return (newirq); - } - /* try high priority allocation now that share has failed */ - if ((vector = apic_allocate_vector(ipl, irqno, 1)) == 0) { - cmn_err(CE_WARN, "No interrupt vector: %s instance %d", - ddi_get_name(dip), ddi_get_instance(dip)); - return (-1); - } - } - - mutex_enter(&airq_mutex); - if (apic_irq_table[irqno] == NULL) { - irqptr = kmem_zalloc(sizeof (apic_irq_t), KM_SLEEP); - irqptr->airq_temp_cpu = IRQ_UNINIT; - apic_irq_table[irqno] = irqptr; - } else { - irqptr = apic_irq_table[irqno]; - if (irqptr->airq_mps_intr_index != FREE_INDEX) { - /* - * The slot is used by another irqno, so allocate - * a free irqno for this interrupt - */ - newirq = apic_allocate_irq(apic_first_avail_irq); - if (newirq == -1) { - mutex_exit(&airq_mutex); - return (-1); - } - irqno = newirq; - irqptr = apic_irq_table[irqno]; - if (irqptr == NULL) { - irqptr = kmem_zalloc(sizeof (apic_irq_t), - KM_SLEEP); - irqptr->airq_temp_cpu = IRQ_UNINIT; - apic_irq_table[irqno] = irqptr; - } - apic_modify_vector(vector, newirq); - } - } - apic_max_device_irq = max(irqno, apic_max_device_irq); - apic_min_device_irq = min(irqno, apic_min_device_irq); - mutex_exit(&airq_mutex); - irqptr->airq_ioapicindex = ioapicindex; - irqptr->airq_intin_no = ipin; - irqptr->airq_ipl = ipl; - irqptr->airq_vector = vector; - irqptr->airq_origirq = (uchar_t)origirq; - irqptr->airq_share_id = 0; - irqptr->airq_mps_intr_index = (short)intr_index; - irqptr->airq_dip = dip; - irqptr->airq_major = major; - irqptr->airq_cpu = apic_bind_intr(dip, irqno, ioapic, ipin); - if (intr_flagp) - irqptr->airq_iflag = *intr_flagp; - - if (!DDI_INTR_IS_MSI_OR_MSIX(type)) { - /* setup I/O APIC entry for non-MSI/X interrupts */ - apic_record_rdt_entry(irqptr, irqno); - } - return (irqno); -} - -/* - * return the cpu to which this intr should be bound. - * Check properties or any other mechanism to see if user wants it - * bound to a specific CPU. If so, return the cpu id with high bit set. - * If not, use the policy to choose a cpu and return the id. - */ -uchar_t -apic_bind_intr(dev_info_t *dip, int irq, uchar_t ioapicid, uchar_t intin) -{ - int instance, instno, prop_len, bind_cpu, count; - uint_t i, rc; - uchar_t cpu; - major_t major; - char *name, *drv_name, *prop_val, *cptr; - char prop_name[32]; - - - if (apic_intr_policy == INTR_LOWEST_PRIORITY) - return (IRQ_UNBOUND); - - drv_name = NULL; - rc = DDI_PROP_NOT_FOUND; - major = (major_t)-1; - if (dip != NULL) { - name = ddi_get_name(dip); - major = ddi_name_to_major(name); - drv_name = ddi_major_to_name(major); - instance = ddi_get_instance(dip); - if (apic_intr_policy == INTR_ROUND_ROBIN_WITH_AFFINITY) { - i = apic_min_device_irq; - for (; i <= apic_max_device_irq; i++) { - - if ((i == irq) || (apic_irq_table[i] == NULL) || - (apic_irq_table[i]->airq_mps_intr_index - == FREE_INDEX)) - continue; - - if ((apic_irq_table[i]->airq_major == major) && - (!(apic_irq_table[i]->airq_cpu & - IRQ_USER_BOUND))) { - - cpu = apic_irq_table[i]->airq_cpu; - - cmn_err(CE_CONT, - "!pcplusmp: %s (%s) instance #%d " - "vector 0x%x ioapic 0x%x " - "intin 0x%x is bound to cpu %d\n", - name, drv_name, instance, irq, - ioapicid, intin, cpu); - return (cpu); - } - } - } - /* - * search for "drvname"_intpt_bind_cpus property first, the - * syntax of the property should be "a[,b,c,...]" where - * instance 0 binds to cpu a, instance 1 binds to cpu b, - * instance 3 binds to cpu c... - * ddi_getlongprop() will search /option first, then / - * if "drvname"_intpt_bind_cpus doesn't exist, then find - * intpt_bind_cpus property. The syntax is the same, and - * it applies to all the devices if its "drvname" specific - * property doesn't exist - */ - (void) strcpy(prop_name, drv_name); - (void) strcat(prop_name, "_intpt_bind_cpus"); - rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, 0, prop_name, - (caddr_t)&prop_val, &prop_len); - if (rc != DDI_PROP_SUCCESS) { - rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, 0, - "intpt_bind_cpus", (caddr_t)&prop_val, &prop_len); - } - } - if (rc == DDI_PROP_SUCCESS) { - for (i = count = 0; i < (prop_len - 1); i++) - if (prop_val[i] == ',') - count++; - if (prop_val[i-1] != ',') - count++; - /* - * if somehow the binding instances defined in the - * property are not enough for this instno., then - * reuse the pattern for the next instance until - * it reaches the requested instno - */ - instno = instance % count; - i = 0; - cptr = prop_val; - while (i < instno) - if (*cptr++ == ',') - i++; - bind_cpu = stoi(&cptr); - kmem_free(prop_val, prop_len); - /* if specific cpu is bogus, then default to cpu 0 */ - if (bind_cpu >= apic_nproc) { - cmn_err(CE_WARN, "pcplusmp: %s=%s: CPU %d not present", - prop_name, prop_val, bind_cpu); - bind_cpu = 0; - } else { - /* indicate that we are bound at user request */ - bind_cpu |= IRQ_USER_BOUND; - } - /* - * no need to check apic_cpus[].aci_status, if specific cpu is - * not up, then post_cpu_start will handle it. - */ - } else { - bind_cpu = apic_next_bind_cpu++; - if (bind_cpu >= apic_nproc) { - apic_next_bind_cpu = 1; - bind_cpu = 0; - } - } - if (drv_name != NULL) - cmn_err(CE_CONT, "!pcplusmp: %s (%s) instance %d " - "vector 0x%x ioapic 0x%x intin 0x%x is bound to cpu %d\n", - name, drv_name, instance, - irq, ioapicid, intin, bind_cpu & ~IRQ_USER_BOUND); - else - cmn_err(CE_CONT, "!pcplusmp: " - "vector 0x%x ioapic 0x%x intin 0x%x is bound to cpu %d\n", - irq, ioapicid, intin, bind_cpu & ~IRQ_USER_BOUND); - - return ((uchar_t)bind_cpu); -} - -static struct apic_io_intr * -apic_find_io_intr_w_busid(int irqno, int busid) -{ - struct apic_io_intr *intrp; - - /* - * It can have more than 1 entry with same source bus IRQ, - * but unique with the source bus id - */ - intrp = apic_io_intrp; - if (intrp != NULL) { - while (intrp->intr_entry == APIC_IO_INTR_ENTRY) { - if (intrp->intr_irq == irqno && - intrp->intr_busid == busid && - intrp->intr_type == IO_INTR_INT) - return (intrp); - intrp++; - } - } - APIC_VERBOSE_IOAPIC((CE_NOTE, "Did not find io intr for irqno:" - "busid %x:%x\n", irqno, busid)); - return ((struct apic_io_intr *)NULL); -} - - -struct mps_bus_info { - char *bus_name; - int bus_id; -} bus_info_array[] = { - "ISA ", BUS_ISA, - "PCI ", BUS_PCI, - "EISA ", BUS_EISA, - "XPRESS", BUS_XPRESS, - "PCMCIA", BUS_PCMCIA, - "VL ", BUS_VL, - "CBUS ", BUS_CBUS, - "CBUSII", BUS_CBUSII, - "FUTURE", BUS_FUTURE, - "INTERN", BUS_INTERN, - "MBI ", BUS_MBI, - "MBII ", BUS_MBII, - "MPI ", BUS_MPI, - "MPSA ", BUS_MPSA, - "NUBUS ", BUS_NUBUS, - "TC ", BUS_TC, - "VME ", BUS_VME, - "PCI-E ", BUS_PCIE -}; - -static int -apic_find_bus_type(char *bus) -{ - int i = 0; - - for (; i < sizeof (bus_info_array)/sizeof (struct mps_bus_info); i++) - if (strncmp(bus, bus_info_array[i].bus_name, - strlen(bus_info_array[i].bus_name)) == 0) - return (bus_info_array[i].bus_id); - APIC_VERBOSE_IOAPIC((CE_WARN, "Did not find bus type for bus %s", bus)); - return (0); -} - -static int -apic_find_bus(int busid) -{ - struct apic_bus *busp; - - busp = apic_busp; - while (busp->bus_entry == APIC_BUS_ENTRY) { - if (busp->bus_id == busid) - return (apic_find_bus_type((char *)&busp->bus_str1)); - busp++; - } - APIC_VERBOSE_IOAPIC((CE_WARN, "Did not find bus for bus id %x", busid)); - return (0); -} - -static int -apic_find_bus_id(int bustype) -{ - struct apic_bus *busp; - - busp = apic_busp; - while (busp->bus_entry == APIC_BUS_ENTRY) { - if (apic_find_bus_type((char *)&busp->bus_str1) == bustype) - return (busp->bus_id); - busp++; - } - APIC_VERBOSE_IOAPIC((CE_WARN, "Did not find bus id for bustype %x", - bustype)); - return (-1); -} - -/* - * Check if a particular irq need to be reserved for any io_intr - */ -static struct apic_io_intr * -apic_find_io_intr(int irqno) -{ - struct apic_io_intr *intrp; - - intrp = apic_io_intrp; - if (intrp != NULL) { - while (intrp->intr_entry == APIC_IO_INTR_ENTRY) { - if (intrp->intr_irq == irqno && - intrp->intr_type == IO_INTR_INT) - return (intrp); - intrp++; - } - } - return ((struct apic_io_intr *)NULL); -} - -/* - * Check if the given ioapicindex intin combination has already been assigned - * an irq. If so return irqno. Else -1 - */ -static int -apic_find_intin(uchar_t ioapic, uchar_t intin) -{ - apic_irq_t *irqptr; - int i; - - /* find ioapic and intin in the apic_irq_table[] and return the index */ - for (i = apic_min_device_irq; i <= apic_max_device_irq; i++) { - irqptr = apic_irq_table[i]; - while (irqptr) { - if ((irqptr->airq_mps_intr_index >= 0) && - (irqptr->airq_intin_no == intin) && - (irqptr->airq_ioapicindex == ioapic)) { - APIC_VERBOSE_IOAPIC((CE_NOTE, "!Found irq " - "entry for ioapic:intin %x:%x " - "shared interrupts ?", ioapic, intin)); - return (i); - } - irqptr = irqptr->airq_next; - } - } - return (-1); -} - -int -apic_allocate_irq(int irq) -{ - int freeirq, i; - - if ((freeirq = apic_find_free_irq(irq, (APIC_RESV_IRQ - 1))) == -1) - if ((freeirq = apic_find_free_irq(APIC_FIRST_FREE_IRQ, - (irq - 1))) == -1) { - /* - * if BIOS really defines every single irq in the mps - * table, then don't worry about conflicting with - * them, just use any free slot in apic_irq_table - */ - for (i = APIC_FIRST_FREE_IRQ; i < APIC_RESV_IRQ; i++) { - if ((apic_irq_table[i] == NULL) || - apic_irq_table[i]->airq_mps_intr_index == - FREE_INDEX) { - freeirq = i; - break; - } - } - if (freeirq == -1) { - /* This shouldn't happen, but just in case */ - cmn_err(CE_WARN, "pcplusmp: NO available IRQ"); - return (-1); - } - } - if (apic_irq_table[freeirq] == NULL) { - apic_irq_table[freeirq] = - kmem_zalloc(sizeof (apic_irq_t), KM_NOSLEEP); - if (apic_irq_table[freeirq] == NULL) { - cmn_err(CE_WARN, "pcplusmp: NO memory to allocate IRQ"); - return (-1); - } - apic_irq_table[freeirq]->airq_mps_intr_index = FREE_INDEX; - } - return (freeirq); -} - -static int -apic_find_free_irq(int start, int end) -{ - int i; - - for (i = start; i <= end; i++) - /* Check if any I/O entry needs this IRQ */ - if (apic_find_io_intr(i) == NULL) { - /* Then see if it is free */ - if ((apic_irq_table[i] == NULL) || - (apic_irq_table[i]->airq_mps_intr_index == - FREE_INDEX)) { - return (i); - } - } - return (-1); -} - -/* - * Allocate a free vector for irq at ipl. Takes care of merging of multiple - * IPLs into a single APIC level as well as stretching some IPLs onto multiple - * levels. APIC_HI_PRI_VECTS interrupts are reserved for high priority - * requests and allocated only when pri is set. - */ -static uchar_t -apic_allocate_vector(int ipl, int irq, int pri) -{ - int lowest, highest, i; - - highest = apic_ipltopri[ipl] + APIC_VECTOR_MASK; - lowest = apic_ipltopri[ipl - 1] + APIC_VECTOR_PER_IPL; - - if (highest < lowest) /* Both ipl and ipl - 1 map to same pri */ - lowest -= APIC_VECTOR_PER_IPL; - -#ifdef DEBUG - if (apic_restrict_vector) /* for testing shared interrupt logic */ - highest = lowest + apic_restrict_vector + APIC_HI_PRI_VECTS; -#endif /* DEBUG */ - if (pri == 0) - highest -= APIC_HI_PRI_VECTS; - - for (i = lowest; i < highest; i++) { - if (APIC_CHECK_RESERVE_VECTORS(i)) - continue; - if (apic_vector_to_irq[i] == APIC_RESV_IRQ) { - apic_vector_to_irq[i] = (uchar_t)irq; - return (i); - } - } - - return (0); -} - -static void -apic_modify_vector(uchar_t vector, int irq) -{ - apic_vector_to_irq[vector] = (uchar_t)irq; -} - -/* - * Mark vector as being in the process of being deleted. Interrupts - * may still come in on some CPU. The moment an interrupt comes with - * the new vector, we know we can free the old one. Called only from - * addspl and delspl with interrupts disabled. Because an interrupt - * can be shared, but no interrupt from either device may come in, - * we also use a timeout mechanism, which we arbitrarily set to - * apic_revector_timeout microseconds. - */ -static void -apic_mark_vector(uchar_t oldvector, uchar_t newvector) -{ - int iflag = intr_clear(); - lock_set(&apic_revector_lock); - if (!apic_oldvec_to_newvec) { - apic_oldvec_to_newvec = - kmem_zalloc(sizeof (newvector) * APIC_MAX_VECTOR * 2, - KM_NOSLEEP); - - if (!apic_oldvec_to_newvec) { - /* - * This failure is not catastrophic. - * But, the oldvec will never be freed. - */ - apic_error |= APIC_ERR_MARK_VECTOR_FAIL; - lock_clear(&apic_revector_lock); - intr_restore(iflag); - return; - } - apic_newvec_to_oldvec = &apic_oldvec_to_newvec[APIC_MAX_VECTOR]; - } - - /* See if we already did this for drivers which do double addintrs */ - if (apic_oldvec_to_newvec[oldvector] != newvector) { - apic_oldvec_to_newvec[oldvector] = newvector; - apic_newvec_to_oldvec[newvector] = oldvector; - apic_revector_pending++; - } - lock_clear(&apic_revector_lock); - intr_restore(iflag); - (void) timeout(apic_xlate_vector_free_timeout_handler, - (void *)(uintptr_t)oldvector, drv_usectohz(apic_revector_timeout)); -} - -/* - * xlate_vector is called from intr_enter if revector_pending is set. - * It will xlate it if needed and mark the old vector as free. - */ -static uchar_t -apic_xlate_vector(uchar_t vector) -{ - uchar_t newvector, oldvector = 0; - - lock_set(&apic_revector_lock); - /* Do we really need to do this ? */ - if (!apic_revector_pending) { - lock_clear(&apic_revector_lock); - return (vector); - } - if ((newvector = apic_oldvec_to_newvec[vector]) != 0) - oldvector = vector; - else { - /* - * The incoming vector is new . See if a stale entry is - * remaining - */ - if ((oldvector = apic_newvec_to_oldvec[vector]) != 0) - newvector = vector; - } - - if (oldvector) { - apic_revector_pending--; - apic_oldvec_to_newvec[oldvector] = 0; - apic_newvec_to_oldvec[newvector] = 0; - apic_free_vector(oldvector); - lock_clear(&apic_revector_lock); - /* There could have been more than one reprogramming! */ - return (apic_xlate_vector(newvector)); - } - lock_clear(&apic_revector_lock); - return (vector); -} - -void -apic_xlate_vector_free_timeout_handler(void *arg) -{ - int iflag; - uchar_t oldvector, newvector; - - oldvector = (uchar_t)(uintptr_t)arg; - iflag = intr_clear(); - lock_set(&apic_revector_lock); - if ((newvector = apic_oldvec_to_newvec[oldvector]) != 0) { - apic_free_vector(oldvector); - apic_oldvec_to_newvec[oldvector] = 0; - apic_newvec_to_oldvec[newvector] = 0; - apic_revector_pending--; - } - - lock_clear(&apic_revector_lock); - intr_restore(iflag); -} - - -/* Mark vector as not being used by any irq */ -static void -apic_free_vector(uchar_t vector) -{ - apic_vector_to_irq[vector] = APIC_RESV_IRQ; -} - -/* - * compute the polarity, trigger mode and vector for programming into - * the I/O apic and record in airq_rdt_entry. - */ -static void -apic_record_rdt_entry(apic_irq_t *irqptr, int irq) -{ - int ioapicindex, bus_type, vector; - short intr_index; - uint_t level, po, io_po; - struct apic_io_intr *iointrp; - - intr_index = irqptr->airq_mps_intr_index; - DDI_INTR_IMPLDBG((CE_CONT, "apic_record_rdt_entry: intr_index=%d " - "irq = 0x%x dip = 0x%p vector = 0x%x\n", intr_index, irq, - (void *)irqptr->airq_dip, irqptr->airq_vector)); - - if (intr_index == RESERVE_INDEX) { - apic_error |= APIC_ERR_INVALID_INDEX; - return; - } else if (APIC_IS_MSI_OR_MSIX_INDEX(intr_index)) { - return; - } - - vector = irqptr->airq_vector; - ioapicindex = irqptr->airq_ioapicindex; - /* Assume edge triggered by default */ - level = 0; - /* Assume active high by default */ - po = 0; - - if (intr_index == DEFAULT_INDEX || intr_index == FREE_INDEX) { - ASSERT(irq < 16); - if (eisa_level_intr_mask & (1 << irq)) - level = AV_LEVEL; - if (intr_index == FREE_INDEX && apic_defconf == 0) - apic_error |= APIC_ERR_INVALID_INDEX; - } else if (intr_index == ACPI_INDEX) { - bus_type = irqptr->airq_iflag.bustype; - if (irqptr->airq_iflag.intr_el == INTR_EL_CONFORM) { - if (bus_type == BUS_PCI) - level = AV_LEVEL; - } else - level = (irqptr->airq_iflag.intr_el == INTR_EL_LEVEL) ? - AV_LEVEL : 0; - if (level && - ((irqptr->airq_iflag.intr_po == INTR_PO_ACTIVE_LOW) || - (irqptr->airq_iflag.intr_po == INTR_PO_CONFORM && - bus_type == BUS_PCI))) - po = AV_ACTIVE_LOW; - } else { - iointrp = apic_io_intrp + intr_index; - bus_type = apic_find_bus(iointrp->intr_busid); - if (iointrp->intr_el == INTR_EL_CONFORM) { - if ((irq < 16) && (eisa_level_intr_mask & (1 << irq))) - level = AV_LEVEL; - else if (bus_type == BUS_PCI) - level = AV_LEVEL; - } else - level = (iointrp->intr_el == INTR_EL_LEVEL) ? - AV_LEVEL : 0; - if (level && ((iointrp->intr_po == INTR_PO_ACTIVE_LOW) || - (iointrp->intr_po == INTR_PO_CONFORM && - bus_type == BUS_PCI))) - po = AV_ACTIVE_LOW; - } - if (level) - apic_level_intr[irq] = 1; - /* - * The 82489DX External APIC cannot do active low polarity interrupts. - */ - if (po && (apic_io_ver[ioapicindex] != IOAPIC_VER_82489DX)) - io_po = po; - else - io_po = 0; - - if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) - printf("setio: ioapic=%x intin=%x level=%x po=%x vector=%x\n", - ioapicindex, irqptr->airq_intin_no, level, io_po, vector); - - irqptr->airq_rdt_entry = level|io_po|vector; -} - -static processorid_t -apic_find_cpu(int flag) -{ - processorid_t acid = 0; - int i; - - /* Find the first CPU with the passed-in flag set */ - for (i = 0; i < apic_nproc; i++) { - if (apic_cpus[i].aci_status & flag) { - acid = i; - break; - } - } - - ASSERT((apic_cpus[acid].aci_status & flag) != 0); - return (acid); -} - -/* - * Call rebind to do the actual programming. - * Must be called with interrupts disabled and apic_ioapic_lock held - * 'p' is polymorphic -- if this function is called to process a deferred - * reprogramming, p is of type 'struct ioapic_reprogram_data *', from which - * the irq pointer is retrieved. If not doing deferred reprogramming, - * p is of the type 'apic_irq_t *'. - * - * apic_ioapic_lock must be held across this call, as it protects apic_rebind - * and it protects apic_find_cpu() from a race in which a CPU can be taken - * offline after a cpu is selected, but before apic_rebind is called to - * bind interrupts to it. - */ -static int -apic_setup_io_intr(void *p, int irq, boolean_t deferred) -{ - apic_irq_t *irqptr; - struct ioapic_reprogram_data *drep = NULL; - int rv; - - if (deferred) { - drep = (struct ioapic_reprogram_data *)p; - ASSERT(drep != NULL); - irqptr = drep->irqp; - } else - irqptr = (apic_irq_t *)p; - - ASSERT(irqptr != NULL); - - rv = apic_rebind(irqptr, apic_irq_table[irq]->airq_cpu, drep); - if (rv) { - /* - * CPU is not up or interrupts are disabled. Fall back to - * the first available CPU - */ - rv = apic_rebind(irqptr, apic_find_cpu(APIC_CPU_INTR_ENABLE), - drep); - } - - return (rv); -} - -/* - * Bind interrupt corresponding to irq_ptr to bind_cpu. - * Must be called with interrupts disabled and apic_ioapic_lock held - */ -static int -apic_rebind(apic_irq_t *irq_ptr, int bind_cpu, - struct ioapic_reprogram_data *drep) -{ - int ioapicindex, intin_no; - volatile int32_t *ioapic; - uchar_t airq_temp_cpu; - apic_cpus_info_t *cpu_infop; - uint32_t rdt_entry; - int which_irq; - - which_irq = apic_vector_to_irq[irq_ptr->airq_vector]; - - intin_no = irq_ptr->airq_intin_no; - ioapicindex = irq_ptr->airq_ioapicindex; - ioapic = apicioadr[ioapicindex]; - airq_temp_cpu = irq_ptr->airq_temp_cpu; - if (airq_temp_cpu != IRQ_UNINIT && airq_temp_cpu != IRQ_UNBOUND) { - if (airq_temp_cpu & IRQ_USER_BOUND) - /* Mask off high bit so it can be used as array index */ - airq_temp_cpu &= ~IRQ_USER_BOUND; - - ASSERT(airq_temp_cpu < apic_nproc); - } - - /* - * Can't bind to a CPU that's not accepting interrupts: - */ - cpu_infop = &apic_cpus[bind_cpu & ~IRQ_USER_BOUND]; - if (!(cpu_infop->aci_status & APIC_CPU_INTR_ENABLE)) - return (1); - - /* - * If we are about to change the interrupt vector for this interrupt, - * and this interrupt is level-triggered, attached to an IOAPIC, - * has been delivered to a CPU and that CPU has not handled it - * yet, we cannot reprogram the IOAPIC now. - */ - if (!APIC_IS_MSI_OR_MSIX_INDEX(irq_ptr->airq_mps_intr_index)) { - - rdt_entry = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no); - - if ((irq_ptr->airq_vector != RDT_VECTOR(rdt_entry)) && - apic_check_stuck_interrupt(irq_ptr, airq_temp_cpu, - bind_cpu, ioapic, intin_no, which_irq, drep) != 0) { - - return (0); - } - } - - /* - * NOTE: We do not unmask the RDT here, as an interrupt MAY still - * come in before we have a chance to reprogram it below. The - * reprogramming below will simultaneously change and unmask the - * RDT entry. - */ - - if ((uchar_t)bind_cpu == IRQ_UNBOUND) { - - rdt_entry = AV_LDEST | AV_LOPRI | irq_ptr->airq_rdt_entry; - - /* Write the RDT entry -- no specific CPU binding */ - WRITE_IOAPIC_RDT_ENTRY_HIGH_DWORD(ioapic, intin_no, AV_TOALL); - - if (airq_temp_cpu != IRQ_UNINIT && airq_temp_cpu != IRQ_UNBOUND) - apic_cpus[airq_temp_cpu].aci_temp_bound--; - - /* Write the vector, trigger, and polarity portion of the RDT */ - WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no, rdt_entry); - - irq_ptr->airq_temp_cpu = IRQ_UNBOUND; - return (0); - } - - if (bind_cpu & IRQ_USER_BOUND) { - cpu_infop->aci_bound++; - } else { - cpu_infop->aci_temp_bound++; - } - ASSERT((bind_cpu & ~IRQ_USER_BOUND) < apic_nproc); - if (!APIC_IS_MSI_OR_MSIX_INDEX(irq_ptr->airq_mps_intr_index)) { - /* Write the RDT entry -- bind to a specific CPU: */ - WRITE_IOAPIC_RDT_ENTRY_HIGH_DWORD(ioapic, intin_no, - cpu_infop->aci_local_id << APIC_ID_BIT_OFFSET); - } - if ((airq_temp_cpu != IRQ_UNBOUND) && (airq_temp_cpu != IRQ_UNINIT)) { - apic_cpus[airq_temp_cpu].aci_temp_bound--; - } - if (!APIC_IS_MSI_OR_MSIX_INDEX(irq_ptr->airq_mps_intr_index)) { - - rdt_entry = AV_PDEST | AV_FIXED | irq_ptr->airq_rdt_entry; - - /* Write the vector, trigger, and polarity portion of the RDT */ - WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no, rdt_entry); - - } else { - int type = (irq_ptr->airq_mps_intr_index == MSI_INDEX) ? - DDI_INTR_TYPE_MSI : DDI_INTR_TYPE_MSIX; - (void) apic_pci_msi_disable_mode(irq_ptr->airq_dip, type, - ioapicindex); - if (ioapicindex == irq_ptr->airq_origirq) { - /* first one */ - DDI_INTR_IMPLDBG((CE_CONT, "apic_rebind: call " - "apic_pci_msi_enable_vector\n")); - if (apic_pci_msi_enable_vector(irq_ptr->airq_dip, type, - which_irq, irq_ptr->airq_vector, - irq_ptr->airq_intin_no, - cpu_infop->aci_local_id) != PSM_SUCCESS) { - cmn_err(CE_WARN, "pcplusmp: " - "apic_pci_msi_enable_vector " - "returned PSM_FAILURE"); - } - } - if ((ioapicindex + irq_ptr->airq_intin_no - 1) == - irq_ptr->airq_origirq) { /* last one */ - DDI_INTR_IMPLDBG((CE_CONT, "apic_rebind: call " - "pci_msi_enable_mode\n")); - if (apic_pci_msi_enable_mode(irq_ptr->airq_dip, - type, which_irq) != PSM_SUCCESS) { - DDI_INTR_IMPLDBG((CE_CONT, "pcplusmp: " - "pci_msi_enable failed\n")); - (void) apic_pci_msi_unconfigure( - irq_ptr->airq_dip, type, which_irq); - } - } - } - irq_ptr->airq_temp_cpu = (uchar_t)bind_cpu; - apic_redist_cpu_skip &= ~(1 << (bind_cpu & ~IRQ_USER_BOUND)); - return (0); -} - -static void -apic_last_ditch_clear_remote_irr(volatile int32_t *ioapic, int intin_no) -{ - if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no) - & AV_REMOTE_IRR) != 0) { - /* - * Trying to clear the bit through normal - * channels has failed. So as a last-ditch - * effort, try to set the trigger mode to - * edge, then to level. This has been - * observed to work on many systems. - */ - WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, - intin_no, - READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, - intin_no) & ~AV_LEVEL); - - WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, - intin_no, - READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, - intin_no) | AV_LEVEL); - - /* - * If the bit's STILL set, this interrupt may - * be hosed. - */ - if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, - intin_no) & AV_REMOTE_IRR) != 0) { - - prom_printf("pcplusmp: Remote IRR still " - "not clear for IOAPIC %p intin %d.\n" - "\tInterrupts to this pin may cease " - "functioning.\n", ioapic, intin_no); -#ifdef DEBUG - apic_last_ditch_reprogram_failures++; -#endif - } - } -} - -/* - * This function is protected by apic_ioapic_lock coupled with the - * fact that interrupts are disabled. - */ -static void -delete_defer_repro_ent(int which_irq) -{ - ASSERT(which_irq >= 0); - ASSERT(which_irq <= 255); - - if (apic_reprogram_info[which_irq].done) - return; - - apic_reprogram_info[which_irq].done = B_TRUE; - -#ifdef DEBUG - apic_defer_repro_total_retries += - apic_reprogram_info[which_irq].tries; - - apic_defer_repro_successes++; -#endif - - if (--apic_reprogram_outstanding == 0) { - - setlvlx = apic_intr_exit; - } -} - - -/* - * Interrupts must be disabled during this function to prevent - * self-deadlock. Interrupts are disabled because this function - * is called from apic_check_stuck_interrupt(), which is called - * from apic_rebind(), which requires its caller to disable interrupts. - */ -static void -add_defer_repro_ent(apic_irq_t *irq_ptr, int which_irq, int new_bind_cpu) -{ - ASSERT(which_irq >= 0); - ASSERT(which_irq <= 255); - - /* - * On the off-chance that there's already a deferred - * reprogramming on this irq, check, and if so, just update the - * CPU and irq pointer to which the interrupt is targeted, then return. - */ - if (!apic_reprogram_info[which_irq].done) { - apic_reprogram_info[which_irq].bindcpu = new_bind_cpu; - apic_reprogram_info[which_irq].irqp = irq_ptr; - return; - } - - apic_reprogram_info[which_irq].irqp = irq_ptr; - apic_reprogram_info[which_irq].bindcpu = new_bind_cpu; - apic_reprogram_info[which_irq].tries = 0; - /* - * This must be the last thing set, since we're not - * grabbing any locks, apic_try_deferred_reprogram() will - * make its decision about using this entry iff done - * is false. - */ - apic_reprogram_info[which_irq].done = B_FALSE; - - /* - * If there were previously no deferred reprogrammings, change - * setlvlx to call apic_try_deferred_reprogram() - */ - if (++apic_reprogram_outstanding == 1) { - - setlvlx = apic_try_deferred_reprogram; - } -} - -static void -apic_try_deferred_reprogram(int prev_ipl, int irq) -{ - int reproirq, iflag; - struct ioapic_reprogram_data *drep; - - apic_intr_exit(prev_ipl, irq); - - if (!lock_try(&apic_defer_reprogram_lock)) { - return; - } - - /* - * Acquire the apic_ioapic_lock so that any other operations that - * may affect the apic_reprogram_info state are serialized. - * It's still possible for the last deferred reprogramming to clear - * between the time we entered this function and the time we get to - * the for loop below. In that case, *setlvlx will have been set - * back to apic_intr_exit and drep will be NULL. (There's no way to - * stop that from happening -- we would need to grab a lock before - * calling *setlvlx, which is neither realistic nor prudent). - */ - iflag = intr_clear(); - lock_set(&apic_ioapic_lock); - - /* - * For each deferred RDT entry, try to reprogram it now. Note that - * there is no lock acquisition to read apic_reprogram_info because - * '.done' is set only after the other fields in the structure are set. - */ - - drep = NULL; - for (reproirq = 0; reproirq <= APIC_MAX_VECTOR; reproirq++) { - if (apic_reprogram_info[reproirq].done == B_FALSE) { - drep = &apic_reprogram_info[reproirq]; - break; - } - } - - /* - * Either we found a deferred action to perform, or - * we entered this function spuriously, after *setlvlx - * was restored to point to apic_intr_enter. Any other - * permutation is invalid. - */ - ASSERT(drep != NULL || *setlvlx == apic_intr_exit); - - /* - * Though we can't really do anything about errors - * at this point, keep track of them for reporting. - * Note that it is very possible for apic_setup_io_intr - * to re-register this very timeout if the Remote IRR bit - * has not yet cleared. - */ - -#ifdef DEBUG - if (drep != NULL) { - if (apic_setup_io_intr(drep, reproirq, B_TRUE) != 0) { - apic_deferred_setup_failures++; - } - } else { - apic_deferred_spurious_enters++; - } -#else - if (drep != NULL) - (void) apic_setup_io_intr(drep, reproirq, B_TRUE); -#endif - - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - - lock_clear(&apic_defer_reprogram_lock); -} - -static void -apic_ioapic_wait_pending_clear(volatile int32_t *ioapic, int intin_no) -{ - int waited; - - /* - * Wait for the delivery pending bit to clear. - */ - if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no) & - (AV_LEVEL|AV_PENDING)) == (AV_LEVEL|AV_PENDING)) { - - /* - * If we're still waiting on the delivery of this interrupt, - * continue to wait here until it is delivered (this should be - * a very small amount of time, but include a timeout just in - * case). - */ - for (waited = 0; waited < apic_max_reps_clear_pending; - waited++) { - if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no) - & AV_PENDING) == 0) { - break; - } - } - } -} - -/* - * Checks to see if the IOAPIC interrupt entry specified has its Remote IRR - * bit set. Calls functions that modify the function that setlvlx points to, - * so that the reprogramming can be retried very shortly. - * - * This function will mask the RDT entry if the interrupt is level-triggered. - * (The caller is responsible for unmasking the RDT entry.) - * - * Returns non-zero if the caller should defer IOAPIC reprogramming. - */ -static int -apic_check_stuck_interrupt(apic_irq_t *irq_ptr, int old_bind_cpu, - int new_bind_cpu, volatile int32_t *ioapic, int intin_no, int which_irq, - struct ioapic_reprogram_data *drep) -{ - int32_t rdt_entry; - int waited; - int reps = 0; - - /* - * Wait for the delivery pending bit to clear. - */ - do { - ++reps; - - apic_ioapic_wait_pending_clear(ioapic, intin_no); - - /* - * Mask the RDT entry, but only if it's a level-triggered - * interrupt - */ - rdt_entry = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no); - if ((rdt_entry & (AV_LEVEL|AV_MASK)) == AV_LEVEL) { - - /* Mask it */ - WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no, - AV_MASK | rdt_entry); - } - - if ((rdt_entry & AV_LEVEL) == AV_LEVEL) { - /* - * If there was a race and an interrupt was injected - * just before we masked, check for that case here. - * Then, unmask the RDT entry and try again. If we're - * on our last try, don't unmask (because we want the - * RDT entry to remain masked for the rest of the - * function). - */ - rdt_entry = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, - intin_no); - if ((rdt_entry & AV_PENDING) && - (reps < apic_max_reps_clear_pending)) { - /* Unmask it */ - WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, - intin_no, rdt_entry & ~AV_MASK); - } - } - - } while ((rdt_entry & AV_PENDING) && - (reps < apic_max_reps_clear_pending)); - -#ifdef DEBUG - if (rdt_entry & AV_PENDING) - apic_intr_deliver_timeouts++; -#endif - - /* - * If the remote IRR bit is set, then the interrupt has been sent - * to a CPU for processing. We have no choice but to wait for - * that CPU to process the interrupt, at which point the remote IRR - * bit will be cleared. - */ - if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no) & - (AV_LEVEL|AV_REMOTE_IRR)) == (AV_LEVEL|AV_REMOTE_IRR)) { - - /* - * If the CPU that this RDT is bound to is NOT the current - * CPU, wait until that CPU handles the interrupt and ACKs - * it. If this interrupt is not bound to any CPU (that is, - * if it's bound to the logical destination of "anyone"), it - * may have been delivered to the current CPU so handle that - * case by deferring the reprogramming (below). - */ - if ((old_bind_cpu != IRQ_UNBOUND) && - (old_bind_cpu != IRQ_UNINIT) && - (old_bind_cpu != psm_get_cpu_id())) { - for (waited = 0; waited < apic_max_reps_clear_pending; - waited++) { - if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, - intin_no) & AV_REMOTE_IRR) == 0) { - - delete_defer_repro_ent(which_irq); - - /* Remote IRR has cleared! */ - return (0); - } - } - } - - /* - * If we waited and the Remote IRR bit is still not cleared, - * AND if we've invoked the timeout APIC_REPROGRAM_MAX_TIMEOUTS - * times for this interrupt, try the last-ditch workaround: - */ - if (drep && drep->tries >= APIC_REPROGRAM_MAX_TRIES) { - - apic_last_ditch_clear_remote_irr(ioapic, intin_no); - - /* Mark this one as reprogrammed: */ - delete_defer_repro_ent(which_irq); - - return (0); - } else { -#ifdef DEBUG - apic_intr_deferrals++; -#endif - - /* - * If waiting for the Remote IRR bit (above) didn't - * allow it to clear, defer the reprogramming. - * Add a new deferred-programming entry if the - * caller passed a NULL one (and update the existing one - * in case anything changed). - */ - add_defer_repro_ent(irq_ptr, which_irq, new_bind_cpu); - if (drep) - drep->tries++; - - /* Inform caller to defer IOAPIC programming: */ - return (1); - } - - } - - /* Remote IRR is clear */ - delete_defer_repro_ent(which_irq); - - return (0); -} - -/* - * Called to migrate all interrupts at an irq to another cpu. - * Must be called with interrupts disabled and apic_ioapic_lock held - */ -int -apic_rebind_all(apic_irq_t *irq_ptr, int bind_cpu) -{ - apic_irq_t *irqptr = irq_ptr; - int retval = 0; - - while (irqptr) { - if (irqptr->airq_temp_cpu != IRQ_UNINIT) - retval |= apic_rebind(irqptr, bind_cpu, NULL); - irqptr = irqptr->airq_next; - } - - return (retval); -} - -/* - * apic_intr_redistribute does all the messy computations for identifying - * which interrupt to move to which CPU. Currently we do just one interrupt - * at a time. This reduces the time we spent doing all this within clock - * interrupt. When it is done in idle, we could do more than 1. - * First we find the most busy and the most free CPU (time in ISR only) - * skipping those CPUs that has been identified as being ineligible (cpu_skip) - * Then we look for IRQs which are closest to the difference between the - * most busy CPU and the average ISR load. We try to find one whose load - * is less than difference.If none exists, then we chose one larger than the - * difference, provided it does not make the most idle CPU worse than the - * most busy one. In the end, we clear all the busy fields for CPUs. For - * IRQs, they are cleared as they are scanned. - */ -static void -apic_intr_redistribute() -{ - int busiest_cpu, most_free_cpu; - int cpu_free, cpu_busy, max_busy, min_busy; - int min_free, diff; - int average_busy, cpus_online; - int i, busy, iflag; - apic_cpus_info_t *cpu_infop; - apic_irq_t *min_busy_irq = NULL; - apic_irq_t *max_busy_irq = NULL; - - busiest_cpu = most_free_cpu = -1; - cpu_free = cpu_busy = max_busy = average_busy = 0; - min_free = apic_sample_factor_redistribution; - cpus_online = 0; - /* - * Below we will check for CPU_INTR_ENABLE, bound, temp_bound, temp_cpu - * without ioapic_lock. That is OK as we are just doing statistical - * sampling anyway and any inaccuracy now will get corrected next time - * The call to rebind which actually changes things will make sure - * we are consistent. - */ - for (i = 0; i < apic_nproc; i++) { - if (!(apic_redist_cpu_skip & (1 << i)) && - (apic_cpus[i].aci_status & APIC_CPU_INTR_ENABLE)) { - - cpu_infop = &apic_cpus[i]; - /* - * If no unbound interrupts or only 1 total on this - * CPU, skip - */ - if (!cpu_infop->aci_temp_bound || - (cpu_infop->aci_bound + cpu_infop->aci_temp_bound) - == 1) { - apic_redist_cpu_skip |= 1 << i; - continue; - } - - busy = cpu_infop->aci_busy; - average_busy += busy; - cpus_online++; - if (max_busy < busy) { - max_busy = busy; - busiest_cpu = i; - } - if (min_free > busy) { - min_free = busy; - most_free_cpu = i; - } - if (busy > apic_int_busy_mark) { - cpu_busy |= 1 << i; - } else { - if (busy < apic_int_free_mark) - cpu_free |= 1 << i; - } - } - } - if ((cpu_busy && cpu_free) || - (max_busy >= (min_free + apic_diff_for_redistribution))) { - - apic_num_imbalance++; -#ifdef DEBUG - if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) { - prom_printf( - "redistribute busy=%x free=%x max=%x min=%x", - cpu_busy, cpu_free, max_busy, min_free); - } -#endif /* DEBUG */ - - - average_busy /= cpus_online; - - diff = max_busy - average_busy; - min_busy = max_busy; /* start with the max possible value */ - max_busy = 0; - min_busy_irq = max_busy_irq = NULL; - i = apic_min_device_irq; - for (; i < apic_max_device_irq; i++) { - apic_irq_t *irq_ptr; - /* Change to linked list per CPU ? */ - if ((irq_ptr = apic_irq_table[i]) == NULL) - continue; - /* Check for irq_busy & decide which one to move */ - /* Also zero them for next round */ - if ((irq_ptr->airq_temp_cpu == busiest_cpu) && - irq_ptr->airq_busy) { - if (irq_ptr->airq_busy < diff) { - /* - * Check for least busy CPU, - * best fit or what ? - */ - if (max_busy < irq_ptr->airq_busy) { - /* - * Most busy within the - * required differential - */ - max_busy = irq_ptr->airq_busy; - max_busy_irq = irq_ptr; - } - } else { - if (min_busy > irq_ptr->airq_busy) { - /* - * least busy, but more than - * the reqd diff - */ - if (min_busy < - (diff + average_busy - - min_free)) { - /* - * Making sure new cpu - * will not end up - * worse - */ - min_busy = - irq_ptr->airq_busy; - - min_busy_irq = irq_ptr; - } - } - } - } - irq_ptr->airq_busy = 0; - } - - if (max_busy_irq != NULL) { -#ifdef DEBUG - if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) { - prom_printf("rebinding %x to %x", - max_busy_irq->airq_vector, most_free_cpu); - } -#endif /* DEBUG */ - iflag = intr_clear(); - if (lock_try(&apic_ioapic_lock)) { - if (apic_rebind_all(max_busy_irq, - most_free_cpu) == 0) { - /* Make change permenant */ - max_busy_irq->airq_cpu = - (uchar_t)most_free_cpu; - } - lock_clear(&apic_ioapic_lock); - } - intr_restore(iflag); - - } else if (min_busy_irq != NULL) { -#ifdef DEBUG - if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) { - prom_printf("rebinding %x to %x", - min_busy_irq->airq_vector, most_free_cpu); - } -#endif /* DEBUG */ - - iflag = intr_clear(); - if (lock_try(&apic_ioapic_lock)) { - if (apic_rebind_all(min_busy_irq, - most_free_cpu) == 0) { - /* Make change permenant */ - min_busy_irq->airq_cpu = - (uchar_t)most_free_cpu; - } - lock_clear(&apic_ioapic_lock); - } - intr_restore(iflag); - - } else { - if (cpu_busy != (1 << busiest_cpu)) { - apic_redist_cpu_skip |= 1 << busiest_cpu; - /* - * We leave cpu_skip set so that next time we - * can choose another cpu - */ - } - } - apic_num_rebind++; - } else { - /* - * found nothing. Could be that we skipped over valid CPUs - * or we have balanced everything. If we had a variable - * ticks_for_redistribution, it could be increased here. - * apic_int_busy, int_free etc would also need to be - * changed. - */ - if (apic_redist_cpu_skip) - apic_redist_cpu_skip = 0; - } - for (i = 0; i < apic_nproc; i++) { - apic_cpus[i].aci_busy = 0; - } -} - -static void -apic_cleanup_busy() -{ - int i; - apic_irq_t *irq_ptr; - - for (i = 0; i < apic_nproc; i++) { - apic_cpus[i].aci_busy = 0; - } - - for (i = apic_min_device_irq; i < apic_max_device_irq; i++) { - if ((irq_ptr = apic_irq_table[i]) != NULL) - irq_ptr->airq_busy = 0; - } - apic_skipped_redistribute = 0; -} - /* * This function will reprogram the timer. @@ -5091,7 +1694,7 @@ apic_timer_reprogram(hrtime_t time) { hrtime_t now; uint_t ticks; - int64_t delta; + int64_t delta; /* * We should be called from high PIL context (CBE_HIGH_PIL), @@ -5253,10 +1856,12 @@ apic_redistribute_compute(void) * more empirical data to decide if that is a * good strategy. Punt for now. */ - if (apic_skipped_redistribute) + if (apic_skipped_redistribute) { apic_cleanup_busy(); - else + apic_skipped_redistribute = 0; + } else { apic_intr_redistribute(); + } } else apic_skipped_redistribute++; } @@ -5264,402 +1869,268 @@ apic_redistribute_compute(void) } -static int -apic_acpi_translate_pci_irq(dev_info_t *dip, int busid, int devid, - int ipin, int *pci_irqp, iflag_t *intr_flagp) -{ - - int status; - acpi_psm_lnk_t acpipsmlnk; - - if ((status = acpi_get_irq_cache_ent(busid, devid, ipin, pci_irqp, - intr_flagp)) == ACPI_PSM_SUCCESS) { - APIC_VERBOSE_IRQ((CE_CONT, "!pcplusmp: Found irqno %d " - "from cache for device %s, instance #%d\n", *pci_irqp, - ddi_get_name(dip), ddi_get_instance(dip))); - return (status); - } - - bzero(&acpipsmlnk, sizeof (acpi_psm_lnk_t)); - - if ((status = acpi_translate_pci_irq(dip, ipin, pci_irqp, intr_flagp, - &acpipsmlnk)) == ACPI_PSM_FAILURE) { - APIC_VERBOSE_IRQ((CE_WARN, "pcplusmp: " - " acpi_translate_pci_irq failed for device %s, instance" - " #%d", ddi_get_name(dip), ddi_get_instance(dip))); - return (status); - } - - if (status == ACPI_PSM_PARTIAL && acpipsmlnk.lnkobj != NULL) { - status = apic_acpi_irq_configure(&acpipsmlnk, dip, pci_irqp, - intr_flagp); - if (status != ACPI_PSM_SUCCESS) { - status = acpi_get_current_irq_resource(&acpipsmlnk, - pci_irqp, intr_flagp); - } - } - - if (status == ACPI_PSM_SUCCESS) { - acpi_new_irq_cache_ent(busid, devid, ipin, *pci_irqp, - intr_flagp, &acpipsmlnk); - - APIC_VERBOSE_IRQ((CE_CONT, "pcplusmp: [ACPI] " - "new irq %d for device %s, instance #%d\n", - *pci_irqp, ddi_get_name(dip), ddi_get_instance(dip))); - } - - return (status); -} +/* + * The following functions are in the platform specific file so that they + * can be different functions depending on whether we are running on + * bare metal or a hypervisor. + */ /* - * Adds an entry to the irq list passed in, and returns the new list. - * Entries are added in priority order (lower numerical priorities are - * placed closer to the head of the list) + * map an apic for memory-mapped access */ -static prs_irq_list_t * -acpi_insert_prs_irq_ent(prs_irq_list_t *listp, int priority, int irq, - iflag_t *iflagp, acpi_prs_private_t *prsprvp) +uint32_t * +mapin_apic(uint32_t addr, size_t len, int flags) { - struct prs_irq_list_ent *newent, *prevp = NULL, *origlistp; - - newent = kmem_zalloc(sizeof (struct prs_irq_list_ent), KM_SLEEP); - - newent->list_prio = priority; - newent->irq = irq; - newent->intrflags = *iflagp; - newent->prsprv = *prsprvp; - /* ->next is NULL from kmem_zalloc */ - - /* - * New list -- return the new entry as the list. - */ - if (listp == NULL) - return (newent); - - /* - * Save original list pointer for return (since we're not modifying - * the head) - */ - origlistp = listp; - - /* - * Insertion sort, with entries with identical keys stored AFTER - * existing entries (the less-than-or-equal test of priority does - * this for us). - */ - while (listp != NULL && listp->list_prio <= priority) { - prevp = listp; - listp = listp->next; - } - - newent->next = listp; + /*LINTED: pointer cast may result in improper alignment */ + return ((uint32_t *)psm_map_phys(addr, len, flags)); +} - if (prevp == NULL) { /* Add at head of list (newent is the new head) */ - return (newent); - } else { - prevp->next = newent; - return (origlistp); - } +uint32_t * +mapin_ioapic(uint32_t addr, size_t len, int flags) +{ + return (mapin_apic(addr, len, flags)); } /* - * Frees the list passed in, deallocating all memory and leaving *listpp - * set to NULL. + * unmap an apic */ -static void -acpi_destroy_prs_irq_list(prs_irq_list_t **listpp) +void +mapout_apic(caddr_t addr, size_t len) { - struct prs_irq_list_ent *nextp; - - ASSERT(listpp != NULL); + psm_unmap_phys(addr, len); +} - while (*listpp != NULL) { - nextp = (*listpp)->next; - kmem_free(*listpp, sizeof (struct prs_irq_list_ent)); - *listpp = nextp; - } +void +mapout_ioapic(caddr_t addr, size_t len) +{ + mapout_apic(addr, len); } /* - * apic_choose_irqs_from_prs returns a list of irqs selected from the list of - * irqs returned by the link device's _PRS method. The irqs are chosen - * to minimize contention in situations where the interrupt link device - * can be programmed to steer interrupts to different interrupt controller - * inputs (some of which may already be in use). The list is sorted in order - * of irqs to use, with the highest priority given to interrupt controller - * inputs that are not shared. When an interrupt controller input - * must be shared, apic_choose_irqs_from_prs adds the possible irqs to the - * returned list in the order that minimizes sharing (thereby ensuring lowest - * possible latency from interrupt trigger time to ISR execution time). + * This function allocate "count" vector(s) for the given "dip/pri/type" */ -static prs_irq_list_t * -apic_choose_irqs_from_prs(acpi_irqlist_t *irqlistent, dev_info_t *dip, - int crs_irq) +int +apic_alloc_vectors(dev_info_t *dip, int inum, int count, int pri, int type, + int behavior) { - int32_t irq; - int i; - prs_irq_list_t *prsirqlistp = NULL; - iflag_t iflags; - - while (irqlistent != NULL) { - irqlistent->intr_flags.bustype = BUS_PCI; - - for (i = 0; i < irqlistent->num_irqs; i++) { - - irq = irqlistent->irqs[i]; - - if (irq <= 0) { - /* invalid irq number */ - continue; - } + int rcount, i; + uchar_t start, irqno, cpu; + major_t major; + apic_irq_t *irqptr; - if ((irq < 16) && (apic_reserved_irqlist[irq])) - continue; + /* only supports MSI at the moment, will add MSI-X support later */ + if (type != DDI_INTR_TYPE_MSI) + return (0); - if ((apic_irq_table[irq] == NULL) || - (apic_irq_table[irq]->airq_dip == dip)) { + DDI_INTR_IMPLDBG((CE_CONT, "apic_alloc_vectors: dip=0x%p type=%d " + "inum=0x%x pri=0x%x count=0x%x behavior=%d\n", + (void *)dip, type, inum, pri, count, behavior)); - prsirqlistp = acpi_insert_prs_irq_ent( - prsirqlistp, 0 /* Highest priority */, irq, - &irqlistent->intr_flags, - &irqlistent->acpi_prs_prv); + if (count > 1) { + if (behavior == DDI_INTR_ALLOC_STRICT && + (apic_multi_msi_enable == 0 || count > apic_multi_msi_max)) + return (0); - /* - * If we do not prefer the current irq from _CRS - * or if we do and this irq is the same as the - * current irq from _CRS, this is the one - * to pick. - */ - if (!(apic_prefer_crs) || (irq == crs_irq)) { - return (prsirqlistp); - } - continue; - } + if (apic_multi_msi_enable == 0) + count = 1; + else if (count > apic_multi_msi_max) + count = apic_multi_msi_max; + } - /* - * Edge-triggered interrupts cannot be shared - */ - if (irqlistent->intr_flags.intr_el == INTR_EL_EDGE) - continue; + if ((rcount = apic_navail_vector(dip, pri)) > count) + rcount = count; + else if (rcount == 0 || (rcount < count && + behavior == DDI_INTR_ALLOC_STRICT)) + return (0); - /* - * To work around BIOSes that contain incorrect - * interrupt polarity information in interrupt - * descriptors returned by _PRS, we assume that - * the polarity of the other device sharing this - * interrupt controller input is compatible. - * If it's not, the caller will catch it when - * the caller invokes the link device's _CRS method - * (after invoking its _SRS method). - */ - iflags = irqlistent->intr_flags; - iflags.intr_po = - apic_irq_table[irq]->airq_iflag.intr_po; + /* if not ISP2, then round it down */ + if (!ISP2(rcount)) + rcount = 1 << (highbit(rcount) - 1); - if (!acpi_intr_compatible(iflags, - apic_irq_table[irq]->airq_iflag)) - continue; + mutex_enter(&airq_mutex); - /* - * If we prefer the irq from _CRS, no need - * to search any further (and make sure - * to add this irq with the highest priority - * so it's tried first). - */ - if (crs_irq == irq && apic_prefer_crs) { + for (start = 0; rcount > 0; rcount >>= 1) { + if ((start = apic_find_multi_vectors(pri, rcount)) != 0 || + behavior == DDI_INTR_ALLOC_STRICT) + break; + } - return (acpi_insert_prs_irq_ent( - prsirqlistp, - 0 /* Highest priority */, - irq, &iflags, - &irqlistent->acpi_prs_prv)); - } + if (start == 0) { + /* no vector available */ + mutex_exit(&airq_mutex); + return (0); + } - /* - * Priority is equal to the share count (lower - * share count is higher priority). Note that - * the intr flags passed in here are the ones we - * changed above -- if incorrect, it will be - * caught by the caller's _CRS flags comparison. - */ - prsirqlistp = acpi_insert_prs_irq_ent( - prsirqlistp, - apic_irq_table[irq]->airq_share, irq, - &iflags, &irqlistent->acpi_prs_prv); + major = (dip != NULL) ? ddi_name_to_major(ddi_get_name(dip)) : 0; + for (i = 0; i < rcount; i++) { + if ((irqno = apic_allocate_irq(apic_first_avail_irq)) == + (uchar_t)-1) { + mutex_exit(&airq_mutex); + DDI_INTR_IMPLDBG((CE_CONT, "apic_alloc_vectors: " + "apic_allocate_irq failed\n")); + return (i); } - - /* Go to the next irqlist entry */ - irqlistent = irqlistent->next; + apic_max_device_irq = max(irqno, apic_max_device_irq); + apic_min_device_irq = min(irqno, apic_min_device_irq); + irqptr = apic_irq_table[irqno]; +#ifdef DEBUG + if (apic_vector_to_irq[start + i] != APIC_RESV_IRQ) + DDI_INTR_IMPLDBG((CE_CONT, "apic_alloc_vectors: " + "apic_vector_to_irq is not APIC_RESV_IRQ\n")); +#endif + apic_vector_to_irq[start + i] = (uchar_t)irqno; + + irqptr->airq_vector = (uchar_t)(start + i); + irqptr->airq_ioapicindex = (uchar_t)inum; /* start */ + irqptr->airq_intin_no = (uchar_t)rcount; + irqptr->airq_ipl = pri; + irqptr->airq_vector = start + i; + irqptr->airq_origirq = (uchar_t)(inum + i); + irqptr->airq_share_id = 0; + irqptr->airq_mps_intr_index = MSI_INDEX; + irqptr->airq_dip = dip; + irqptr->airq_major = major; + if (i == 0) /* they all bound to the same cpu */ + cpu = irqptr->airq_cpu = apic_bind_intr(dip, irqno, + 0xff, 0xff); + else + irqptr->airq_cpu = cpu; + DDI_INTR_IMPLDBG((CE_CONT, "apic_alloc_vectors: irq=0x%x " + "dip=0x%p vector=0x%x origirq=0x%x pri=0x%x\n", irqno, + (void *)irqptr->airq_dip, irqptr->airq_vector, + irqptr->airq_origirq, pri)); } - - return (prsirqlistp); + mutex_exit(&airq_mutex); + return (rcount); } /* - * Configures the irq for the interrupt link device identified by - * acpipsmlnkp. - * - * Gets the current and the list of possible irq settings for the - * device. If apic_unconditional_srs is not set, and the current - * resource setting is in the list of possible irq settings, - * current irq resource setting is passed to the caller. - * - * Otherwise, picks an irq number from the list of possible irq - * settings, and sets the irq of the device to this value. - * If prefer_crs is set, among a set of irq numbers in the list that have - * the least number of devices sharing the interrupt, we pick current irq - * resource setting if it is a member of this set. - * - * Passes the irq number in the value pointed to by pci_irqp, and - * polarity and sensitivity in the structure pointed to by dipintrflagp - * to the caller. - * - * Note that if setting the irq resource failed, but successfuly obtained - * the current irq resource settings, passes the current irq resources - * and considers it a success. - * - * Returns: - * ACPI_PSM_SUCCESS on success. - * - * ACPI_PSM_FAILURE if an error occured during the configuration or - * if a suitable irq was not found for this device, or if setting the - * irq resource and obtaining the current resource fails. - * + * Allocate a free vector for irq at ipl. Takes care of merging of multiple + * IPLs into a single APIC level as well as stretching some IPLs onto multiple + * levels. APIC_HI_PRI_VECTS interrupts are reserved for high priority + * requests and allocated only when pri is set. */ -static int -apic_acpi_irq_configure(acpi_psm_lnk_t *acpipsmlnkp, dev_info_t *dip, - int *pci_irqp, iflag_t *dipintr_flagp) +uchar_t +apic_allocate_vector(int ipl, int irq, int pri) { + int lowest, highest, i; - int32_t irq; - int cur_irq = -1; - acpi_irqlist_t *irqlistp; - prs_irq_list_t *prs_irq_listp, *prs_irq_entp; - boolean_t found_irq = B_FALSE; + highest = apic_ipltopri[ipl] + APIC_VECTOR_MASK; + lowest = apic_ipltopri[ipl - 1] + APIC_VECTOR_PER_IPL; - dipintr_flagp->bustype = BUS_PCI; + if (highest < lowest) /* Both ipl and ipl - 1 map to same pri */ + lowest -= APIC_VECTOR_PER_IPL; - if ((acpi_get_possible_irq_resources(acpipsmlnkp, &irqlistp)) - == ACPI_PSM_FAILURE) { - APIC_VERBOSE_IRQ((CE_WARN, "!pcplusmp: Unable to determine " - "or assign IRQ for device %s, instance #%d: The system was " - "unable to get the list of potential IRQs from ACPI.", - ddi_get_name(dip), ddi_get_instance(dip))); +#ifdef DEBUG + if (apic_restrict_vector) /* for testing shared interrupt logic */ + highest = lowest + apic_restrict_vector + APIC_HI_PRI_VECTS; +#endif /* DEBUG */ + if (pri == 0) + highest -= APIC_HI_PRI_VECTS; - return (ACPI_PSM_FAILURE); + for (i = lowest; i < highest; i++) { + if (APIC_CHECK_RESERVE_VECTORS(i)) + continue; + if (apic_vector_to_irq[i] == APIC_RESV_IRQ) { + apic_vector_to_irq[i] = (uchar_t)irq; + return (i); + } } - if ((acpi_get_current_irq_resource(acpipsmlnkp, &cur_irq, - dipintr_flagp) == ACPI_PSM_SUCCESS) && (!apic_unconditional_srs) && - (cur_irq > 0)) { - /* - * If an IRQ is set in CRS and that IRQ exists in the set - * returned from _PRS, return that IRQ, otherwise print - * a warning - */ - - if (acpi_irqlist_find_irq(irqlistp, cur_irq, NULL) - == ACPI_PSM_SUCCESS) { - - ASSERT(pci_irqp != NULL); - *pci_irqp = cur_irq; - acpi_free_irqlist(irqlistp); - return (ACPI_PSM_SUCCESS); - } + return (0); +} - APIC_VERBOSE_IRQ((CE_WARN, "!pcplusmp: Could not find the " - "current irq %d for device %s, instance #%d in ACPI's " - "list of possible irqs for this device. Picking one from " - " the latter list.", cur_irq, ddi_get_name(dip), - ddi_get_instance(dip))); - } +/* Mark vector as not being used by any irq */ +void +apic_free_vector(uchar_t vector) +{ + apic_vector_to_irq[vector] = APIC_RESV_IRQ; +} - if ((prs_irq_listp = apic_choose_irqs_from_prs(irqlistp, dip, - cur_irq)) == NULL) { +uint32_t +ioapic_read(int ioapic_ix, uint32_t reg) +{ + volatile uint32_t *ioapic; - APIC_VERBOSE_IRQ((CE_WARN, "!pcplusmp: Could not find a " - "suitable irq from the list of possible irqs for device " - "%s, instance #%d in ACPI's list of possible irqs", - ddi_get_name(dip), ddi_get_instance(dip))); + ioapic = apicioadr[ioapic_ix]; + ioapic[APIC_IO_REG] = reg; + return (ioapic[APIC_IO_DATA]); +} - acpi_free_irqlist(irqlistp); - return (ACPI_PSM_FAILURE); - } +void +ioapic_write(int ioapic_ix, uint32_t reg, uint32_t value) +{ + volatile uint32_t *ioapic; - acpi_free_irqlist(irqlistp); + ioapic = apicioadr[ioapic_ix]; + ioapic[APIC_IO_REG] = reg; + ioapic[APIC_IO_DATA] = value; +} - for (prs_irq_entp = prs_irq_listp; - prs_irq_entp != NULL && found_irq == B_FALSE; - prs_irq_entp = prs_irq_entp->next) { +static processorid_t +apic_find_cpu(int flag) +{ + processorid_t acid = 0; + int i; - acpipsmlnkp->acpi_prs_prv = prs_irq_entp->prsprv; - irq = prs_irq_entp->irq; + /* Find the first CPU with the passed-in flag set */ + for (i = 0; i < apic_nproc; i++) { + if (apic_cpus[i].aci_status & flag) { + acid = i; + break; + } + } - APIC_VERBOSE_IRQ((CE_CONT, "!pcplusmp: Setting irq %d for " - "device %s instance #%d\n", irq, ddi_get_name(dip), - ddi_get_instance(dip))); + ASSERT((apic_cpus[acid].aci_status & flag) != 0); + return (acid); +} - if ((acpi_set_irq_resource(acpipsmlnkp, irq)) - == ACPI_PSM_SUCCESS) { - /* - * setting irq was successful, check to make sure CRS - * reflects that. If CRS does not agree with what we - * set, return the irq that was set. - */ +/* + * Call rebind to do the actual programming. + * Must be called with interrupts disabled and apic_ioapic_lock held + * 'p' is polymorphic -- if this function is called to process a deferred + * reprogramming, p is of type 'struct ioapic_reprogram_data *', from which + * the irq pointer is retrieved. If not doing deferred reprogramming, + * p is of the type 'apic_irq_t *'. + * + * apic_ioapic_lock must be held across this call, as it protects apic_rebind + * and it protects apic_find_cpu() from a race in which a CPU can be taken + * offline after a cpu is selected, but before apic_rebind is called to + * bind interrupts to it. + */ +int +apic_setup_io_intr(void *p, int irq, boolean_t deferred) +{ + apic_irq_t *irqptr; + struct ioapic_reprogram_data *drep = NULL; + int rv; - if (acpi_get_current_irq_resource(acpipsmlnkp, &cur_irq, - dipintr_flagp) == ACPI_PSM_SUCCESS) { - - if (cur_irq != irq) - APIC_VERBOSE_IRQ((CE_WARN, - "!pcplusmp: IRQ resource set " - "(irqno %d) for device %s " - "instance #%d, differs from " - "current setting irqno %d", - irq, ddi_get_name(dip), - ddi_get_instance(dip), cur_irq)); - } else { - /* - * On at least one system, there was a bug in - * a DSDT method called by _STA, causing _STA to - * indicate that the link device was disabled - * (when, in fact, it was enabled). Since _SRS - * succeeded, assume that _CRS is lying and use - * the iflags from this _PRS interrupt choice. - * If we're wrong about the flags, the polarity - * will be incorrect and we may get an interrupt - * storm, but there's not much else we can do - * at this point. - */ - *dipintr_flagp = prs_irq_entp->intrflags; - } + if (deferred) { + drep = (struct ioapic_reprogram_data *)p; + ASSERT(drep != NULL); + irqptr = drep->irqp; + } else + irqptr = (apic_irq_t *)p; - /* - * Return the irq that was set, and not what _CRS - * reports, since _CRS has been seen to return - * different IRQs than what was passed to _SRS on some - * systems (and just not return successfully on others). - */ - cur_irq = irq; - found_irq = B_TRUE; - } else { - APIC_VERBOSE_IRQ((CE_WARN, "!pcplusmp: set resource " - "irq %d failed for device %s instance #%d", - irq, ddi_get_name(dip), ddi_get_instance(dip))); + ASSERT(irqptr != NULL); - if (cur_irq == -1) { - acpi_destroy_prs_irq_list(&prs_irq_listp); - return (ACPI_PSM_FAILURE); - } - } + rv = apic_rebind(irqptr, apic_irq_table[irq]->airq_cpu, drep); + if (rv) { + /* + * CPU is not up or interrupts are disabled. Fall back to + * the first available CPU + */ + rv = apic_rebind(irqptr, apic_find_cpu(APIC_CPU_INTR_ENABLE), + drep); } - acpi_destroy_prs_irq_list(&prs_irq_listp); + return (rv); +} - if (!found_irq) - return (ACPI_PSM_FAILURE); - ASSERT(pci_irqp != NULL); - *pci_irqp = cur_irq; - return (ACPI_PSM_SUCCESS); +uchar_t +apic_modify_vector(uchar_t vector, int irq) +{ + apic_vector_to_irq[vector] = (uchar_t)irq; + return (vector); } diff --git a/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c b/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c index 742779383a..02617ae071 100644 --- a/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c +++ b/usr/src/uts/i86pc/io/pcplusmp/apic_introp.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,7 +32,8 @@ #include <sys/cpuvar.h> #include <sys/psm.h> -#include "apic.h" +#include <sys/archsystm.h> +#include <sys/apic.h> #include <sys/sunddi.h> #include <sys/ddi_impldefs.h> #include <sys/mach_intr.h> @@ -52,15 +53,6 @@ apic_irq_t *apic_find_irq(dev_info_t *, struct intrspec *, int); static int apic_get_pending(apic_irq_t *, int); static void apic_clear_mask(apic_irq_t *); static void apic_set_mask(apic_irq_t *); -static uchar_t apic_find_multi_vectors(int, int); -int apic_navail_vector(dev_info_t *, int); -int apic_alloc_vectors(dev_info_t *, int, int, int, int, int); -void apic_free_vectors(dev_info_t *, int, int, int, int); -int apic_intr_ops(dev_info_t *, ddi_intr_handle_impl_t *, - psm_intr_op_t, int *); - -extern int intr_clear(void); -extern void intr_restore(uint_t); /* * MSI support flag: @@ -78,19 +70,6 @@ int apic_support_msi = 0; int apic_multi_msi_enable = 1; int apic_multi_msi_max = 2; -extern uchar_t apic_ipltopri[MAXIPL+1]; -extern uchar_t apic_vector_to_irq[APIC_MAX_VECTOR+1]; -extern int apic_max_device_irq; -extern int apic_min_device_irq; -extern apic_irq_t *apic_irq_table[APIC_MAX_VECTOR+1]; -extern volatile uint32_t *apicadr; /* virtual addr of local APIC */ -extern volatile int32_t *apicioadr[MAX_IO_APIC]; -extern lock_t apic_ioapic_lock; -extern kmutex_t airq_mutex; -extern apic_cpus_info_t *apic_cpus; -extern int apic_first_avail_irq; - - /* * apic_pci_msi_enable_vector: * Set the address/data fields in the MSI/X capability structure @@ -202,7 +181,7 @@ apic_navail_vector(dev_info_t *dip, int pri) * Caller needs to make sure that count has to be power of 2 and should not * be < 1. */ -static uchar_t +uchar_t apic_find_multi_vectors(int pri, int count) { int lowest, highest, i, navail, start, msibits; @@ -245,6 +224,7 @@ apic_find_multi_vectors(int pri, int count) return (0); } + /* * It finds the apic_irq_t associates with the dip, ispec and type. */ @@ -288,7 +268,7 @@ apic_get_pending(apic_irq_t *irqp, int type) { int bit, index, irr, pending; int intin_no; - volatile int32_t *ioapic; + int apic_ix; DDI_INTR_IMPLDBG((CE_CONT, "apic_get_pending: irqp: %p, cpuid: %x " "type: %x\n", (void *)irqp, irqp->airq_cpu & ~IRQ_USER_BOUND, @@ -309,8 +289,8 @@ apic_get_pending(apic_irq_t *irqp, int type) if (!pending && (type == DDI_INTR_TYPE_FIXED)) { /* check I/O APIC for fixed interrupt */ intin_no = irqp->airq_intin_no; - ioapic = apicioadr[irqp->airq_ioapicindex]; - pending = (READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no) & + apic_ix = irqp->airq_ioapicindex; + pending = (READ_IOAPIC_RDT_ENTRY_LOW_DWORD(apic_ix, intin_no) & AV_PENDING) ? 1 : 0; } return (pending); @@ -324,23 +304,23 @@ static void apic_clear_mask(apic_irq_t *irqp) { int intin_no; - int iflag; + ulong_t iflag; int32_t rdt_entry; - volatile int32_t *ioapic; + int apic_ix; DDI_INTR_IMPLDBG((CE_CONT, "apic_clear_mask: irqp: %p\n", (void *)irqp)); intin_no = irqp->airq_intin_no; - ioapic = apicioadr[irqp->airq_ioapicindex]; + apic_ix = irqp->airq_ioapicindex; iflag = intr_clear(); lock_set(&apic_ioapic_lock); - rdt_entry = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no); + rdt_entry = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(apic_ix, intin_no); /* clear mask */ - WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no, + WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(apic_ix, intin_no, ((~AV_MASK) & rdt_entry)); lock_clear(&apic_ioapic_lock); @@ -355,23 +335,23 @@ static void apic_set_mask(apic_irq_t *irqp) { int intin_no; - volatile int32_t *ioapic; - int iflag; + int apic_ix; + ulong_t iflag; int32_t rdt_entry; DDI_INTR_IMPLDBG((CE_CONT, "apic_set_mask: irqp: %p\n", (void *)irqp)); intin_no = irqp->airq_intin_no; - ioapic = apicioadr[irqp->airq_ioapicindex]; + apic_ix = irqp->airq_ioapicindex; iflag = intr_clear(); lock_set(&apic_ioapic_lock); - rdt_entry = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no); + rdt_entry = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(apic_ix, intin_no); /* mask it */ - WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no, + WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(apic_ix, intin_no, (AV_MASK | rdt_entry)); lock_clear(&apic_ioapic_lock); @@ -379,105 +359,6 @@ apic_set_mask(apic_irq_t *irqp) } -/* - * This function allocate "count" vector(s) for the given "dip/pri/type" - */ -int -apic_alloc_vectors(dev_info_t *dip, int inum, int count, int pri, int type, - int behavior) -{ - int rcount, i; - uchar_t start, irqno, cpu; - major_t major; - apic_irq_t *irqptr; - - /* only supports MSI at the moment, will add MSI-X support later */ - if (type != DDI_INTR_TYPE_MSI) - return (0); - - DDI_INTR_IMPLDBG((CE_CONT, "apic_alloc_vectors: dip=0x%p type=%d " - "inum=0x%x pri=0x%x count=0x%x behavior=%d\n", - (void *)dip, type, inum, pri, count, behavior)); - - if (count > 1) { - if (behavior == DDI_INTR_ALLOC_STRICT && - (apic_multi_msi_enable == 0 || count > apic_multi_msi_max)) - return (0); - - if (apic_multi_msi_enable == 0) - count = 1; - else if (count > apic_multi_msi_max) - count = apic_multi_msi_max; - } - - if ((rcount = apic_navail_vector(dip, pri)) > count) - rcount = count; - else if (rcount == 0 || (rcount < count && - behavior == DDI_INTR_ALLOC_STRICT)) - return (0); - - /* if not ISP2, then round it down */ - if (!ISP2(rcount)) - rcount = 1 << (highbit(rcount) - 1); - - mutex_enter(&airq_mutex); - - for (start = 0; rcount > 0; rcount >>= 1) { - if ((start = apic_find_multi_vectors(pri, rcount)) != 0 || - behavior == DDI_INTR_ALLOC_STRICT) - break; - } - - if (start == 0) { - /* no vector available */ - mutex_exit(&airq_mutex); - return (0); - } - - major = (dip != NULL) ? ddi_name_to_major(ddi_get_name(dip)) : 0; - for (i = 0; i < rcount; i++) { - if ((irqno = apic_allocate_irq(apic_first_avail_irq)) == - (uchar_t)-1) { - mutex_exit(&airq_mutex); - DDI_INTR_IMPLDBG((CE_CONT, "apic_alloc_vectors: " - "apic_allocate_irq failed\n")); - return (i); - } - apic_max_device_irq = max(irqno, apic_max_device_irq); - apic_min_device_irq = min(irqno, apic_min_device_irq); - irqptr = apic_irq_table[irqno]; -#ifdef DEBUG - if (apic_vector_to_irq[start + i] != APIC_RESV_IRQ) - DDI_INTR_IMPLDBG((CE_CONT, "apic_alloc_vectors: " - "apic_vector_to_irq is not APIC_RESV_IRQ\n")); -#endif - apic_vector_to_irq[start + i] = (uchar_t)irqno; - - irqptr->airq_vector = (uchar_t)(start + i); - irqptr->airq_ioapicindex = (uchar_t)inum; /* start */ - irqptr->airq_intin_no = (uchar_t)rcount; - irqptr->airq_ipl = pri; - irqptr->airq_vector = start + i; - irqptr->airq_origirq = (uchar_t)(inum + i); - irqptr->airq_share_id = 0; - irqptr->airq_mps_intr_index = MSI_INDEX; - irqptr->airq_dip = dip; - irqptr->airq_major = major; - if (i == 0) /* they all bound to the same cpu */ - cpu = irqptr->airq_cpu = apic_bind_intr(dip, irqno, - 0xff, 0xff); - else - irqptr->airq_cpu = cpu; - DDI_INTR_IMPLDBG((CE_CONT, "apic_alloc_vectors: irq=0x%x " - "dip=0x%p vector=0x%x origirq=0x%x pri=0x%x\n", irqno, - (void *)irqptr->airq_dip, irqptr->airq_vector, - irqptr->airq_origirq, pri)); - } - mutex_exit(&airq_mutex); - return (rcount); -} - - void apic_free_vectors(dev_info_t *dip, int inum, int count, int pri, int type) { @@ -794,6 +675,7 @@ apic_pci_msi_disable_mode(dev_info_t *rdip, int type, int inum) return (PSM_SUCCESS); } + /* * This function provides external interface to the nexus for all * functionalities related to the new DDI interrupt framework. @@ -920,7 +802,7 @@ apic_intr_ops(dev_info_t *dip, ddi_intr_handle_impl_t *hdlp, hdlp->ih_scratch1, new_priority, hdlp->ih_type, DDI_INTR_ALLOC_STRICT); - /* Did we get the new vectors? */ + /* Did we get new vectors? */ if (!count_vec) return (PSM_FAILURE); diff --git a/usr/src/uts/i86pc/io/psm/uppc.c b/usr/src/uts/i86pc/io/psm/uppc.c index 6556f3eec4..ac7fb4f399 100644 --- a/usr/src/uts/i86pc/io/psm/uppc.c +++ b/usr/src/uts/i86pc/io/psm/uppc.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,16 +38,11 @@ #include <sys/pit.h> #include <sys/psm_common.h> #include <sys/atomic.h> +#include <sys/archsystm.h> #define NSEC_IN_SEC 1000000000 /* - * External References - */ -extern int intr_clear(void); -extern void intr_restore(uint_t); - -/* * Local Function Prototypes */ static void uppc_softinit(void); @@ -158,7 +153,7 @@ static struct psm_ops uppc_ops = { uppc_gethrtime, /* psm_gethrtime */ uppc_get_next_processorid, /* psm_get_next_processorid */ - (void (*)(processorid_t, caddr_t))NULL, /* psm_cpu_start */ + (int (*)(processorid_t, caddr_t))NULL, /* psm_cpu_start */ (int (*)(void))NULL, /* psm_post_cpu_start */ uppc_shutdown, /* psm_shutdown */ (int (*)(int, int))NULL, /* psm_get_ipivect */ @@ -166,9 +161,6 @@ static struct psm_ops uppc_ops = { uppc_translate_irq, /* psm_translate_irq */ - (int (*)(todinfo_t *))NULL, /* psm_tod_get */ - (int (*)(todinfo_t *))NULL, /* psm_tod_set */ - (void (*)(int, char *))NULL, /* psm_notify_error */ (void (*)(int msg))NULL, /* psm_notify_func */ (void (*)(hrtime_t time))NULL, /* psm_timer_reprogram */ @@ -801,7 +793,6 @@ uppc_translate_irq(dev_info_t *dip, int irqno) UPPC_VERBOSE_IRQ((CE_CONT, "!uppc: non-pci," "irqno %d device %s instance %d\n", irqno, ddi_get_name(dip), ddi_get_instance(dip))); - } return (irqno); @@ -922,7 +913,8 @@ static hrtime_t uppc_gethrtime() { hrtime_t timeval, temp; - unsigned int oflags, ctr0; + unsigned int ctr0; + ulong_t oflags; oflags = intr_clear(); /* disable ints */ lock_set(&uppc_gethrtime_lock); diff --git a/usr/src/uts/common/io/hardclk.c b/usr/src/uts/i86pc/io/todpc_subr.c index c1dedf6801..7e55876af3 100644 --- a/usr/src/uts/common/io/hardclk.c +++ b/usr/src/uts/i86pc/io/todpc_subr.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,32 +47,27 @@ #include <sys/stat.h> #include <sys/sunddi.h> -static int pc_rtcget(unsigned char *buf); -static void pc_rtcput(unsigned char *buf); - -#define CLOCK_RES 1000 /* 1 microsec in nanosecs */ - -int clock_res = CLOCK_RES; +static int todpc_rtcget(unsigned char *buf); +static void todpc_rtcput(unsigned char *buf); /* * Machine-dependent clock routines. */ -extern long gmt_lag; - /* * Write the specified time into the clock chip. * Must be called with tod_lock held. */ -void -pc_tod_set(timestruc_t ts) +/*ARGSUSED*/ +static void +todpc_set(tod_ops_t *top, timestruc_t ts) { - todinfo_t tod = utc_to_tod(ts.tv_sec - gmt_lag); + todinfo_t tod = utc_to_tod(ts.tv_sec - ggmtl()); struct rtc_t rtc; ASSERT(MUTEX_HELD(&tod_lock)); - if (pc_rtcget((unsigned char *)&rtc)) + if (todpc_rtcget((unsigned char *)&rtc)) return; /* @@ -95,7 +90,7 @@ pc_tod_set(timestruc_t ts) rtc.rtc_min = BYTE_TO_BCD(tod.tod_min); rtc.rtc_sec = BYTE_TO_BCD(tod.tod_sec); - pc_rtcput((unsigned char *)&rtc); + todpc_rtcput((unsigned char *)&rtc); } /* @@ -103,8 +98,9 @@ pc_tod_set(timestruc_t ts) * Assumes that the year in the clock chip is valid. * Must be called with tod_lock held. */ -timestruc_t -pc_tod_get(void) +/*ARGSUSED*/ +static timestruc_t +todpc_get(tod_ops_t *top) { timestruc_t ts; todinfo_t tod; @@ -115,7 +111,7 @@ pc_tod_get(void) ASSERT(MUTEX_HELD(&tod_lock)); - if (pc_rtcget((unsigned char *)&rtc)) { + if (todpc_rtcget((unsigned char *)&rtc)) { ts.tv_sec = 0; ts.tv_nsec = 0; tod_fault_reset(); @@ -154,7 +150,7 @@ pc_tod_get(void) tod.tod_min = BCD_TO_BYTE(rtc.rtc_min); tod.tod_sec = BCD_TO_BYTE(rtc.rtc_sec); - ts.tv_sec = tod_to_utc(tod) + gmt_lag; + ts.tv_sec = tod_to_utc(tod) + ggmtl(); ts.tv_nsec = 0; return (ts); @@ -162,7 +158,7 @@ pc_tod_get(void) /* * Routine to read contents of real time clock to the specified buffer. - * Returns -1 if clock not valid, or -2 if clock data cannot be read + * Returns ENXIO if clock not valid, or EAGAIN if clock data cannot be read * else 0. * The routine will busy wait for the Update-In-Progress flag to clear. * On completion of the reads the Seconds register is re-read and the @@ -174,7 +170,7 @@ pc_tod_get(void) */ static int -pc_rtcget(unsigned char *buf) +todpc_rtcget(unsigned char *buf) { unsigned char reg; int i; @@ -186,11 +182,11 @@ pc_rtcget(unsigned char *buf) outb(RTC_ADDR, RTC_D); /* check if clock valid */ reg = inb(RTC_DATA); if ((reg & RTC_VRT) == 0) - return (-1); + return (ENXIO); checkuip: if (retries-- < 0) - return (-2); + return (EAGAIN); outb(RTC_ADDR, RTC_A); /* check if update in progress */ reg = inb(RTC_DATA); if (reg & RTC_UIP) { @@ -221,7 +217,7 @@ checkuip: * raised to 5. */ static void -pc_rtcput(unsigned char *buf) +todpc_rtcput(unsigned char *buf) { unsigned char reg; int i; @@ -240,22 +236,15 @@ pc_rtcput(unsigned char *buf) outb(RTC_DATA, reg & ~RTC_SET); /* allow time update */ } +static tod_ops_t todpc_ops = { + TOD_OPS_VERSION, + todpc_get, + todpc_set, + NULL +}; + /* - * The following wrappers have been added so that locking - * can be exported to platform-independent clock routines - * (ie adjtime(), clock_setttime()), via a functional interface. + * Initialize for the default TOD ops vector for use on hardware. */ -int -hr_clock_lock(void) -{ - ushort_t s; - - CLOCK_LOCK(&s); - return (s); -} -void -hr_clock_unlock(int s) -{ - CLOCK_UNLOCK(s); -} +tod_ops_t *tod_ops = &todpc_ops; diff --git a/usr/src/uts/i86pc/io/xsvc/xsvc.c b/usr/src/uts/i86pc/io/xsvc/xsvc.c new file mode 100644 index 0000000000..2b797dc904 --- /dev/null +++ b/usr/src/uts/i86pc/io/xsvc/xsvc.c @@ -0,0 +1,974 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/errno.h> +#include <sys/types.h> +#include <sys/conf.h> +#include <sys/kmem.h> +#include <sys/ddi.h> +#include <sys/stat.h> +#include <sys/sunddi.h> +#include <sys/file.h> +#include <sys/open.h> +#include <sys/modctl.h> +#include <sys/ddi_impldefs.h> +#include <vm/seg_kmem.h> +#include <sys/vmsystm.h> +#include <sys/sysmacros.h> +#include <sys/ddidevmap.h> +#include <sys/avl.h> + +#include <sys/xsvc.h> + +/* total max memory which can be alloced with ioctl interface */ +uint64_t xsvc_max_memory = 10 * 1024 * 1024; + +extern void i86_va_map(caddr_t vaddr, struct as *asp, caddr_t kaddr); + + +static int xsvc_open(dev_t *devp, int flag, int otyp, cred_t *cred); +static int xsvc_close(dev_t devp, int flag, int otyp, cred_t *cred); +static int xsvc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred, + int *rval); +static int xsvc_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len, + size_t *maplen, uint_t model); +static int xsvc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); +static int xsvc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); +static int xsvc_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, + void **result); + +static struct cb_ops xsvc_cb_ops = { + xsvc_open, /* cb_open */ + xsvc_close, /* cb_close */ + nodev, /* cb_strategy */ + nodev, /* cb_print */ + nodev, /* cb_dump */ + nodev, /* cb_read */ + nodev, /* cb_write */ + xsvc_ioctl, /* cb_ioctl */ + xsvc_devmap, /* cb_devmap */ + NULL, /* cb_mmap */ + NULL, /* cb_segmap */ + nochpoll, /* cb_chpoll */ + ddi_prop_op, /* cb_prop_op */ + NULL, /* cb_stream */ + D_NEW | D_MP | D_64BIT | D_DEVMAP, /* cb_flag */ + CB_REV +}; + +static struct dev_ops xsvc_dev_ops = { + DEVO_REV, /* devo_rev */ + 0, /* devo_refcnt */ + xsvc_getinfo, /* devo_getinfo */ + nulldev, /* devo_identify */ + nulldev, /* devo_probe */ + xsvc_attach, /* devo_attach */ + xsvc_detach, /* devo_detach */ + nodev, /* devo_reset */ + &xsvc_cb_ops, /* devo_cb_ops */ + NULL, /* devo_bus_ops */ + NULL /* power */ +}; + +static struct modldrv xsvc_modldrv = { + &mod_driverops, /* Type of module. This one is a driver */ + "xsvc driver v%I%", /* Name of the module. */ + &xsvc_dev_ops, /* driver ops */ +}; + +static struct modlinkage xsvc_modlinkage = { + MODREV_1, + (void *) &xsvc_modldrv, + NULL +}; + + +static int xsvc_ioctl_alloc_memory(xsvc_state_t *state, void *arg, int mode); +static int xsvc_ioctl_flush_memory(xsvc_state_t *state, void *arg, int mode); +static int xsvc_ioctl_free_memory(xsvc_state_t *state, void *arg, int mode); +static int xsvc_mem_alloc(xsvc_state_t *state, uint64_t key, + xsvc_mem_t **mp); +static void xsvc_mem_free(xsvc_state_t *state, xsvc_mem_t *mp); +static xsvc_mem_t *xsvc_mem_lookup(xsvc_state_t *state, + uint64_t key); +static int xsvc_mnode_key_compare(const void *q, const void *e); +static int xsvc_umem_cookie_alloc(caddr_t kva, size_t size, int flags, + ddi_umem_cookie_t *cookiep); +static void xsvc_umem_cookie_free(ddi_umem_cookie_t *cookiep); +static void xsvc_devmap_unmap(devmap_cookie_t dhp, void *pvtp, offset_t off, + size_t len, devmap_cookie_t new_dhp1, void **new_pvtp1, + devmap_cookie_t new_dhp2, void **new_pvtp2); + + +void *xsvc_statep; + +static ddi_device_acc_attr_t xsvc_device_attr = { + DDI_DEVICE_ATTR_V0, + DDI_NEVERSWAP_ACC, + DDI_STRICTORDER_ACC +}; + +static struct devmap_callback_ctl xsvc_callbk = { + DEVMAP_OPS_REV, + NULL, + NULL, + NULL, + xsvc_devmap_unmap +}; + + +/* + * _init() + * + */ +int +_init(void) +{ + int err; + + err = ddi_soft_state_init(&xsvc_statep, sizeof (xsvc_state_t), 1); + if (err != 0) { + return (err); + } + + err = mod_install(&xsvc_modlinkage); + if (err != 0) { + ddi_soft_state_fini(&xsvc_statep); + return (err); + } + + return (0); +} + +/* + * _info() + * + */ +int +_info(struct modinfo *modinfop) +{ + return (mod_info(&xsvc_modlinkage, modinfop)); +} + +/* + * _fini() + * + */ +int +_fini(void) +{ + int err; + + err = mod_remove(&xsvc_modlinkage); + if (err != 0) { + return (err); + } + + ddi_soft_state_fini(&xsvc_statep); + + return (0); +} + +/* + * xsvc_attach() + * + */ +static int +xsvc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) +{ + xsvc_state_t *state; + int maxallocmem; + int instance; + int err; + + + switch (cmd) { + case DDI_ATTACH: + break; + + case DDI_RESUME: + return (DDI_SUCCESS); + + default: + return (DDI_FAILURE); + } + + instance = ddi_get_instance(dip); + err = ddi_soft_state_zalloc(xsvc_statep, instance); + if (err != DDI_SUCCESS) { + return (DDI_FAILURE); + } + state = ddi_get_soft_state(xsvc_statep, instance); + if (state == NULL) { + goto attachfail_get_soft_state; + } + + state->xs_dip = dip; + state->xs_instance = instance; + + /* Initialize allocation count */ + mutex_init(&state->xs_mutex, NULL, MUTEX_DRIVER, NULL); + state->xs_currently_alloced = 0; + + /* create the minor node (for the ioctl) */ + err = ddi_create_minor_node(dip, "xsvc", S_IFCHR, instance, DDI_PSEUDO, + 0); + if (err != DDI_SUCCESS) { + goto attachfail_minor_node; + } + + /* + * the maxallocmem property will override the default (xsvc_max_memory). + * This is the maximum total memory the ioctl will allow to be alloced. + */ + maxallocmem = ddi_prop_get_int(DDI_DEV_T_ANY, state->xs_dip, + DDI_PROP_DONTPASS, "maxallocmem", -1); + if (maxallocmem >= 0) { + xsvc_max_memory = maxallocmem * 1024; + } + + /* Initialize list of memory allocs */ + mutex_init(&state->xs_mlist.ml_mutex, NULL, MUTEX_DRIVER, NULL); + avl_create(&state->xs_mlist.ml_avl, xsvc_mnode_key_compare, + sizeof (xsvc_mnode_t), offsetof(xsvc_mnode_t, mn_link)); + + /* Report that driver was loaded */ + ddi_report_dev(dip); + + return (DDI_SUCCESS); + +attachfail_minor_node: + mutex_destroy(&state->xs_mutex); +attachfail_get_soft_state: + (void) ddi_soft_state_free(xsvc_statep, instance); + + return (err); +} + +/* + * xsvc_detach() + * + */ +static int +xsvc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) +{ + xsvc_state_t *state; + xsvc_mnode_t *mnode; + xsvc_mem_t *mp; + int instance; + + + instance = ddi_get_instance(dip); + state = ddi_get_soft_state(xsvc_statep, instance); + if (state == NULL) { + return (DDI_FAILURE); + } + + switch (cmd) { + case DDI_DETACH: + break; + + case DDI_SUSPEND: + return (DDI_SUCCESS); + + default: + return (DDI_FAILURE); + } + + ddi_remove_minor_node(dip, NULL); + + /* Free any memory on list */ + while ((mnode = avl_first(&state->xs_mlist.ml_avl)) != NULL) { + mp = mnode->mn_home; + xsvc_mem_free(state, mp); + } + + /* remove list */ + avl_destroy(&state->xs_mlist.ml_avl); + mutex_destroy(&state->xs_mlist.ml_mutex); + + mutex_destroy(&state->xs_mutex); + (void) ddi_soft_state_free(xsvc_statep, state->xs_instance); + return (DDI_SUCCESS); +} + +/* + * xsvc_getinfo() + * + */ +/*ARGSUSED*/ +static int +xsvc_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) +{ + xsvc_state_t *state; + int instance; + dev_t dev; + int err; + + + dev = (dev_t)arg; + instance = getminor(dev); + + switch (cmd) { + case DDI_INFO_DEVT2DEVINFO: + state = ddi_get_soft_state(xsvc_statep, instance); + if (state == NULL) { + return (DDI_FAILURE); + } + *result = (void *)state->xs_dip; + err = DDI_SUCCESS; + break; + + case DDI_INFO_DEVT2INSTANCE: + *result = (void *)(uintptr_t)instance; + err = DDI_SUCCESS; + break; + + default: + err = DDI_FAILURE; + break; + } + + return (err); +} + + +/* + * xsvc_open() + * + */ +/*ARGSUSED*/ +static int +xsvc_open(dev_t *devp, int flag, int otyp, cred_t *cred) +{ + xsvc_state_t *state; + int instance; + + instance = getminor(*devp); + state = ddi_get_soft_state(xsvc_statep, instance); + if (state == NULL) { + return (ENXIO); + } + + return (0); +} + +/* + * xsvc_close() + * + */ +/*ARGSUSED*/ +static int +xsvc_close(dev_t devp, int flag, int otyp, cred_t *cred) +{ + return (0); +} + +/* + * xsvc_ioctl() + * + */ +/*ARGSUSED*/ +static int +xsvc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred, int *rval) +{ + xsvc_state_t *state; + int instance; + int err; + + + err = drv_priv(cred); + if (err != 0) { + return (EPERM); + } + instance = getminor(dev); + if (instance == -1) { + return (EBADF); + } + state = ddi_get_soft_state(xsvc_statep, instance); + if (state == NULL) { + return (EBADF); + } + + switch (cmd) { + case XSVC_ALLOC_MEM: + err = xsvc_ioctl_alloc_memory(state, (void *)arg, mode); + break; + + case XSVC_FREE_MEM: + err = xsvc_ioctl_free_memory(state, (void *)arg, mode); + break; + + case XSVC_FLUSH_MEM: + err = xsvc_ioctl_flush_memory(state, (void *)arg, mode); + break; + + default: + err = ENXIO; + } + + return (err); +} + +/* + * xsvc_ioctl_alloc_memory() + * + */ +static int +xsvc_ioctl_alloc_memory(xsvc_state_t *state, void *arg, int mode) +{ + xsvc_mem_req_32 params32; + xsvc_mloc_32 *usgl32; + xsvc_mem_req params; + xsvc_mloc_32 sgl32; + xsvc_mloc *usgl; + xsvc_mem_t *mp; + xsvc_mloc sgl; + uint64_t key; + size_t size; + int err; + int i; + + + /* Copy in the params, then get the size and key */ + if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { + err = ddi_copyin(arg, ¶ms32, sizeof (xsvc_mem_req_32), + mode); + if (err != 0) { + return (EFAULT); + } + + key = (uint64_t)params32.xsvc_mem_reqid; + size = P2ROUNDUP((size_t)params32.xsvc_mem_size, PAGESIZE); + } else { + err = ddi_copyin(arg, ¶ms, sizeof (xsvc_mem_req), mode); + if (err != 0) { + return (EFAULT); + } + key = (uint64_t)params.xsvc_mem_reqid; + size = P2ROUNDUP(params.xsvc_mem_size, PAGESIZE); + } + + /* + * make sure this doesn't put us over the maximum allowed to be + * allocated + */ + mutex_enter(&state->xs_mutex); + if ((state->xs_currently_alloced + size) > xsvc_max_memory) { + mutex_exit(&state->xs_mutex); + return (EAGAIN); + } + state->xs_currently_alloced += size; + mutex_exit(&state->xs_mutex); + + /* get state to track this memory */ + err = xsvc_mem_alloc(state, key, &mp); + if (err != 0) { + return (err); + } + mp->xm_size = size; + + /* allocate and bind the memory */ + mp->xm_dma_attr.dma_attr_version = DMA_ATTR_V0; + mp->xm_dma_attr.dma_attr_count_max = (uint64_t)0xFFFFFFFF; + mp->xm_dma_attr.dma_attr_burstsizes = 1; + mp->xm_dma_attr.dma_attr_minxfer = 1; + mp->xm_dma_attr.dma_attr_maxxfer = (uint64_t)0xFFFFFFFF; + mp->xm_dma_attr.dma_attr_seg = (uint64_t)0xFFFFFFFF; + mp->xm_dma_attr.dma_attr_granular = 1; + mp->xm_dma_attr.dma_attr_flags = 0; + + /* Finish converting params */ + if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { + mp->xm_dma_attr.dma_attr_addr_lo = params32.xsvc_mem_addr_lo; + mp->xm_dma_attr.dma_attr_addr_hi = params32.xsvc_mem_addr_hi; + mp->xm_dma_attr.dma_attr_sgllen = params32.xsvc_mem_sgllen; + usgl32 = (xsvc_mloc_32 *)(uintptr_t)params32.xsvc_sg_list; + mp->xm_dma_attr.dma_attr_align = P2ROUNDUP( + params32.xsvc_mem_align, PAGESIZE); + } else { + mp->xm_dma_attr.dma_attr_addr_lo = params.xsvc_mem_addr_lo; + mp->xm_dma_attr.dma_attr_addr_hi = params.xsvc_mem_addr_hi; + mp->xm_dma_attr.dma_attr_sgllen = params.xsvc_mem_sgllen; + usgl = (xsvc_mloc *)(uintptr_t)params.xsvc_sg_list; + mp->xm_dma_attr.dma_attr_align = P2ROUNDUP( + params.xsvc_mem_align, PAGESIZE); + } + + mp->xm_device_attr = xsvc_device_attr; + + err = ddi_dma_alloc_handle(state->xs_dip, &mp->xm_dma_attr, + DDI_DMA_SLEEP, NULL, &mp->xm_dma_handle); + if (err != DDI_SUCCESS) { + err = EINVAL; + goto allocfail_alloc_handle; + } + + /* don't sleep here so we don't get stuck in contig alloc */ + err = ddi_dma_mem_alloc(mp->xm_dma_handle, mp->xm_size, + &mp->xm_device_attr, DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, + &mp->xm_addr, &mp->xm_real_length, &mp->xm_mem_handle); + if (err != DDI_SUCCESS) { + err = EINVAL; + goto allocfail_alloc_mem; + } + + err = ddi_dma_addr_bind_handle(mp->xm_dma_handle, NULL, mp->xm_addr, + mp->xm_size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, + NULL, &mp->xm_cookie, &mp->xm_cookie_count); + if (err != DDI_DMA_MAPPED) { + err = EFAULT; + goto allocfail_bind; + } + + /* return sgl */ + for (i = 0; i < mp->xm_cookie_count; i++) { + if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { + sgl32.mloc_addr = mp->xm_cookie.dmac_laddress; + sgl32.mloc_size = mp->xm_cookie.dmac_size; + err = ddi_copyout(&sgl32, &usgl32[i], + sizeof (xsvc_mloc_32), mode); + if (err != 0) { + err = EFAULT; + goto allocfail_copyout; + } + } else { + sgl.mloc_addr = mp->xm_cookie.dmac_laddress; + sgl.mloc_size = mp->xm_cookie.dmac_size; + err = ddi_copyout(&sgl, &usgl[i], sizeof (xsvc_mloc), + mode); + if (err != 0) { + err = EFAULT; + goto allocfail_copyout; + } + } + ddi_dma_nextcookie(mp->xm_dma_handle, &mp->xm_cookie); + } + + /* set the last sgl entry to 0 to indicate cookie count */ + if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { + sgl32.mloc_addr = 0; + sgl32.mloc_size = 0; + err = ddi_copyout(&sgl32, &usgl32[i], sizeof (xsvc_mloc_32), + mode); + if (err != 0) { + err = EFAULT; + goto allocfail_copyout; + } + } else { + sgl.mloc_addr = 0; + sgl.mloc_size = 0; + err = ddi_copyout(&sgl, &usgl[i], sizeof (xsvc_mloc), mode); + if (err != 0) { + err = EFAULT; + goto allocfail_copyout; + } + } + + return (0); + +allocfail_copyout: + (void) ddi_dma_unbind_handle(mp->xm_dma_handle); +allocfail_bind: + ddi_dma_mem_free(&mp->xm_mem_handle); +allocfail_alloc_mem: + ddi_dma_free_handle(&mp->xm_dma_handle); +allocfail_alloc_handle: + mp->xm_dma_handle = NULL; + xsvc_mem_free(state, mp); + + mutex_enter(&state->xs_mutex); + state->xs_currently_alloced = state->xs_currently_alloced - size; + mutex_exit(&state->xs_mutex); + + return (err); +} + +/* + * xsvc_ioctl_flush_memory() + * + */ +static int +xsvc_ioctl_flush_memory(xsvc_state_t *state, void *arg, int mode) +{ + xsvc_mem_req_32 params32; + xsvc_mem_req params; + xsvc_mem_t *mp; + uint64_t key; + int err; + + + if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { + err = ddi_copyin(arg, ¶ms32, sizeof (xsvc_mem_req_32), + mode); + if (err != 0) { + return (EFAULT); + } + key = (uint64_t)params32.xsvc_mem_reqid; + } else { + err = ddi_copyin(arg, ¶ms, sizeof (xsvc_mem_req), mode); + if (err != 0) { + return (EFAULT); + } + key = (uint64_t)params.xsvc_mem_reqid; + } + + /* find the memory */ + mp = xsvc_mem_lookup(state, key); + if (mp == NULL) { + return (EINVAL); + } + + (void) ddi_dma_sync(mp->xm_dma_handle, 0, 0, DDI_DMA_SYNC_FORCPU); + + return (0); +} + + +/* + * xsvc_ioctl_free_memory() + * + */ +static int +xsvc_ioctl_free_memory(xsvc_state_t *state, void *arg, int mode) +{ + xsvc_mem_req_32 params32; + xsvc_mem_req params; + xsvc_mem_t *mp; + uint64_t key; + int err; + + + if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) { + err = ddi_copyin(arg, ¶ms32, sizeof (xsvc_mem_req_32), + mode); + if (err != 0) { + return (EFAULT); + } + key = (uint64_t)params32.xsvc_mem_reqid; + } else { + err = ddi_copyin(arg, ¶ms, sizeof (xsvc_mem_req), mode); + if (err != 0) { + return (EFAULT); + } + key = (uint64_t)params.xsvc_mem_reqid; + } + + /* find the memory */ + mp = xsvc_mem_lookup(state, key); + if (mp == NULL) { + return (EINVAL); + } + + xsvc_mem_free(state, mp); + + return (0); +} + +/* + * xsvc_mem_alloc() + * + */ +static int +xsvc_mem_alloc(xsvc_state_t *state, uint64_t key, xsvc_mem_t **mp) +{ + xsvc_mem_t *mem; + + mem = xsvc_mem_lookup(state, key); + if (mem != NULL) { + xsvc_mem_free(state, mem); + } + + *mp = kmem_alloc(sizeof (xsvc_mem_t), KM_SLEEP); + (*mp)->xm_mnode.mn_home = *mp; + (*mp)->xm_mnode.mn_key = key; + + mutex_enter(&state->xs_mlist.ml_mutex); + avl_add(&state->xs_mlist.ml_avl, &(*mp)->xm_mnode); + mutex_exit(&state->xs_mlist.ml_mutex); + + return (0); +} + +/* + * xsvc_mem_free() + * + */ +static void +xsvc_mem_free(xsvc_state_t *state, xsvc_mem_t *mp) +{ + if (mp->xm_dma_handle != NULL) { + (void) ddi_dma_unbind_handle(mp->xm_dma_handle); + ddi_dma_mem_free(&mp->xm_mem_handle); + ddi_dma_free_handle(&mp->xm_dma_handle); + + mutex_enter(&state->xs_mutex); + state->xs_currently_alloced = state->xs_currently_alloced - + mp->xm_size; + mutex_exit(&state->xs_mutex); + } + + mutex_enter(&state->xs_mlist.ml_mutex); + avl_remove(&state->xs_mlist.ml_avl, &mp->xm_mnode); + mutex_exit(&state->xs_mlist.ml_mutex); + + kmem_free(mp, sizeof (*mp)); +} + +/* + * xsvc_mem_lookup() + * + */ +static xsvc_mem_t * +xsvc_mem_lookup(xsvc_state_t *state, uint64_t key) +{ + xsvc_mnode_t mnode; + xsvc_mnode_t *mnp; + avl_index_t where; + xsvc_mem_t *mp; + + mnode.mn_key = key; + mutex_enter(&state->xs_mlist.ml_mutex); + mnp = avl_find(&state->xs_mlist.ml_avl, &mnode, &where); + mutex_exit(&state->xs_mlist.ml_mutex); + + if (mnp != NULL) { + mp = mnp->mn_home; + } else { + mp = NULL; + } + + return (mp); +} + +/* + * xsvc_mnode_key_compare() + * + */ +static int +xsvc_mnode_key_compare(const void *q, const void *e) +{ + xsvc_mnode_t *n1; + xsvc_mnode_t *n2; + + n1 = (xsvc_mnode_t *)q; + n2 = (xsvc_mnode_t *)e; + + if (n1->mn_key < n2->mn_key) { + return (-1); + } else if (n1->mn_key > n2->mn_key) { + return (1); + } else { + return (0); + } +} + +/* + * xsvc_devmap() + * + */ +/*ARGSUSED*/ +static int +xsvc_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len, + size_t *maplen, uint_t model) +{ + ddi_umem_cookie_t cookie; + xsvc_state_t *state; + offset_t off_align; + size_t npages; + caddr_t kvai; + size_t psize; + int instance; + caddr_t kva; + pfn_t pfn; + int err; + int i; + + + instance = getminor(dev); + state = ddi_get_soft_state(xsvc_statep, instance); + if (state == NULL) { + return (ENXIO); + } + + /* + * On 64-bit kernels, if we have a 32-bit application doing a mmap(), + * smmap32 will sign extend the offset. We need to undo that since + * we are passed a physical address in off, not a offset. + */ +#if defined(__amd64) + if (((model & DDI_MODEL_MASK) == DDI_MODEL_ILP32) && + ((off & ~0xFFFFFFFFll) == ~0xFFFFFFFFll)) { + off = off & 0xFFFFFFFF; + } +#endif + + pfn = btop(off); + + /* always work with whole pages */ + off_align = P2ALIGN(off, PAGESIZE); + psize = P2ROUNDUP(off + len, PAGESIZE) - off_align; + + /* + * if this is memory we're trying to map into user space, we first + * need to map the PFNs into KVA, then build up a umem cookie, and + * finally do a umem_setup to map it in. + */ + if (pf_is_memory(pfn)) { + npages = btop(psize); + + kva = vmem_alloc(heap_arena, psize, VM_SLEEP); + if (kva == NULL) { + return (-1); + } + + kvai = kva; + for (i = 0; i < npages; i++) { + hat_devload(kas.a_hat, kvai, PAGESIZE, pfn, + PROT_READ | PROT_WRITE, HAT_LOAD_LOCK); + pfn++; + kvai = (caddr_t)((uintptr_t)kvai + PAGESIZE); + } + + err = xsvc_umem_cookie_alloc(kva, psize, KM_SLEEP, &cookie); + if (err != 0) { + goto devmapfail_cookie_alloc; + } + + if ((err = devmap_umem_setup(dhp, state->xs_dip, &xsvc_callbk, + cookie, 0, psize, PROT_ALL, 0, &xsvc_device_attr)) < 0) { + goto devmapfail_umem_setup; + } + *maplen = psize; + + /* Is this is not memory, go through devmem_setup */ + } else { + if ((err = devmap_devmem_setup(dhp, state->xs_dip, NULL, 0, + off_align, psize, PROT_ALL, 0, &xsvc_device_attr)) < 0) { + return (err); + } + *maplen = psize; + } + + return (0); + +devmapfail_umem_setup: + xsvc_umem_cookie_free(&cookie); + +devmapfail_cookie_alloc: + kvai = kva; + for (i = 0; i < npages; i++) { + hat_unload(kas.a_hat, kvai, PAGESIZE, + HAT_UNLOAD_UNLOCK); + kvai = (caddr_t)((uintptr_t)kvai + PAGESIZE); + } + vmem_free(heap_arena, kva, psize); + + return (err); +} + +/* + * xsvc_umem_cookie_alloc() + * + * allocate a umem cookie to be used in devmap_umem_setup using KVA already + * allocated. + */ +int +xsvc_umem_cookie_alloc(caddr_t kva, size_t size, int flags, + ddi_umem_cookie_t *cookiep) +{ + struct ddi_umem_cookie *umem_cookiep; + + umem_cookiep = kmem_zalloc(sizeof (struct ddi_umem_cookie), flags); + if (umem_cookiep == NULL) { + *cookiep = NULL; + return (-1); + } + + umem_cookiep->cvaddr = kva; + umem_cookiep->type = KMEM_NON_PAGEABLE; + umem_cookiep->size = size; + *cookiep = (ddi_umem_cookie_t *)umem_cookiep; + + return (0); +} + +/* + * xsvc_umem_cookie_free() + * + */ +static void +xsvc_umem_cookie_free(ddi_umem_cookie_t *cookiep) +{ + kmem_free(*cookiep, sizeof (struct ddi_umem_cookie)); + *cookiep = NULL; +} + +/* + * xsvc_devmap_unmap() + * + * This routine is only call if we were mapping in memory in xsvc_devmap(). + * i.e. we only pass in xsvc_callbk to devmap_umem_setup if pf_is_memory() + * was true. It would have been nice if devmap_callback_ctl had an args param. + * We wouldn't have had to look into the devmap_handle and into the umem + * cookie. + */ +/*ARGSUSED*/ +static void +xsvc_devmap_unmap(devmap_cookie_t dhc, void *pvtp, offset_t off, size_t len, + devmap_cookie_t new_dhp1, void **new_pvtp1, devmap_cookie_t new_dhp2, + void **new_pvtp2) +{ + struct ddi_umem_cookie *cp; + devmap_handle_t *dhp; + size_t npages; + caddr_t kvai; + caddr_t kva; + size_t size; + int i; + + + /* peek into the umem cookie to figure out what we need to free up */ + dhp = (devmap_handle_t *)dhc; + cp = (struct ddi_umem_cookie *)dhp->dh_cookie; + kva = cp->cvaddr; + size = cp->size; + + /* + * free up the umem cookie, then unmap all the pages what we mapped + * in during devmap, then free up the kva space. + */ + npages = btop(size); + xsvc_umem_cookie_free(&dhp->dh_cookie); + kvai = kva; + for (i = 0; i < npages; i++) { + hat_unload(kas.a_hat, kvai, PAGESIZE, HAT_UNLOAD_UNLOCK); + kvai = (caddr_t)((uintptr_t)kvai + PAGESIZE); + } + vmem_free(heap_arena, kva, size); +} diff --git a/usr/src/uts/i86pc/io/xsvc/xsvc.conf b/usr/src/uts/i86pc/io/xsvc/xsvc.conf new file mode 100644 index 0000000000..c41d589972 --- /dev/null +++ b/usr/src/uts/i86pc/io/xsvc/xsvc.conf @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# +#ident "%Z%%M% %I% %E% SMI" + +# Driver.conf file for xsvc Pseudo-driver. +# +# The reg property defines the physical range that the xsvc driver can +# map into user space. +# +name="xsvc" class="root" reg=0x0,0,0xffffffff; +maxallocmem=10240; diff --git a/usr/src/uts/i86pc/ml/amd64.il b/usr/src/uts/i86pc/ml/amd64.il new file mode 100644 index 0000000000..4405e60e0d --- /dev/null +++ b/usr/src/uts/i86pc/ml/amd64.il @@ -0,0 +1,183 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/ +/ Inline functions specific to the i86pc kernel running on bare metal. +/ + +/ +/ return value of cr3 register +/ + .inline getcr3,0 + movq %cr3, %rax + .end + +/ +/ reload cr3 register with its current value +/ + .inline reload_cr3,0 + movq %cr3, %rdi + movq %rdi, %cr3 + .end + +/ +/ return value of cr8 register +/ + .inline getcr8,0 + movq %cr8, %rax + .end + +/ +/ set cr8 register +/ + .inline setcr8,0 + movq %rdi, %cr8 + .end + +/ +/ enable interrupts +/ + .inline sti,0 + sti + .end + +/ +/ disable interrupts +/ + .inline cli,0 + cli + .end + +/ +/ disable interrupts and return value describing if interrupts were enabled +/ + .inline clear_int_flag,0 + pushfq + cli + popq %rax + .end + + .inline intr_clear,0 + pushfq + cli + popq %rax + .end + +/ +/ return the value of the flags register +/ + .inline getflags,0 + pushfq + popq %rax + .end + +/ +/ restore interrupt enable flag to value returned from 'clear_int_flag' above +/ + .inline restore_int_flag,4 + pushq %rdi + popfq + .end + + .inline intr_restore,4 + pushq %rdi + popfq + .end + +/ +/ in and out +/ + .inline inb,4 + movq %rdi, %rdx + xorq %rax, %rax + inb (%dx) + .end + + .inline inw,4 + movq %rdi, %rdx + xorq %rax, %rax + inw (%dx) + .end + + .inline inl,4 + movq %rdi, %rdx + xorq %rax, %rax + inl (%dx) + .end + + .inline outb,8 + movq %rdi, %rdx + movq %rsi, %rax + outb (%dx) + .end + + .inline outw,8 + movq %rdi, %rdx + movq %rsi, %rax + outw (%dx) + .end + + .inline outl,8 + movq %rdi, %rdx + movq %rsi, %rax + outl (%dx) + .end + +/* + * Read Time Stamp Counter + * uint64_t tsc_read(); + * + * usage: + * uint64_t cycles = tsc_read(); + */ + .inline tsc_read, 0 + rdtsc / %edx:%eax = RDTSC + shlq $32, %rdx + orq %rdx, %rax + .end + +/* + * Call the halt instruction. This will put the CPU to sleep until + * it is again awoken via an interrupt. + * This function should be called with interrupts already disabled + * for the CPU. + * Note that "sti" will only enable interrupts at the end of the + * subsequent instruction...in this case: "hlt". + */ + .inline i86_halt,0 + sti + hlt + .end +/ +/ execute the bsrw instruction +/ + .inline bsrw_insn,4 + xorl %eax, %eax + bsrw %di, %ax + .end + diff --git a/usr/src/uts/i86pc/ml/bios_call_src.s b/usr/src/uts/i86pc/ml/bios_call_src.s new file mode 100644 index 0000000000..a587929066 --- /dev/null +++ b/usr/src/uts/i86pc/ml/bios_call_src.s @@ -0,0 +1,565 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(__lint) + +int silence_lint = 0; + +#else + +#include <sys/segments.h> +#include <sys/controlregs.h> + +/* + * Do a call into BIOS. This goes down to 16 bit real mode and back again. + */ + +/* + * instruction prefix to change operand size in instruction + */ +#define DATASZ .byte 0x66; + +#if defined(__amd64) +#define MOVCR(x, y) movq x,%rax; movq %rax, y +#define LOAD_XAX(sym) leaq sym, %rax +#elif defined(__i386) +#define MOVCR(x, y) movl x,%eax; movl %eax, y +#define LOAD_XAX(sym) leal sym, %eax +#endif + + .globl _start +_start: + +#if defined(__i386) + + /* + * Save caller registers + */ + movl %ebp, save_ebp + movl %esp, save_esp + movl %ebx, save_ebx + movl %esi, save_esi + movl %edi, save_edi + + /* get registers argument into esi */ + movl 8(%esp), %esi + + /* put interrupt number in %bl */ + movl 4(%esp), %ebx + + /* Switch to a low memory stack */ + movl $_start, %esp + + /* allocate space for args on stack */ + subl $18, %esp + movl %esp, %edi + +#elif defined(__amd64) + + /* + * Save caller registers + */ + movq %rbp, save_rbp + movq %rsp, save_rsp + movq %rbx, save_rbx + movq %rsi, save_rsi + movq %r12, save_r12 + movq %r13, save_r13 + movq %r14, save_r14 + movq %r15, save_r15 + + /* Switch to a low memory stack */ + movq $_start, %rsp + + /* put interrupt number in %bl */ + movq %rdi, %rbx + + /* allocate space for args on stack */ + subq $18, %rsp + movq %rsp, %rdi + +#endif + + /* copy args from high memory to stack in low memory */ + cld + movl $18, %ecx + rep + movsb + + /* + * Save system registers + */ + sidt save_idt + sgdt save_gdt + str save_tr + movw %cs, save_cs + movw %ds, save_ds + movw %ss, save_ss + movw %es, save_es + movw %fs, save_fs + movw %gs, save_gs + MOVCR( %cr4, save_cr4) + MOVCR( %cr3, save_cr3) + MOVCR( %cr0, save_cr0) + +#if defined(__amd64) + /* + * save/clear the extension parts of the fs/gs base registers and cr8 + */ + movl $MSR_AMD_FSBASE, %ecx + rdmsr + movl %eax, save_fsbase + movl %edx, save_fsbase + 4 + xorl %eax, %eax + xorl %edx, %edx + wrmsr + + movl $MSR_AMD_GSBASE, %ecx + rdmsr + movl %eax, save_gsbase + movl %edx, save_gsbase + 4 + xorl %eax, %eax + xorl %edx, %edx + wrmsr + + movl $MSR_AMD_KGSBASE, %ecx + rdmsr + movl %eax, save_kgsbase + movl %edx, save_kgsbase + 4 + xorl %eax, %eax + xorl %edx, %edx + wrmsr + + movq %cr8, %rax + movq %rax, save_cr8 +#endif + + /* + * set offsets in 16 bit ljmp instructions below + */ + LOAD_XAX(enter_real) + movw %ax, enter_real_ljmp + + LOAD_XAX(enter_protected) + movw %ax, enter_protected_ljmp + + LOAD_XAX(gdt_info) + movw %ax, gdt_info_load + + /* + * insert BIOS interrupt number into later instruction + */ + movb %bl, int_instr+1 + jmp 1f +1: + + /* + * zero out all the registers to make sure they're 16 bit clean + */ +#if defined(__amd64) + xorq %r8, %r8 + xorq %r9, %r9 + xorq %r10, %r10 + xorq %r11, %r11 + xorq %r12, %r12 + xorq %r13, %r13 + xorq %r14, %r14 + xorq %r15, %r15 +#endif + xorl %eax, %eax + xorl %ebx, %ebx + xorl %ecx, %ecx + xorl %edx, %edx + xorl %ebp, %ebp + xorl %esi, %esi + xorl %edi, %edi + + /* + * Load our own GDT/IDT + */ + lgdt gdt_info + lidt idt_info + +#if defined(__amd64) + /* + * Shut down 64 bit mode. First get into compatiblity mode. + */ + movq %rsp, %rax + pushq $B32DATA_SEL + pushq %rax + pushf + pushq $B32CODE_SEL + pushq $1f + iretq +1: + .code32 + + /* + * disable long mode by: + * - shutting down paging (bit 31 of cr0) + * - flushing the TLB + * - disabling LME (long made enable) in EFER (extended feature reg) + */ + movl %cr0, %eax + btcl $31, %eax /* disable paging */ + movl %eax, %cr0 + ljmp $B32CODE_SEL, $1f +1: + + xorl %eax, %eax + movl %eax, %cr3 /* flushes TLB */ + + movl $MSR_AMD_EFER, %ecx /* Extended Feature Enable */ + rdmsr + btcl $8, %eax /* bit 8 Long Mode Enable bit */ + wrmsr +#endif + + /* + * ok.. now enter 16 bit mode, so we can shut down protected mode + * + * We'll have to act like we're still in a 32 bit section. + * So the code from this point has DATASZ in front of it to get 32 bit + * operands. If DATASZ is missing the operands will be 16 bit. + * + * Now shut down paging and protected (ie. segmentation) modes. + */ + ljmp $B16CODE_SEL, $enter_16_bit +enter_16_bit: + + /* + * Make sure hidden parts of segment registers are 16 bit clean + */ + DATASZ movl $B16DATA_SEL, %eax + movw %ax, %ss + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + + + DATASZ movl $0x0, %eax /* put us in real mode */ + DATASZ movl %eax, %cr0 + .byte 0xea /* ljmp */ +enter_real_ljmp: + .value 0 /* addr (16 bit) */ + .value 0x0 /* value for %cs */ +enter_real: + + /* + * zero out the remaining segment registers + */ + DATASZ xorl %eax, %eax + movw %ax, %ss + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + + /* + * load the arguments to the BIOS call from the stack + */ + popl %eax /* really executes a 16 bit pop */ + popl %ebx + popl %ecx + popl %edx + popl %esi + popl %edi + popl %ebp + pop %es + pop %ds + + /* + * do the actual BIOS call + */ + sti +int_instr: + int $0x10 /* this int number is overwritten */ + cli /* ensure interrupts remain disabled */ + + /* + * save results of the BIOS call + */ + pushf + push %ds + push %es + pushl %ebp /* still executes as 16 bit */ + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + + /* + * Restore protected mode and 32 bit execution + */ + push $0 /* make sure %ds is zero before lgdt */ + pop %ds + .byte 0x0f, 0x01, 0x16 /* lgdt */ +gdt_info_load: + .value 0 /* temp GDT in currently addressible mem */ + + DATASZ movl $0x1, %eax + DATASZ movl %eax, %cr0 + + .byte 0xea /* ljmp */ +enter_protected_ljmp: + .value 0 /* addr (still in 16 bit) */ + .value B32CODE_SEL /* %cs value */ +enter_protected: + + /* + * We are now back in a 32 bit code section, fix data/stack segments + */ + .code32 + movw $B32DATA_SEL, %ax + movw %ax, %ds + movw %ax, %ss + + /* + * Re-enable paging. Note we only use 32 bit mov's to restore these + * control registers. That's OK as the upper 32 bits are always zero. + */ + movl save_cr4, %eax + movl %eax, %cr4 + movl save_cr3, %eax + movl %eax, %cr3 + +#if defined(__amd64) + /* + * re-enable long mode + */ + movl $MSR_AMD_EFER, %ecx + rdmsr + btsl $8, %eax + wrmsr +#endif + + movl save_cr0, %eax + movl %eax, %cr0 + jmp enter_paging +enter_paging: + + +#if defined(__amd64) + /* + * transition back to 64 bit mode + */ + pushl $B64CODE_SEL + pushl $longmode + lret +longmode: + .code64 +#endif + /* + * restore caller frame pointer and segment registers + */ + lgdt save_gdt + lidt save_idt + + /* + * Before loading the task register we need to reset the busy bit + * in its corresponding GDT selector. The busy bit is the 2nd bit in + * the 5th byte of the selector. + */ +#if defined(__i386) + movzwl save_tr, %eax + addl save_gdt+2, %eax + btcl $1, 5(%eax) +#elif defined(__amd64) + movzwq save_tr, %rax + addq save_gdt+2, %rax + btcl $1, 5(%rax) +#endif + ltr save_tr + movw save_ds, %ds + movw save_ss, %ss + movw save_es, %es + movw save_fs, %fs + movw save_gs, %gs + +#if defined(__i386) + pushl save_cs + pushl $.newcs + lret +#elif defined(__amd64) + pushq save_cs + pushq $.newcs + lretq +#endif +.newcs: + +#if defined(__amd64) + /* + * restore the hidden kernel segment base register values + */ + movl save_fsbase, %eax + movl save_fsbase + 4, %edx + movl $MSR_AMD_FSBASE, %ecx + wrmsr + + movl save_gsbase, %eax + movl save_gsbase + 4, %edx + movl $MSR_AMD_GSBASE, %ecx + wrmsr + + movl save_kgsbase, %eax + movl save_kgsbase + 4, %edx + movl $MSR_AMD_KGSBASE, %ecx + wrmsr + + movq save_cr8, %rax + cmpq $0, %rax + je 1f + movq %rax, %cr8 +1: +#endif + + /* + * copy results to caller's location, then restore remaining registers + */ +#if defined(__i386) + movl save_esp, %edi + movl 8(%edi), %edi + movl %esp, %esi + movl $18, %ecx + rep + movsb + movw 18(%esp), %ax + andl $0xffff, %eax + movl save_ebx, %ebx + movl save_esi, %esi + movl save_edi, %edi + movl save_esp, %esp + movl save_ebp, %ebp + movl save_esp, %esp + ret + +#elif defined(__amd64) + movq save_rsi, %rdi + movq %rsp, %rsi + movq $18, %rcx + rep + movsb + movw 18(%rsp), %ax + andq $0xffff, %rax + movq save_r12, %r12 + movq save_r13, %r13 + movq save_r14, %r14 + movq save_r15, %r15 + movq save_rbx, %rbx + movq save_rbp, %rbp + movq save_rsp, %rsp + ret + +#endif + + +/* + * Caller's registers to restore + */ + .align 4 +save_esi: + .long 0 +save_edi: + .long 0 +save_ebx: + .long 0 +save_ebp: + .long 0 +save_esp: + .long 0 + + .align 8 +#if defined(__amd64) +save_rsi: + .quad 0 +save_rbx: + .quad 0 +save_rbp: + .quad 0 +save_rsp: + .quad 0 +save_r12: + .quad 0 +save_r13: + .quad 0 +save_r14: + .quad 0 +save_r15: + .quad 0 +save_kgsbase: + .quad 0 +save_gsbase: + .quad 0 +save_fsbase: + .quad 0 +save_cr8: + .quad 0 +#endif /* __amd64 */ + +save_idt: + .quad 0 + .quad 0 + +save_gdt: + .quad 0 + .quad 0 + +save_cr0: + .quad 0 +save_cr3: + .quad 0 +save_cr4: + .quad 0 +save_cs: + .quad 0 +save_ss: + .value 0 +save_ds: + .value 0 +save_es: + .value 0 +save_fs: + .value 0 +save_gs: + .value 0 +save_tr: + .value 0 + +idt_info: + .value 0x3ff + .quad 0 + + +/* + * We need to trampoline thru a gdt we have in low memory. + */ +#include "../boot/boot_gdt.s" +#endif /* __lint */ diff --git a/usr/src/uts/i86pc/ml/genassym.c b/usr/src/uts/i86pc/ml/genassym.c index a346a8f59b..cda4acb3a3 100644 --- a/usr/src/uts/i86pc/ml/genassym.c +++ b/usr/src/uts/i86pc/ml/genassym.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -48,8 +48,11 @@ #include <sys/pic.h> #include <sys/pit.h> #include <sys/fp.h> +#include <sys/disp.h> #include <sys/archsystm.h> +#include <sys/x86_archext.h> #include <sys/sunddi.h> +#include <sys/mach_mmu.h> #undef exit /* unhide exit, see comment above */ extern void exit(int); @@ -111,9 +114,6 @@ main(int argc, char *argv[]) printf("#define\tFPU_EN 0x%x\n", FPU_EN); printf("#define\tFPU_VALID 0x%x\n", FPU_VALID); - printf("#define\tELF_NOTE_PAGESIZE_HINT 0x%x\n", - ELF_NOTE_PAGESIZE_HINT); - printf("#define\tFP_NO 0x%x\n", FP_NO); printf("#define\tFP_SW 0x%x\n", FP_SW); printf("#define\tFP_HW 0x%x\n", FP_HW); @@ -162,15 +162,8 @@ main(int argc, char *argv[]) printf("#define\tDDI_DEV_AUTOINCR 0x%x\n", DDI_DEV_AUTOINCR); printf("#define\tMMU_STD_PAGESIZE 0x%x\n", (uint_t)MMU_STD_PAGESIZE); - printf("#define\tMMU_STD_PAGESHIFT 0x%x\n", (uint_t)MMU_STD_PAGESHIFT); printf("#define\tMMU_STD_PAGEMASK 0x%x\n", (uint_t)MMU_STD_PAGEMASK); - printf("#define\tMMU_L2_MASK 0x%x\n", (uint_t)(NPTEPERPT - 1)); - printf("#define\tNPTESHIFT 0x%x\n", (uint_t)NPTESHIFT); - printf("#define\tFOURMB_PAGEOFFSET 0x%x\n", (uint_t)FOURMB_PAGEOFFSET); - printf("#define\tFOURMB_PAGESIZE 0x%x\n", (uint_t)FOURMB_PAGESIZE); - printf("#define\tPTE_LARGEPAGE 0x%x\n", (uint_t)PTE_LARGEPAGE); - printf("#define\tPTE_VALID 0x%x\n", (uint_t)PTE_VALID); - printf("#define\tPTE_SRWX 0x%x\n", (uint_t)PTE_SRWX); + printf("#define\tFOUR_MEG 0x%x\n", (uint_t)FOUR_MEG); printf("#define\tTRAPTR_NENT 0x%x\n", TRAPTR_NENT); @@ -182,5 +175,7 @@ main(int argc, char *argv[]) printf("#define\tMODS_WEAK 0x%x\n", MODS_WEAK); printf("#define\tMODS_INSTALLED 0x%x\n", MODS_INSTALLED); + printf("#define\tKPREEMPT_SYNC 0x%x\n", KPREEMPT_SYNC); + return (0); } diff --git a/usr/src/uts/i86pc/ml/ia32.il b/usr/src/uts/i86pc/ml/ia32.il new file mode 100644 index 0000000000..4a7be58bd7 --- /dev/null +++ b/usr/src/uts/i86pc/ml/ia32.il @@ -0,0 +1,187 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/ +/ Inline functions specific to the i86pc kernel running on bare metal. +/ + +/ +/ return value of cr3 register +/ + .inline getcr3,0 + movl %cr3, %eax + .end + +/ +/ reload cr3 register with its current value +/ + .inline reload_cr3,0 + movl %cr3, %eax + movl %eax, %cr3 + .end + +/* + * Put a new value into cr3 (page table base register + * void setcr3(void *value) + */ + .inline setcr3,4 + movl (%esp), %eax + movl %eax, %cr3 + .end + +/ +/ enable interrupts +/ + .inline sti,0 + sti + .end + +/ +/ disable interrupts +/ + .inline cli,0 + cli + .end + +/ +/ disable interrupts and return value describing if interrupts were enabled +/ + .inline clear_int_flag,0 + pushfl + cli + popl %eax + .end + + .inline intr_clear,0 + pushfl + cli + popl %eax + .end + +/ +/ return the flags register +/ + .inline getflags,0 + pushfl + popl %eax + .end + +/ +/ restore interrupt enable flag to value returned from 'clear_int_flag' above +/ + .inline restore_int_flag,4 + pushl (%esp) + popfl + .end + + .inline intr_restore,4 + pushl (%esp) + popfl + .end + +/ +/ in and out +/ + .inline inb,4 + movl (%esp), %edx + xorl %eax, %eax + inb (%dx) + .end + + .inline inw,4 + movl (%esp), %edx + xorl %eax, %eax + inw (%dx) + .end + + .inline inl,4 + movl (%esp), %edx + xorl %eax, %eax + inl (%dx) + .end + + .inline outb,8 + movl (%esp), %edx + movl 4(%esp), %eax + outb (%dx) + .end + + .inline outw,8 + movl (%esp), %edx + movl 4(%esp), %eax + outw (%dx) + .end + + .inline outl,8 + movl (%esp), %edx + movl 4(%esp), %eax + outl (%dx) + .end + +/* + * Invalidate TLB translation to 1 page. + * void mmu_tlbflush_entry(void *addr) + */ + .inline mmu_tlbflush_entry,4 + movl (%esp), %eax + invlpg (%eax) + .end + +/* + * Read Time Stamp Counter + * uint64_t tsc_read(); + * + * usage: + * uint64_t cycles = tsc_read(); + */ + .inline tsc_read, 0 + rdtsc / %edx:%eax = RDTSC + .end + +/* + * Call the halt instruction. This will put the CPU to sleep until + * it is again awoken via an interrupt. + * This function should be called with interrupts already disabled + * for the CPU. + * Note that "sti" will only enable interrupts at the end of the + * subsequent instruction...in this case: "hlt". + */ + .inline i86_halt,0 + sti + hlt + .end + +/* + * execute the bsrw instruction + * int bsrw_insn(uint16_t) + */ + .inline bsrw_insn,4 + xorl %eax, %eax + movw (%esp), %cx + bsrw %cx, %ax + .end diff --git a/usr/src/uts/i86pc/ml/interrupt.s b/usr/src/uts/i86pc/ml/interrupt.s index 69e990674d..da1348ecbd 100644 --- a/usr/src/uts/i86pc/ml/interrupt.s +++ b/usr/src/uts/i86pc/ml/interrupt.s @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -55,9 +55,6 @@ #include <sys/panic.h> #include "assym.h" -_ftrace_intr_thread_fmt: - .string "intr_thread(): regs=0x%lx, int=0x%x, pil=0x%x" - #endif /* lint */ #if defined(__i386) @@ -79,23 +76,8 @@ patch_tsc(void) */ ENTRY_NP(patch_tsc) movw _rdtsc_insn, %cx - movw %cx, _tsc_patch1 - movw %cx, _tsc_patch2 - movw %cx, _tsc_patch3 - movw %cx, _tsc_patch4 - movw %cx, _tsc_patch5 - movw %cx, _tsc_patch6 - movw %cx, _tsc_patch7 - movw %cx, _tsc_patch8 - movw %cx, _tsc_patch9 - movw %cx, _tsc_patch10 - movw %cx, _tsc_patch11 - movw %cx, _tsc_patch12 - movw %cx, _tsc_patch13 - movw %cx, _tsc_patch14 movw %cx, _tsc_patch15 movw %cx, _tsc_patch16 - movw %cx, _tsc_patch17 ret _rdtsc_insn: rdtsc @@ -119,16 +101,12 @@ _interrupt(void) /* * Common register usage: * - * %rbx cpu pointer - * %r12 trap trace pointer -and- stash of - * vec across intr_thread dispatch. - * %r13d ipl of isr - * %r14d old ipl (ipl level we entered on) - * %r15 interrupted thread stack pointer + * %r12 trap trace pointer */ ENTRY_NP2(cmnint, _interrupt) INTR_PUSH + INTGATE_INIT_KERNEL_FLAGS /* (set kernel rflags values) */ /* * At the end of TRACE_PTR %r12 points to the current TRAPTRACE entry @@ -138,404 +116,36 @@ _interrupt(void) TRACE_REGS(%r12, %rsp, %rax, %rbx) /* Uses label 9 */ TRACE_STAMP(%r12) /* Clobbers %eax, %edx, uses 9 */ - DISABLE_INTR_FLAGS /* (and set kernel flag values) */ - movq %rsp, %rbp TRACE_STACK(%r12) +#ifdef TRAPTRACE LOADCPU(%rbx) /* &cpu */ - leaq REGOFF_TRAPNO(%rbp), %rsi /* &vector */ movl CPU_PRI(%rbx), %r14d /* old ipl */ - movl CPU_SOFTINFO(%rbx), %edx - -#ifdef TRAPTRACE movl $255, TTR_IPL(%r12) movl %r14d, %edi movb %dil, TTR_PRI(%r12) movl CPU_BASE_SPL(%rbx), %edi movb %dil, TTR_SPL(%r12) movb $255, TTR_VECTOR(%r12) + movq %r12, %rsi /* pass traptrace record pointer */ #endif - /* - * Check to see if the trap number is T_SOFTINT; if it is, - * jump straight to dosoftint now. - */ - cmpq $T_SOFTINT, (%rsi) - je dosoftint - - /* - * Raise the interrupt priority level, returns newpil. - * (The vector address is in %rsi so setlvl can update it.) - */ - movl %r14d, %edi /* old ipl */ - /* &vector */ - call *setlvl(%rip) - -#ifdef TRAPTRACE - movb %al, TTR_IPL(%r12) -#endif - /* - * check for spurious interrupt - */ - cmpl $-1, %eax - je _sys_rtt - -#ifdef TRAPTRACE - movl %r14d, %edx - movb %dl, TTR_PRI(%r12) - movl CPU_BASE_SPL(%rbx), %edx - movb %dl, TTR_SPL(%r12) -#endif - movl %eax, CPU_PRI(%rbx) /* update ipl */ - -#ifdef TRAPTRACE - movl REGOFF_TRAPNO(%rbp), %edx - movb %dl, TTR_VECTOR(%r12) -#endif - movl %eax, %r13d /* ipl of isr */ - - /* - * At this point we can take one of two paths. - * If the new level is at or below lock level, we will - * run this interrupt in a separate thread. - */ - cmpl $LOCK_LEVEL, %eax - jbe intr_thread - - movq %rbx, %rdi /* &cpu */ - movl %r13d, %esi /* ipl */ - movl %r14d, %edx /* old ipl */ - movq %rbp, %rcx /* ®s */ - call hilevel_intr_prolog - orl %eax, %eax /* zero if need to switch stack */ - jnz 1f - - /* - * Save the thread stack and get on the cpu's interrupt stack - */ - movq %rsp, %r15 - movq CPU_INTR_STACK(%rbx), %rsp -1: - - sti - - /* - * Walk the list of handlers for this vector, calling - * them as we go until no more interrupts are claimed. - */ - movl REGOFF_TRAPNO(%rbp), %edi - call av_dispatch_autovect - - cli - - movq %rbx, %rdi /* &cpu */ - movl %r13d, %esi /* ipl */ - movl %r14d, %edx /* oldipl */ - movl REGOFF_TRAPNO(%rbp), %ecx /* vec */ - call hilevel_intr_epilog - orl %eax, %eax /* zero if need to switch stack */ - jnz 2f - movq %r15, %rsp -2: /* - * Check for, and execute, softints before we iret. - * - * (dosoftint expects oldipl in %r14d (which is where it is) - * the cpu pointer in %rbx (which is where it is) and the - * softinfo in %edx (which is where we'll put it right now)) - */ - movl CPU_SOFTINFO(%rbx), %edx - orl %edx, %edx - jz _sys_rtt - jmp dosoftint + movq %rsp, %rdi /* pass struct regs pointer */ + call do_interrupt + jmp _sys_rtt /*NOTREACHED*/ SET_SIZE(cmnint) SET_SIZE(_interrupt) -/* - * Handle an interrupt in a new thread - * - * As we branch here, interrupts are still masked, - * %rbx still contains the cpu pointer, - * %r14d contains the old ipl that we came in on, and - * %eax contains the new ipl that we got from the setlvl routine - */ - - ENTRY_NP(intr_thread) - - movq %rbx, %rdi /* &cpu */ - movq %rbp, %rsi /* ®s = stack pointer for _sys_rtt */ - movl REGOFF_TRAPNO(%rbp), %r12d /* stash the vec */ - movl %eax, %edx /* new pil from setlvlx() */ - call intr_thread_prolog - movq %rsp, %r15 - movq %rax, %rsp /* t_stk from interrupt thread */ - movq %rsp, %rbp - - sti - - testl $FTRACE_ENABLED, CPU_FTRACE_STATE(%rbx) - jz 1f - /* - * ftracing support. do we need this on x86? - */ - leaq _ftrace_intr_thread_fmt(%rip), %rdi - movq %rbp, %rsi /* ®s */ - movl %r12d, %edx /* vec */ - movq CPU_THREAD(%rbx), %r11 /* (the interrupt thread) */ - movzbl T_PIL(%r11), %ecx /* newipl */ - call ftrace_3_notick -1: - movl %r12d, %edi /* vec */ - call av_dispatch_autovect - - cli - - movq %rbx, %rdi /* &cpu */ - movl %r12d, %esi /* vec */ - movl %r14d, %edx /* oldpil */ - call intr_thread_epilog - /* - * If we return from here (we might not if the interrupted thread - * has exited or blocked, in which case we'll have quietly swtch()ed - * away) then we need to switch back to our old %rsp - */ - movq %r15, %rsp - movq %rsp, %rbp - /* - * Check for, and execute, softints before we iret. - * - * (dosoftint expects oldpil in %r14d, the cpu pointer in %rbx and - * the mcpu_softinfo.st_pending field in %edx. - */ - movl CPU_SOFTINFO(%rbx), %edx - orl %edx, %edx - jz _sys_rtt - /*FALLTHROUGH*/ - -/* - * Process soft interrupts. - * Interrupts are masked, and we have a minimal frame on the stack. - * %edx should contain the mcpu_softinfo.st_pending field - */ - - ALTENTRY(dosoftint) - - movq %rbx, %rdi /* &cpu */ - movq %rbp, %rsi /* ®s = stack pointer for _sys_rtt */ - /* cpu->cpu_m.mcpu_softinfo.st_pending */ - movl %r14d, %ecx /* oldipl */ - call dosoftint_prolog - /* - * dosoftint_prolog() usually returns a stack pointer for the - * interrupt thread that we must switch to. However, if the - * returned stack pointer is NULL, then the software interrupt was - * too low in priority to run now; we'll catch it another time. - */ - orq %rax, %rax - jz _sys_rtt - movq %rsp, %r15 - movq %rax, %rsp /* t_stk from interrupt thread */ - movq %rsp, %rbp - - sti - - /* - * Enabling interrupts (above) could raise the current ipl - * and base spl. But, we continue processing the current soft - * interrupt and we will check the base spl next time around - * so that blocked interrupt threads get a chance to run. - */ - movq CPU_THREAD(%rbx), %r11 /* now an interrupt thread */ - movzbl T_PIL(%r11), %edi - call av_dispatch_softvect - - cli - - movq %rbx, %rdi /* &cpu */ - movl %r14d, %esi /* oldpil */ - call dosoftint_epilog - movq %r15, %rsp /* back on old stack pointer */ - movq %rsp, %rbp - movl CPU_SOFTINFO(%rbx), %edx - orl %edx, %edx - jz _sys_rtt - jmp dosoftint - - SET_SIZE(dosoftint) - SET_SIZE(intr_thread) - #elif defined(__i386) -/* - * One day, this should just invoke the C routines that know how to - * do all the interrupt bookkeeping. In the meantime, try - * and make the assembler a little more comprehensible. - */ - -#define INC64(basereg, offset) \ - addl $1, offset(basereg); \ - adcl $0, offset + 4(basereg) - -#define TSC_CLR(basereg, offset) \ - movl $0, offset(basereg); \ - movl $0, offset + 4(basereg) - -/* - * The following macros assume the time value is in %edx:%eax - * e.g. from a rdtsc instruction. - */ -#define TSC_STORE(reg, offset) \ - movl %eax, offset(reg); \ - movl %edx, offset + 4(reg) - -#define TSC_LOAD(reg, offset) \ - movl offset(reg), %eax; \ - movl offset + 4(reg), %edx - -#define TSC_ADD_TO(reg, offset) \ - addl %eax, offset(reg); \ - adcl %edx, offset + 4(reg) - -#define TSC_SUB_FROM(reg, offset) \ - subl offset(reg), %eax; \ - sbbl offset + 4(reg), %edx /* interval in edx:eax */ - -/* - * basereg - pointer to cpu struct - * pilreg - pil or converted pil (pil - (LOCK_LEVEL + 1)) - * - * Returns (base + pil * 8) in pilreg - */ -#define PILBASE(basereg, pilreg) \ - lea (basereg, pilreg, 8), pilreg - -/* - * Returns (base + (pil - (LOCK_LEVEL + 1)) * 8) in pilreg - */ -#define HIGHPILBASE(basereg, pilreg) \ - subl $LOCK_LEVEL + 1, pilreg; \ - PILBASE(basereg, pilreg) - -/* - * Returns (base + pil * 16) in pilreg - */ -#define PILBASE_INTRSTAT(basereg, pilreg) \ - shl $4, pilreg; \ - addl basereg, pilreg; - -/* - * Returns (cpu + cpu_mstate * 8) in tgt - */ -#define INTRACCTBASE(cpureg, tgtreg) \ - movzwl CPU_MSTATE(cpureg), tgtreg; \ - lea (cpureg, tgtreg, 8), tgtreg - -/* - * cpu_stats.sys.intr[PIL]++ - */ -#define INC_CPU_STATS_INTR(pilreg, tmpreg, tmpreg_32, basereg) \ - movl pilreg, tmpreg_32; \ - PILBASE(basereg, tmpreg); \ - INC64(tmpreg, _CONST(CPU_STATS_SYS_INTR - 8)) - -/* - * Unlink thread from CPU's list - */ -#define UNLINK_INTR_THREAD(cpureg, ithread, tmpreg) \ - mov CPU_INTR_THREAD(cpureg), ithread; \ - mov T_LINK(ithread), tmpreg; \ - mov tmpreg, CPU_INTR_THREAD(cpureg) - -/* - * Link a thread into CPU's list - */ -#define LINK_INTR_THREAD(cpureg, ithread, tmpreg) \ - mov CPU_INTR_THREAD(cpureg), tmpreg; \ - mov tmpreg, T_LINK(ithread); \ - mov ithread, CPU_INTR_THREAD(cpureg) - -#if defined(DEBUG) - -/* - * Do not call panic, if panic is already in progress. - */ -#define __PANIC(msg, label) \ - cmpl $0, panic_quiesce; \ - jne label; \ - pushl $msg; \ - call panic - -#define __CMP64_JNE(basereg, offset, label) \ - cmpl $0, offset(basereg); \ - jne label; \ - cmpl $0, offset + 4(basereg); \ - jne label - -/* - * ASSERT(!(CPU->cpu_intr_actv & (1 << PIL))) - */ -#define ASSERT_NOT_CPU_INTR_ACTV(pilreg, basereg, msg) \ - btl pilreg, CPU_INTR_ACTV(basereg); \ - jnc 4f; \ - __PANIC(msg, 4f); \ -4: - -/* - * ASSERT(CPU->cpu_intr_actv & (1 << PIL)) - */ -#define ASSERT_CPU_INTR_ACTV(pilreg, basereg, msg) \ - btl pilreg, CPU_INTR_ACTV(basereg); \ - jc 5f; \ - __PANIC(msg, 5f); \ -5: - -/* - * ASSERT(CPU->cpu_pil_high_start != 0) - */ -#define ASSERT_CPU_PIL_HIGH_START_NZ(basereg) \ - __CMP64_JNE(basereg, CPU_PIL_HIGH_START, 6f); \ - __PANIC(_interrupt_timestamp_zero, 6f); \ -6: - -/* - * ASSERT(t->t_intr_start != 0) - */ -#define ASSERT_T_INTR_START_NZ(basereg) \ - __CMP64_JNE(basereg, T_INTR_START, 7f); \ - __PANIC(_intr_thread_t_intr_start_zero, 7f); \ -7: - -_interrupt_actv_bit_set: - .string "_interrupt(): cpu_intr_actv bit already set for PIL" -_interrupt_actv_bit_not_set: - .string "_interrupt(): cpu_intr_actv bit not set for PIL" -_interrupt_timestamp_zero: - .string "_interrupt(): timestamp zero upon handler return" -_intr_thread_actv_bit_not_set: - .string "intr_thread(): cpu_intr_actv bit not set for PIL" -_intr_thread_t_intr_start_zero: - .string "intr_thread(): t_intr_start zero upon handler return" -_dosoftint_actv_bit_set: - .string "dosoftint(): cpu_intr_actv bit already set for PIL" -_dosoftint_actv_bit_not_set: - .string "dosoftint(): cpu_intr_actv bit not set for PIL" - - DGDEF(intr_thread_cnt) - .4byte 0 - -#else -#define ASSERT_NOT_CPU_INTR_ACTV(pilreg, basereg, msg) -#define ASSERT_CPU_INTR_ACTV(pilreg, basereg, msg) -#define ASSERT_CPU_PIL_HIGH_START_NZ(basereg) -#define ASSERT_T_INTR_START_NZ(basereg) -#endif - ENTRY_NP2(cmnint, _interrupt) INTR_PUSH + INTGATE_INIT_KERNEL_FLAGS /* * At the end of TRACE_PTR %esi points to the current TRAPTRACE entry @@ -546,298 +156,15 @@ _dosoftint_actv_bit_not_set: TRACE_STAMP(%esi) /* Clobbers %eax, %edx, uses 9 */ movl %esp, %ebp - DISABLE_INTR_FLAGS - LOADCPU(%ebx) /* get pointer to CPU struct. Avoid gs refs */ - leal REGOFF_TRAPNO(%ebp), %ecx /* get address of vector */ - movl CPU_PRI(%ebx), %edi /* get ipl */ - movl CPU_SOFTINFO(%ebx), %edx - / - / Check to see if the trap number is T_SOFTINT; if it is, we'll - / jump straight to dosoftint now. - / - cmpl $T_SOFTINT, (%ecx) - je dosoftint + TRACE_STACK(%esi) - / raise interrupt priority level - / oldipl is in %edi, vectorp is in %ecx - / newipl is returned in %eax - pushl %ecx - pushl %edi - call *setlvl - popl %edi /* save oldpil in %edi */ - popl %ecx + pushl %esi /* pass traptrace record pointer */ + pushl %ebp /* pass struct regs pointer */ + call do_interrupt /* interrupt service routine */ + addl $8, %esp /* pop args off of stack */ -#ifdef TRAPTRACE - movb %al, TTR_IPL(%esi) -#endif - - / check for spurious interrupt - cmp $-1, %eax - je _sys_rtt - -#ifdef TRAPTRACE - movl CPU_PRI(%ebx), %edx - movb %dl, TTR_PRI(%esi) - movl CPU_BASE_SPL(%ebx), %edx - movb %dl, TTR_SPL(%esi) -#endif - - movl %eax, CPU_PRI(%ebx) /* update ipl */ - movl REGOFF_TRAPNO(%ebp), %ecx /* reload the interrupt vector */ - -#ifdef TRAPTRACE - movb %cl, TTR_VECTOR(%esi) -#endif - - / At this point we can take one of two paths. If the new priority - / level is less than or equal to LOCK LEVEL then we jump to code that - / will run this interrupt as a separate thread. Otherwise the - / interrupt is NOT run as a separate thread. - - / %edi - old priority level - / %ebp - pointer to REGS - / %ecx - translated vector - / %eax - ipl of isr - / %ebx - cpu pointer - - cmpl $LOCK_LEVEL, %eax /* compare to highest thread level */ - jbe intr_thread /* process as a separate thread */ - - cmpl $CBE_HIGH_PIL, %eax /* Is this a CY_HIGH_LEVEL interrupt? */ - jne 2f - - movl REGOFF_PC(%ebp), %esi - movl %edi, CPU_PROFILE_PIL(%ebx) /* record interrupted PIL */ - testw $CPL_MASK, REGOFF_CS(%ebp) /* trap from supervisor mode? */ - jz 1f - movl %esi, CPU_PROFILE_UPC(%ebx) /* record user PC */ - movl $0, CPU_PROFILE_PC(%ebx) /* zero kernel PC */ - jmp 2f - -1: - movl %esi, CPU_PROFILE_PC(%ebx) /* record kernel PC */ - movl $0, CPU_PROFILE_UPC(%ebx) /* zero user PC */ - -2: - pushl %ecx /* vec */ - pushl %eax /* newpil */ - - / - / See if we are interrupting another high-level interrupt. - / - movl CPU_INTR_ACTV(%ebx), %eax - andl $CPU_INTR_ACTV_HIGH_LEVEL_MASK, %eax - jz 0f - / - / We have interrupted another high-level interrupt. - / Load starting timestamp, compute interval, update cumulative counter. - / - bsrl %eax, %ecx /* find PIL of interrupted handler */ - movl %ecx, %esi /* save PIL for later */ - HIGHPILBASE(%ebx, %ecx) -_tsc_patch1: - nop; nop /* patched to rdtsc if available */ - TSC_SUB_FROM(%ecx, CPU_PIL_HIGH_START) - - PILBASE_INTRSTAT(%ebx, %esi) - TSC_ADD_TO(%esi, CPU_INTRSTAT) - INTRACCTBASE(%ebx, %ecx) - TSC_ADD_TO(%ecx, CPU_INTRACCT) /* cpu_intracct[cpu_mstate] += tsc */ - / - / Another high-level interrupt is active below this one, so - / there is no need to check for an interrupt thread. That will be - / done by the lowest priority high-level interrupt active. - / - jmp 1f -0: - / - / See if we are interrupting a low-level interrupt thread. - / - movl CPU_THREAD(%ebx), %esi - testw $T_INTR_THREAD, T_FLAGS(%esi) - jz 1f - / - / We have interrupted an interrupt thread. Account for its time slice - / only if its time stamp is non-zero. - / - cmpl $0, T_INTR_START+4(%esi) - jne 0f - cmpl $0, T_INTR_START(%esi) - je 1f -0: - movzbl T_PIL(%esi), %ecx /* %ecx has PIL of interrupted handler */ - PILBASE_INTRSTAT(%ebx, %ecx) -_tsc_patch2: - nop; nop /* patched to rdtsc if available */ - TSC_SUB_FROM(%esi, T_INTR_START) - TSC_CLR(%esi, T_INTR_START) - TSC_ADD_TO(%ecx, CPU_INTRSTAT) - INTRACCTBASE(%ebx, %ecx) - TSC_ADD_TO(%ecx, CPU_INTRACCT) /* cpu_intracct[cpu_mstate] += tsc */ -1: - / Store starting timestamp in CPU structure for this PIL. - popl %ecx /* restore new PIL */ - pushl %ecx - HIGHPILBASE(%ebx, %ecx) -_tsc_patch3: - nop; nop /* patched to rdtsc if available */ - TSC_STORE(%ecx, CPU_PIL_HIGH_START) - - popl %eax /* restore new pil */ - popl %ecx /* vec */ - / - / Set bit for this PIL in CPU's interrupt active bitmask. - / - - ASSERT_NOT_CPU_INTR_ACTV(%eax, %ebx, _interrupt_actv_bit_set) - - / Save old CPU_INTR_ACTV - movl CPU_INTR_ACTV(%ebx), %esi - - cmpl $15, %eax - jne 0f - / PIL-15 interrupt. Increment nest-count in upper 16 bits of intr_actv - incw CPU_INTR_ACTV_REF(%ebx) /* increment ref count */ -0: - btsl %eax, CPU_INTR_ACTV(%ebx) - / - / Handle high-level nested interrupt on separate interrupt stack - / - testl $CPU_INTR_ACTV_HIGH_LEVEL_MASK, %esi - jnz onstack /* already on interrupt stack */ - movl %esp, %eax - movl CPU_INTR_STACK(%ebx), %esp /* get on interrupt stack */ - pushl %eax /* save the thread stack pointer */ -onstack: - movl $autovect, %esi /* get autovect structure before */ - /* sti to save on AGI later */ - sti /* enable interrupts */ - pushl %ecx /* save interrupt vector */ - / - / Get handler address - / -pre_loop1: - movl AVH_LINK(%esi, %ecx, 8), %esi - xorl %ebx, %ebx /* bh is no. of intpts in chain */ - /* bl is DDI_INTR_CLAIMED status of chain */ - testl %esi, %esi /* if pointer is null */ - jz .intr_ret /* then skip */ -loop1: - incb %bh - movl AV_VECTOR(%esi), %edx /* get the interrupt routine */ - testl %edx, %edx /* if func is null */ - jz .intr_ret /* then skip */ - pushl $0 - pushl AV_INTARG2(%esi) - pushl AV_INTARG1(%esi) - pushl AV_VECTOR(%esi) - pushl AV_DIP(%esi) - call __dtrace_probe_interrupt__start - pushl AV_INTARG2(%esi) /* get 2nd arg to interrupt routine */ - pushl AV_INTARG1(%esi) /* get first arg to interrupt routine */ - call *%edx /* call interrupt routine with arg */ - addl $8, %esp - movl %eax, 16(%esp) - call __dtrace_probe_interrupt__complete - addl $20, %esp - orb %al, %bl /* see if anyone claims intpt. */ - movl AV_LINK(%esi), %esi /* get next routine on list */ - testl %esi, %esi /* if pointer is non-null */ - jnz loop1 /* then continue */ - -.intr_ret: - cmpb $1, %bh /* if only 1 intpt in chain, it is OK */ - je .intr_ret1 - orb %bl, %bl /* If no one claims intpt, then it is OK */ - jz .intr_ret1 - movl (%esp), %ecx /* else restore intr vector */ - movl $autovect, %esi /* get autovect structure */ - jmp pre_loop1 /* and try again. */ - -.intr_ret1: - LOADCPU(%ebx) /* get pointer to cpu struct */ - - cli - movl CPU_PRI(%ebx), %esi - - / cpu_stats.sys.intr[PIL]++ - INC_CPU_STATS_INTR(%esi, %eax, %eax, %ebx) - - / - / Clear bit for this PIL in CPU's interrupt active bitmask. - / - - ASSERT_CPU_INTR_ACTV(%esi, %ebx, _interrupt_actv_bit_not_set) - - cmpl $15, %esi - jne 0f - / Only clear bit if reference count is now zero. - decw CPU_INTR_ACTV_REF(%ebx) - jnz 1f -0: - btrl %esi, CPU_INTR_ACTV(%ebx) -1: - / - / Take timestamp, compute interval, update cumulative counter. - / esi = PIL -_tsc_patch4: - nop; nop /* patched to rdtsc if available */ - movl %esi, %ecx /* save for later */ - HIGHPILBASE(%ebx, %esi) - - ASSERT_CPU_PIL_HIGH_START_NZ(%esi) - - TSC_SUB_FROM(%esi, CPU_PIL_HIGH_START) - - PILBASE_INTRSTAT(%ebx, %ecx) - TSC_ADD_TO(%ecx, CPU_INTRSTAT) - INTRACCTBASE(%ebx, %esi) - TSC_ADD_TO(%esi, CPU_INTRACCT) /* cpu_intracct[cpu_mstate] += tsc */ - / - / Check for lower-PIL nested high-level interrupt beneath current one - / If so, place a starting timestamp in its pil_high_start entry. - / - movl CPU_INTR_ACTV(%ebx), %eax - movl %eax, %esi - andl $CPU_INTR_ACTV_HIGH_LEVEL_MASK, %eax - jz 0f - bsrl %eax, %ecx /* find PIL of nested interrupt */ - HIGHPILBASE(%ebx, %ecx) -_tsc_patch5: - nop; nop /* patched to rdtsc if available */ - TSC_STORE(%ecx, CPU_PIL_HIGH_START) - / - / Another high-level interrupt is active below this one, so - / there is no need to check for an interrupt thread. That will be - / done by the lowest priority high-level interrupt active. - / - jmp 1f -0: - / Check to see if there is a low-level interrupt active. If so, - / place a starting timestamp in the thread structure. - movl CPU_THREAD(%ebx), %esi - testw $T_INTR_THREAD, T_FLAGS(%esi) - jz 1f -_tsc_patch6: - nop; nop /* patched to rdtsc if available */ - TSC_STORE(%esi, T_INTR_START) -1: - movl %edi, CPU_PRI(%ebx) - /* interrupt vector already on stack */ - pushl %edi /* old ipl */ - call *setlvlx - addl $8, %esp /* eax contains the current ipl */ - - movl CPU_INTR_ACTV(%ebx), %esi /* reset stack pointer if no more */ - shrl $LOCK_LEVEL + 1, %esi /* HI PRI intrs. */ - jnz .intr_ret2 - popl %esp /* restore the thread stack pointer */ -.intr_ret2: - movl CPU_SOFTINFO(%ebx), %edx /* any pending software interrupts */ - orl %edx, %edx - jz _sys_rtt - jmp dosoftint /* check for softints before we return. */ + jmp _sys_rtt SET_SIZE(cmnint) SET_SIZE(_interrupt) @@ -855,388 +182,6 @@ _interrupt_size: #endif /* __lint */ -#if defined(__i386) - -/* - * Handle an interrupt in a new thread. - * Entry: traps disabled. - * %edi - old priority level - * %ebp - pointer to REGS - * %ecx - translated vector - * %eax - ipl of isr. - * %ebx - pointer to CPU struct - * Uses: - */ - -#if !defined(__lint) - - ENTRY_NP(intr_thread) - / - / Set bit for this PIL in CPU's interrupt active bitmask. - / - - ASSERT_NOT_CPU_INTR_ACTV(%eax, %ebx, _interrupt_actv_bit_set) - - btsl %eax, CPU_INTR_ACTV(%ebx) - - / Get set to run interrupt thread. - / There should always be an interrupt thread since we allocate one - / for each level on the CPU. - / - / Note that the code in kcpc_overflow_intr -relies- on the ordering - / of events here - in particular that t->t_lwp of the interrupt - / thread is set to the pinned thread *before* curthread is changed - / - movl CPU_THREAD(%ebx), %edx /* cur thread in edx */ - - / - / Are we interrupting an interrupt thread? If so, account for it. - / - testw $T_INTR_THREAD, T_FLAGS(%edx) - jz 0f - / - / We have interrupted an interrupt thread. Account for its time slice - / only if its time stamp is non-zero. t_intr_start may be zero due to - / cpu_intr_swtch_enter. - / - cmpl $0, T_INTR_START+4(%edx) - jne 1f - cmpl $0, T_INTR_START(%edx) - je 0f -1: - pushl %ecx - pushl %eax - movl %edx, %esi -_tsc_patch7: - nop; nop /* patched to rdtsc if available */ - TSC_SUB_FROM(%esi, T_INTR_START) - TSC_CLR(%esi, T_INTR_START) - movzbl T_PIL(%esi), %ecx - PILBASE_INTRSTAT(%ebx, %ecx) - TSC_ADD_TO(%ecx, CPU_INTRSTAT) - INTRACCTBASE(%ebx, %ecx) - TSC_ADD_TO(%ecx, CPU_INTRACCT) /* cpu_intracct[cpu_mstate] += tsc */ - movl %esi, %edx - popl %eax - popl %ecx -0: - movl %esp, T_SP(%edx) /* mark stack in curthread for resume */ - pushl %edi /* get a temporary register */ - UNLINK_INTR_THREAD(%ebx, %esi, %edi) - - movl T_LWP(%edx), %edi - movl %edx, T_INTR(%esi) /* push old thread */ - movl %edi, T_LWP(%esi) - / - / Threads on the interrupt thread free list could have state already - / set to TS_ONPROC, but it helps in debugging if they're TS_FREE - / - movl $ONPROC_THREAD, T_STATE(%esi) - / - / chain the interrupted thread onto list from the interrupt thread. - / Set the new interrupt thread as the current one. - / - popl %edi /* Don't need a temp reg anymore */ - movl T_STACK(%esi), %esp /* interrupt stack pointer */ - movl %esp, %ebp - movl %esi, CPU_THREAD(%ebx) /* set new thread */ - pushl %eax /* save the ipl */ - / - / Initialize thread priority level from intr_pri - / - movb %al, T_PIL(%esi) /* store pil */ - movzwl intr_pri, %ebx /* XXX Can cause probs if new class */ - /* is loaded on some other cpu. */ - addl %ebx, %eax /* convert level to dispatch priority */ - movw %ax, T_PRI(%esi) - - / - / Take timestamp and store it in the thread structure. - / - movl %eax, %ebx /* save priority over rdtsc */ -_tsc_patch8: - nop; nop /* patched to rdtsc if available */ - TSC_STORE(%esi, T_INTR_START) - movl %ebx, %eax /* restore priority */ - - / The following 3 instructions need not be in cli. - / Putting them here only to avoid the AGI penalty on Pentiums. - - pushl %ecx /* save interrupt vector. */ - pushl %esi /* save interrupt thread */ - movl $autovect, %esi /* get autovect structure */ - sti /* enable interrupts */ - - / Fast event tracing. - LOADCPU(%ebx) - movl CPU_FTRACE_STATE(%ebx), %ebx - testl $FTRACE_ENABLED, %ebx - jz 1f - - movl 8(%esp), %ebx - pushl %ebx /* ipl */ - pushl %ecx /* int vector */ - movl T_SP(%edx), %ebx - pushl %ebx /* ®s */ - pushl $_ftrace_intr_thread_fmt - call ftrace_3_notick - addl $8, %esp - popl %ecx /* restore int vector */ - addl $4, %esp -1: -pre_loop2: - movl AVH_LINK(%esi, %ecx, 8), %esi - xorl %ebx, %ebx /* bh is cno. of intpts in chain */ - /* bl is DDI_INTR_CLAIMED status of * chain */ - testl %esi, %esi /* if pointer is null */ - jz loop_done2 /* we're done */ -loop2: - movl AV_VECTOR(%esi), %edx /* get the interrupt routine */ - testl %edx, %edx /* if pointer is null */ - jz loop_done2 /* we're done */ - incb %bh - pushl $0 - pushl AV_INTARG2(%esi) - pushl AV_INTARG1(%esi) - pushl AV_VECTOR(%esi) - pushl AV_DIP(%esi) - call __dtrace_probe_interrupt__start - pushl AV_INTARG2(%esi) /* get 2nd arg to interrupt routine */ - pushl AV_INTARG1(%esi) /* get first arg to interrupt routine */ - call *%edx /* call interrupt routine with arg */ - addl $8, %esp - movl %eax, 16(%esp) - call __dtrace_probe_interrupt__complete - addl $20, %esp - orb %al, %bl /* see if anyone claims intpt. */ - movl AV_TICKSP(%esi), %ecx - testl %ecx, %ecx - jz no_time - call intr_get_time - movl AV_TICKSP(%esi), %ecx - TSC_ADD_TO(%ecx, 0) -no_time: - movl AV_LINK(%esi), %esi /* get next routine on list */ - testl %esi, %esi /* if pointer is non-null */ - jnz loop2 /* continue */ -loop_done2: - cmpb $1, %bh /* if only 1 intpt in chain, it is OK */ - je .loop_done2_1 - orb %bl, %bl /* If no one claims intpt, then it is OK */ - jz .loop_done2_1 - movl $autovect, %esi /* else get autovect structure */ - movl 4(%esp), %ecx /* restore intr vector */ - jmp pre_loop2 /* and try again. */ -.loop_done2_1: - popl %esi /* restore intr thread pointer */ - - LOADCPU(%ebx) - - cli /* protect interrupt thread pool and intr_actv */ - movzbl T_PIL(%esi), %eax - - / Save value in regs - pushl %eax /* current pil */ - pushl %edx /* (huh?) */ - pushl %edi /* old pil */ - - / cpu_stats.sys.intr[PIL]++ - INC_CPU_STATS_INTR(%eax, %edx, %edx, %ebx) - - / - / Take timestamp, compute interval, and update cumulative counter. - / esi = thread pointer, ebx = cpu pointer, eax = PIL - / - movl %eax, %edi - - ASSERT_T_INTR_START_NZ(%esi) - -_tsc_patch9: - nop; nop /* patched to rdtsc if available */ - TSC_SUB_FROM(%esi, T_INTR_START) - PILBASE_INTRSTAT(%ebx, %edi) - TSC_ADD_TO(%edi, CPU_INTRSTAT) - INTRACCTBASE(%ebx, %edi) - TSC_ADD_TO(%edi, CPU_INTRACCT) /* cpu_intracct[cpu_mstate] += tsc */ - popl %edi - popl %edx - popl %eax - - / - / Clear bit for this PIL in CPU's interrupt active bitmask. - / - - ASSERT_CPU_INTR_ACTV(%eax, %ebx, _intr_thread_actv_bit_not_set) - - btrl %eax, CPU_INTR_ACTV(%ebx) - - / if there is still an interrupted thread underneath this one - / then the interrupt was never blocked and the return is fairly - / simple. Otherwise jump to intr_thread_exit - cmpl $0, T_INTR(%esi) - je intr_thread_exit - - / - / link the thread back onto the interrupt thread pool - LINK_INTR_THREAD(%ebx, %esi, %edx) - - movl CPU_BASE_SPL(%ebx), %eax /* used below. */ - / set the thread state to free so kmdb doesn't see it - movl $FREE_THREAD, T_STATE(%esi) - - cmpl %eax, %edi /* if (oldipl >= basespl) */ - jae intr_restore_ipl /* then use oldipl */ - movl %eax, %edi /* else use basespl */ -intr_restore_ipl: - movl %edi, CPU_PRI(%ebx) - /* intr vector already on stack */ - pushl %edi /* old ipl */ - call *setlvlx /* eax contains the current ipl */ - / - / Switch back to the interrupted thread - movl T_INTR(%esi), %ecx - - / Place starting timestamp in interrupted thread's thread structure. -_tsc_patch10: - nop; nop /* patched to rdtsc if available */ - TSC_STORE(%ecx, T_INTR_START) - - movl T_SP(%ecx), %esp /* restore stack pointer */ - movl %esp, %ebp - movl %ecx, CPU_THREAD(%ebx) - - movl CPU_SOFTINFO(%ebx), %edx /* any pending software interrupts */ - orl %edx, %edx - jz _sys_rtt - jmp dosoftint /* check for softints before we return. */ - - / - / An interrupt returned on what was once (and still might be) - / an interrupt thread stack, but the interrupted process is no longer - / there. This means the interrupt must have blocked. - / - / There is no longer a thread under this one, so put this thread back - / on the CPU's free list and resume the idle thread which will dispatch - / the next thread to run. - / - / All interrupts are disabled here - / - -intr_thread_exit: -#ifdef DEBUG - incl intr_thread_cnt -#endif - INC64(%ebx, CPU_STATS_SYS_INTRBLK) /* cpu_stats.sys.intrblk++ */ - / - / Put thread back on the interrupt thread list. - / As a reminder, the regs at this point are - / esi interrupt thread - / edi old ipl - / ebx ptr to CPU struct - - / Set CPU's base SPL level based on active interrupts bitmask - call set_base_spl - - movl CPU_BASE_SPL(%ebx), %edi - movl %edi, CPU_PRI(%ebx) - /* interrupt vector already on stack */ - pushl %edi - call *setlvlx - addl $8, %esp /* XXX - don't need to pop since */ - /* we are ready to switch */ - call splhigh /* block all intrs below lock level */ - / - / Set the thread state to free so kmdb doesn't see it - / - movl $FREE_THREAD, T_STATE(%esi) - / - / Put thread on either the interrupt pool or the free pool and - / call swtch() to resume another thread. - / - LINK_INTR_THREAD(%ebx, %esi, %edx) - call swtch - / swtch() shouldn't return - - SET_SIZE(intr_thread) - -#endif /* __lint */ -#endif /* __i386 */ - -/* - * Set Cpu's base SPL level, base on which interrupt levels are active - * Called at spl7 or above. - */ - -#if defined(__lint) - -void -set_base_spl(void) -{} - -#else /* __lint */ - - ENTRY_NP(set_base_spl) - movl %gs:CPU_INTR_ACTV, %eax /* load active interrupts mask */ - testl %eax, %eax /* is it zero? */ - jz setbase - testl $0xff00, %eax - jnz ah_set - shl $24, %eax /* shift 'em over so we can find */ - /* the 1st bit faster */ - bsrl %eax, %eax - subl $24, %eax -setbase: - movl %eax, %gs:CPU_BASE_SPL /* store base priority */ - ret -ah_set: - shl $16, %eax - bsrl %eax, %eax - subl $16, %eax - jmp setbase - SET_SIZE(set_base_spl) - -#endif /* __lint */ - -#if defined(__i386) - -/* - * int - * intr_passivate(from, to) - * thread_id_t from; interrupt thread - * thread_id_t to; interrupted thread - * - * intr_passivate(t, itp) makes the interrupted thread "t" runnable. - * - * Since t->t_sp has already been saved, t->t_pc is all that needs - * set in this function. - * - * Returns interrupt level of the thread. - */ - -#if defined(__lint) - -/* ARGSUSED */ -int -intr_passivate(kthread_id_t from, kthread_id_t to) -{ return (0); } - -#else /* __lint */ - - ENTRY(intr_passivate) - movl 8(%esp), %eax /* interrupted thread */ - movl $_sys_rtt, T_PC(%eax) /* set T_PC for interrupted thread */ - - movl 4(%esp), %eax /* interrupt thread */ - movl T_STACK(%eax), %eax /* get the pointer to the start of */ - /* of the interrupt thread stack */ - movl -4(%eax), %eax /* interrupt level was the first */ - /* thing pushed onto the stack */ - ret - SET_SIZE(intr_passivate) - -#endif /* __lint */ -#endif /* __i386 */ - #if defined(__lint) void @@ -1274,412 +219,24 @@ fakesoftint(void) pushq $0 /* err */ pushq $T_SOFTINT /* trap */ jmp cmnint + ALTENTRY(fakesoftint_return) + ret + SET_SIZE(fakesoftint_return) SET_SIZE(fakesoftint) #elif defined(__i386) ENTRY_NP(fakesoftint) - pushf - push %cs - push $fakesoftint_return - push $0 - push $T_SOFTINT + pushfl + pushl %cs + pushl $fakesoftint_return + pushl $0 + pushl $T_SOFTINT jmp cmnint + ALTENTRY(fakesoftint_return) + ret + SET_SIZE(fakesoftint_return) SET_SIZE(fakesoftint) #endif /* __i386 */ - - .align CPTRSIZE - .globl _fakesoftint_size - .type _fakesoftint_size, @object -_fakesoftint_size: - .NWORD . - fakesoftint - SET_SIZE(_fakesoftint_size) - -/* - * dosoftint(old_pil in %edi, softinfo in %edx, CPU pointer in %ebx) - * Process software interrupts - * Interrupts are disabled here. - */ -#if defined(__i386) - - ENTRY_NP(dosoftint) - - bsrl %edx, %edx /* find highest pending interrupt */ - cmpl %edx, %edi /* if curipl >= pri soft pending intr */ - jae _sys_rtt /* skip */ - - movl %gs:CPU_BASE_SPL, %eax /* check for blocked intr threads */ - cmpl %edx, %eax /* if basespl >= pri soft pending */ - jae _sys_rtt /* skip */ - - lock /* MP protect */ - btrl %edx, CPU_SOFTINFO(%ebx) /* clear the selected interrupt bit */ - jnc dosoftint_again - - movl %edx, CPU_PRI(%ebx) /* set IPL to sofint level */ - pushl %edx - call *setspl /* mask levels upto the softint level */ - popl %eax /* priority we are at in %eax */ - - / Get set to run interrupt thread. - / There should always be an interrupt thread since we allocate one - / for each level on the CPU. - UNLINK_INTR_THREAD(%ebx, %esi, %edx) - - / - / Note that the code in kcpc_overflow_intr -relies- on the ordering - / of events here - in particular that t->t_lwp of the interrupt - / thread is set to the pinned thread *before* curthread is changed - / - movl CPU_THREAD(%ebx), %ecx - - / If we are interrupting an interrupt thread, account for it. - testw $T_INTR_THREAD, T_FLAGS(%ecx) - jz 0f - / - / We have interrupted an interrupt thread. Account for its time slice - / only if its time stamp is non-zero. t_intr_start may be zero due to - / cpu_intr_swtch_enter. - / - cmpl $0, T_INTR_START+4(%ecx) - jne 1f - cmpl $0, T_INTR_START(%ecx) - je 0f -1: - pushl %eax - movl %eax, %ebp -_tsc_patch11: - nop; nop /* patched to rdtsc if available */ - PILBASE_INTRSTAT(%ebx, %ebp) - TSC_SUB_FROM(%ecx, T_INTR_START) - TSC_ADD_TO(%ebp, CPU_INTRSTAT) - INTRACCTBASE(%ebx, %ebp) - TSC_ADD_TO(%ebp, CPU_INTRACCT) /* cpu_intracct[cpu_mstate] += tsc */ - popl %eax -0: - movl T_LWP(%ecx), %ebp - movl %ebp, T_LWP(%esi) - / - / Threads on the interrupt thread free list could have state already - / set to TS_ONPROC, but it helps in debugging if they're TS_FREE - / Could eliminate the next two instructions with a little work. - / - movl $ONPROC_THREAD, T_STATE(%esi) - / - / Push interrupted thread onto list from new thread. - / Set the new thread as the current one. - / Set interrupted thread's T_SP because if it is the idle thread, - / Resume() may use that stack between threads. - / - movl %esp, T_SP(%ecx) /* mark stack for resume */ - movl %ecx, T_INTR(%esi) /* push old thread */ - movl %esi, CPU_THREAD(%ebx) /* set new thread */ - movl T_STACK(%esi), %esp /* interrupt stack pointer */ - movl %esp, %ebp - - pushl %eax /* push ipl as first element in stack */ - /* see intr_passivate() */ - / - / Set bit for this PIL in CPU's interrupt active bitmask. - / - - ASSERT_NOT_CPU_INTR_ACTV(%eax, %ebx, _dosoftint_actv_bit_set) - - btsl %eax, CPU_INTR_ACTV(%ebx) - - / - / Initialize thread priority level from intr_pri - / - movb %al, T_PIL(%esi) /* store pil */ - movzwl intr_pri, %ecx - addl %eax, %ecx /* convert level to dispatch priority */ - movw %cx, T_PRI(%esi) - - / - / Store starting timestamp in thread structure. - / esi = thread, ebx = cpu pointer, eax = PIL - / - movl %eax, %ecx /* save PIL from rdtsc clobber */ -_tsc_patch12: - nop; nop /* patched to rdtsc if available */ - TSC_STORE(%esi, T_INTR_START) - - sti /* enable interrupts */ - - / - / Enabling interrupts (above) could raise the current - / IPL and base SPL. But, we continue processing the current soft - / interrupt and we will check the base SPL next time in the loop - / so that blocked interrupt thread would get a chance to run. - / - - / - / dispatch soft interrupts - / - pushl %ecx - call av_dispatch_softvect - addl $4, %esp - - cli /* protect interrupt thread pool */ - /* and softinfo & sysinfo */ - movl CPU_THREAD(%ebx), %esi /* restore thread pointer */ - movzbl T_PIL(%esi), %ecx - - / cpu_stats.sys.intr[PIL]++ - INC_CPU_STATS_INTR(%ecx, %edx, %edx, %ebx) - - / - / Clear bit for this PIL in CPU's interrupt active bitmask. - / - - ASSERT_CPU_INTR_ACTV(%ecx, %ebx, _dosoftint_actv_bit_not_set) - - btrl %ecx, CPU_INTR_ACTV(%ebx) - - / - / Take timestamp, compute interval, update cumulative counter. - / esi = thread, ebx = cpu, ecx = PIL - / - PILBASE_INTRSTAT(%ebx, %ecx) -_tsc_patch13: - nop; nop /* patched to rdtsc if available */ - TSC_SUB_FROM(%esi, T_INTR_START) - TSC_ADD_TO(%ecx, CPU_INTRSTAT) - INTRACCTBASE(%ebx, %ecx) - TSC_ADD_TO(%ecx, CPU_INTRACCT) /* cpu_intracct[cpu_mstate] += tsc */ - - / if there is still an interrupt thread underneath this one - / then the interrupt was never blocked and the return is fairly - / simple. Otherwise jump to softintr_thread_exit. - / softintr_thread_exit expect esi to be curthread & ebx to be ipl. - cmpl $0, T_INTR(%esi) - je softintr_thread_exit - - / - / link the thread back onto the interrupt thread pool - LINK_INTR_THREAD(%ebx, %esi, %edx) - - / set the thread state to free so kmdb doesn't see it - movl $FREE_THREAD, T_STATE(%esi) - / - / Switch back to the interrupted thread - movl T_INTR(%esi), %ecx - movl %ecx, CPU_THREAD(%ebx) - movl T_SP(%ecx), %esp /* restore stack pointer */ - movl %esp, %ebp - - / If we are returning to an interrupt thread, store a starting - / timestamp in the thread structure. - testw $T_INTR_THREAD, T_FLAGS(%ecx) - jz 0f -_tsc_patch14: - nop; nop /* patched to rdtsc if available */ - TSC_STORE(%ecx, T_INTR_START) -0: - movl CPU_BASE_SPL(%ebx), %eax - cmpl %eax, %edi /* if (oldipl >= basespl) */ - jae softintr_restore_ipl /* then use oldipl */ - movl %eax, %edi /* else use basespl */ -softintr_restore_ipl: - movl %edi, CPU_PRI(%ebx) /* set IPL to old level */ - pushl %edi - call *setspl - popl %eax -dosoftint_again: - movl CPU_SOFTINFO(%ebx), %edx /* any pending software interrupts */ - orl %edx, %edx - jz _sys_rtt - jmp dosoftint /* process more software interrupts */ - -softintr_thread_exit: - / - / Put thread back on the interrupt thread list. - / As a reminder, the regs at this point are - / %esi interrupt thread - - / - / This was an interrupt thread, so set CPU's base SPL level - / set_base_spl only uses %eax. - / - call set_base_spl /* interrupt vector already on stack */ - / - / Set the thread state to free so kmdb doesn't see it - / - movl $FREE_THREAD, T_STATE(%esi) - / - / Put thread on either the interrupt pool or the free pool and - / call swtch() to resume another thread. - / - LOADCPU(%ebx) - LINK_INTR_THREAD(%ebx, %esi, %edx) - call splhigh /* block all intrs below lock lvl */ - call swtch - / swtch() shouldn't return - SET_SIZE(dosoftint) - -#endif /* __i386 */ #endif /* __lint */ - -#if defined(lint) - -/* - * intr_get_time() is a resource for interrupt handlers to determine how - * much time has been spent handling the current interrupt. Such a function - * is needed because higher level interrupts can arrive during the - * processing of an interrupt, thus making direct comparisons of %tick by - * the handler inaccurate. intr_get_time() only returns time spent in the - * current interrupt handler. - * - * The caller must be calling from an interrupt handler running at a pil - * below or at lock level. Timings are not provided for high-level - * interrupts. - * - * The first time intr_get_time() is called while handling an interrupt, - * it returns the time since the interrupt handler was invoked. Subsequent - * calls will return the time since the prior call to intr_get_time(). Time - * is returned as ticks. Use tsc_scalehrtime() to convert ticks to nsec. - * - * Theory Of Intrstat[][]: - * - * uint64_t intrstat[pil][0..1] is an array indexed by pil level, with two - * uint64_ts per pil. - * - * intrstat[pil][0] is a cumulative count of the number of ticks spent - * handling all interrupts at the specified pil on this CPU. It is - * exported via kstats to the user. - * - * intrstat[pil][1] is always a count of ticks less than or equal to the - * value in [0]. The difference between [1] and [0] is the value returned - * by a call to intr_get_time(). At the start of interrupt processing, - * [0] and [1] will be equal (or nearly so). As the interrupt consumes - * time, [0] will increase, but [1] will remain the same. A call to - * intr_get_time() will return the difference, then update [1] to be the - * same as [0]. Future calls will return the time since the last call. - * Finally, when the interrupt completes, [1] is updated to the same as [0]. - * - * Implementation: - * - * intr_get_time() works much like a higher level interrupt arriving. It - * "checkpoints" the timing information by incrementing intrstat[pil][0] - * to include elapsed running time, and by setting t_intr_start to rdtsc. - * It then sets the return value to intrstat[pil][0] - intrstat[pil][1], - * and updates intrstat[pil][1] to be the same as the new value of - * intrstat[pil][0]. - * - * In the normal handling of interrupts, after an interrupt handler returns - * and the code in intr_thread() updates intrstat[pil][0], it then sets - * intrstat[pil][1] to the new value of intrstat[pil][0]. When [0] == [1], - * the timings are reset, i.e. intr_get_time() will return [0] - [1] which - * is 0. - * - * Whenever interrupts arrive on a CPU which is handling a lower pil - * interrupt, they update the lower pil's [0] to show time spent in the - * handler that they've interrupted. This results in a growing discrepancy - * between [0] and [1], which is returned the next time intr_get_time() is - * called. Time spent in the higher-pil interrupt will not be returned in - * the next intr_get_time() call from the original interrupt, because - * the higher-pil interrupt's time is accumulated in intrstat[higherpil][]. - */ - -/*ARGSUSED*/ -uint64_t -intr_get_time(void) -{ return 0; } -#else /* lint */ - - -#if defined(__amd64) - ENTRY_NP(intr_get_time) - cli /* make this easy -- block intrs */ - LOADCPU(%rdi) - call intr_thread_get_time - sti - ret - SET_SIZE(intr_get_time) - -#elif defined(__i386) - -#ifdef DEBUG - - -_intr_get_time_high_pil: - .string "intr_get_time(): %pil > LOCK_LEVEL" -_intr_get_time_not_intr: - .string "intr_get_time(): not called from an interrupt thread" -_intr_get_time_no_start_time: - .string "intr_get_time(): t_intr_start == 0" - -/* - * ASSERT(%pil <= LOCK_LEVEL) - */ -#define ASSERT_PIL_BELOW_LOCK_LEVEL(cpureg) \ - testl $CPU_INTR_ACTV_HIGH_LEVEL_MASK, CPU_INTR_ACTV(cpureg); \ - jz 0f; \ - __PANIC(_intr_get_time_high_pil, 0f); \ -0: - -/* - * ASSERT((t_flags & T_INTR_THREAD) != 0 && t_pil > 0) - */ -#define ASSERT_NO_PIL_0_INTRS(thrreg) \ - testw $T_INTR_THREAD, T_FLAGS(thrreg); \ - jz 1f; \ - cmpb $0, T_PIL(thrreg); \ - jne 0f; \ -1: \ - __PANIC(_intr_get_time_not_intr, 0f); \ -0: - -/* - * ASSERT(t_intr_start != 0) - */ -#define ASSERT_INTR_START_NOT_0(thrreg) \ - cmpl $0, T_INTR_START(thrreg); \ - jnz 0f; \ - cmpl $0, T_INTR_START+4(thrreg); \ - jnz 0f; \ - __PANIC(_intr_get_time_no_start_time, 0f); \ -0: - -#endif /* DEBUG */ - - ENTRY_NP(intr_get_time) - - cli /* make this easy -- block intrs */ - pushl %esi /* and free up some registers */ - pushl %ebx - - LOADCPU(%esi) - movl CPU_THREAD(%esi), %ecx - -#ifdef DEBUG - ASSERT_PIL_BELOW_LOCK_LEVEL(%esi) - ASSERT_NO_PIL_0_INTRS(%ecx) - ASSERT_INTR_START_NOT_0(%ecx) -#endif /* DEBUG */ - -_tsc_patch17: - nop; nop /* patched to rdtsc if available */ - TSC_SUB_FROM(%ecx, T_INTR_START) /* get elapsed time */ - TSC_ADD_TO(%ecx, T_INTR_START) /* T_INTR_START = rdtsc */ - - INTRACCTBASE(%esi, %ebx) /* %ebx = CPU + cpu_mstate*8 */ - TSC_ADD_TO(%ebx, CPU_INTRACCT); /* intracct[ms] += elapsed */ - movzbl T_PIL(%ecx), %ecx /* %ecx = pil */ - PILBASE_INTRSTAT(%esi, %ecx) /* %ecx = CPU + pil*16 */ - TSC_ADD_TO(%ecx, CPU_INTRSTAT) /* intrstat[0] += elapsed */ - TSC_LOAD(%ecx, CPU_INTRSTAT) /* get new intrstat[0] */ - TSC_SUB_FROM(%ecx, CPU_INTRSTAT+8) /* diff with intrstat[1] */ - TSC_ADD_TO(%ecx, CPU_INTRSTAT+8) /* intrstat[1] = intrstat[0] */ - - /* %edx/%eax contain difference between old and new intrstat[1] */ - - popl %ebx - popl %esi - sti - ret - SET_SIZE(intr_get_time) -#endif /* __i386 */ - -#endif /* lint */ diff --git a/usr/src/uts/i86pc/ml/kdi_subr.s b/usr/src/uts/i86pc/ml/kdi_subr.s new file mode 100644 index 0000000000..8ed90ed410 --- /dev/null +++ b/usr/src/uts/i86pc/ml/kdi_subr.s @@ -0,0 +1,160 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/asm_linkage.h> +#include <sys/asm_misc.h> +#include <sys/regset.h> +#include <sys/privregs.h> +#include <sys/psw.h> + +#if defined(__lint) +#include <sys/types.h> +#include <sys/segments.h> +#endif + +#if defined(__lint) + +ulong_t +kdi_getdr0(void) +{ + return (0); +} + +ulong_t +kdi_getdr1(void) +{ + return (0); +} + +ulong_t +kdi_getdr2(void) +{ + return (0); +} + +ulong_t +kdi_getdr3(void) +{ + return (0); +} + +ulong_t +kdi_getdr6(void) +{ + return (0); +} + +ulong_t +kdi_getdr7(void) +{ + return (0); +} + +/*ARGSUSED*/ +void +kdi_setdr0(ulong_t value) +{} + +/*ARGSUSED*/ +void +kdi_setdr1(ulong_t value) +{} + +/*ARGSUSED*/ +void +kdi_setdr2(ulong_t value) +{} + +/*ARGSUSED*/ +void +kdi_setdr3(ulong_t value) +{} + +/*ARGSUSED*/ +void +kdi_setdr4(ulong_t value) +{} + +/*ARGSUSED*/ +void +kdi_setdr6(ulong_t value) +{} + +/*ARGSUSED*/ +void +kdi_setdr7(ulong_t value) +{} + +#else + +#if defined(__amd64) + +#define GETDREG(name, r) \ + ENTRY_NP(name); \ + movq r, %rax; \ + ret; \ + SET_SIZE(name) + +#define SETDREG(name, r) \ + ENTRY_NP(name); \ + movq %rdi, r; \ + ret; \ + SET_SIZE(name) + +#elif defined(__i386) + +#define GETDREG(name, r) \ + ENTRY_NP(name); \ + movl r, %eax; \ + ret; \ + SET_SIZE(name) + +#define SETDREG(name, r) \ + ENTRY_NP(name); \ + movl 4(%esp), %eax; \ + movl %eax, r; \ + ret; \ + SET_SIZE(name) + +#endif + + GETDREG(kdi_getdr0, %dr0) + GETDREG(kdi_getdr1, %dr1) + GETDREG(kdi_getdr2, %dr2) + GETDREG(kdi_getdr3, %dr3) + GETDREG(kdi_getdr6, %dr6) + GETDREG(kdi_getdr7, %dr7) + + SETDREG(kdi_setdr0, %dr0) + SETDREG(kdi_setdr1, %dr1) + SETDREG(kdi_setdr2, %dr2) + SETDREG(kdi_setdr3, %dr3) + SETDREG(kdi_setdr6, %dr6) + SETDREG(kdi_setdr7, %dr7) + +#endif /* __lint */ diff --git a/usr/src/uts/i86pc/ml/locore.s b/usr/src/uts/i86pc/ml/locore.s index bc88297503..c3da3b99bc 100644 --- a/usr/src/uts/i86pc/ml/locore.s +++ b/usr/src/uts/i86pc/ml/locore.s @@ -18,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -63,6 +64,7 @@ #include <sys/cmn_err.h> #include <sys/pit.h> #include <sys/panic.h> + #include "assym.h" /* @@ -93,11 +95,17 @@ * * NOW, the real code! */ + /* + * The very first thing in the kernel's text segment must be a jump + * to the os/fakebop.c startup code. + */ + .text + jmp _start /* * Globals: */ - .globl _start + .globl _locore_start .globl mlsetup .globl main .globl panic @@ -143,32 +151,32 @@ /* * Enough padding for 31 more CPUs (no .skip on x86 -- grrrr). */ - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0 #if defined(__amd64) #if NCPU != 64 -#error "NCPU != 64, Expand padding for trap_trace_ctl" +#error "NCPU != 64, Expand padding for trap_trace_ctl" #endif /* * Enough padding for 32 more CPUs (no .skip on x86 -- grrrr). */ - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - .NWORD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + .NWORD 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 #else /* __amd64 */ @@ -200,12 +208,16 @@ /* ARGSUSED */ void -_start(struct boot_syscalls *sysp, struct bootops *bop, Elf64_Boot *ebp) +_locore_start(struct boot_syscalls *sysp, ulong_t rsi, struct bootops *bop) {} #else /* __lint */ - ENTRY_NP(_start) + /* + * kobj_init() vectors us back to here with (note) a slightly different + * set of arguments than _start is given (see lint prototypes above). + */ + ENTRY_NP(_locore_start) /* * %rdi = boot services (should die someday) @@ -249,8 +261,6 @@ _start(struct boot_syscalls *sysp, struct bootops *bop, Elf64_Boot *ebp) popq %r11 movq %r11, REGOFF_RFL(%rsp) - DISABLE_INTR_FLAGS - /* * Enable write protect and alignment check faults. */ @@ -279,35 +289,7 @@ _start(struct boot_syscalls *sysp, struct bootops *bop, Elf64_Boot *ebp) leaq __return_from_main(%rip), %rdi xorl %eax, %eax call panic - SET_SIZE(_start) - - /* - * Kernel's handler to switch stacks before invoking - * vmx's putchar handler. - * - * This is needed because we use the boot program for - * console services for a -long- time before consconfig - * takes them over. In an ideal world, we'd have a console - * configured earlier. - * - * We use this stack to execute bsys->putchar on, because - * we may be asking vmx/boot to print something using a stack - * that only exists in the 64-bit MMU e.g. a trapping thread. - */ - .data - .comm _safe_putchar_stack, DEFAULTSTKSZ, 32 - - ENTRY_NP(_stack_safe_putchar) - .globl _vmx_sysp - movq %rsp, %r11 - leaq _safe_putchar_stack+DEFAULTSTKSZ(%rip), %rsp - pushq %r11 - movq _vmx_sysp(%rip), %r10 - call *BOOTSVCS_PUTCHAR(%r10) - popq %r11 - movq %r11, %rsp - ret - SET_SIZE(_stack_safe_putchar) + SET_SIZE(_locore_start) #endif /* __amd64 */ #endif /* __lint */ @@ -325,93 +307,20 @@ __unsupported_cpu: #if defined(__lint) -/*ARGSUSED*/ +/* ARGSUSED */ void -_start(struct boot_syscalls *sysp, struct bootops *bop, Elf32_Boot * ebp) +_locore_start(struct boot_syscalls *sysp, struct bootops *bop) {} #else /* __lint */ - ENTRY_NP(_start) /* - * We jump to __start to make sure the function - * enable_big_page_support does not span multiple 4K pages. This - * is essential, since we need to turn paging off in - * enable_big_page_support + * kobj_init() vectors us back to here with (note) a slightly different + * set of arguments than _start is given (see lint prototypes above). */ - jmp __start - - /* - * It is very important that this function sit right here in the file - * This function should not span multiple pages. This function has - * to be executed from an address such that we have 1-1 mapping. - * First we disable paging, then we load %cr4 with %edx and then - * enable paging. We return to 0xe00xxxx with paging enabled. - */ - - ENTRY_NP(enable_big_page_support) - movl %cr0, %eax - and $_BITNOT(CR0_PG), %eax - movl %eax, %cr0 / disable paging - movl %cr3, %eax - movl %eax, %cr3 - movl %cr4, %eax - orl %ebx, %eax - movl %eax, %cr4 - nop - movl %cr0, %eax - orl $CR0_PG, %eax / enable paging - movl %eax, %cr0 - jmp enable_big_page_support_done -enable_big_page_support_done: - xorl %eax, %eax - ret - SET_SIZE(enable_big_page_support) - /* - * This function enables physical address extension thereby - * switching from 32 bit pte's to 64 bit pte's - * - * It loads the argument that it received in %ebx into cr3 - * - * XXX is there some reason why this routine -can't- use - * normal C parameter passing conventions?? - */ - ENTRY_NP(enable_pae) - /* - * disable paging - */ - movl %cr0, %eax - andl $_BITNOT(CR0_PG), %eax - movl %eax, %cr0 - /* - * enable physical address extension - */ - movl %cr4, %eax - orl $CR4_PAE, %eax - movl %eax, %cr4 - /* - * set new page table base - */ - movl %ebx, %cr3 - /* - * restart paging - */ - movl %cr0, %eax - orl $CR0_PG, %eax - movl %eax, %cr0 - jmp enable_pae_done / jmp required after enabling paging -enable_pae_done: - /* - * flush TLBs just in case and return - */ - movl %cr3, %eax - movl %eax, %cr3 - orl $CR4_PAE, cr4_value - ret - SET_SIZE(enable_pae) + ENTRY_NP(_locore_start) -__start: /* * %ecx = boot services (should die someday) * %ebx = bootops @@ -433,7 +342,7 @@ __start: mov %ebx, bootops / save bootops movl $bootops, bootopsp - DISABLE_INTR_FLAGS + /* * Save all registers and flags */ @@ -453,6 +362,7 @@ __start: andl $_BITNOT(CR0_WT|CR0_CE), %eax movl %eax, %cr0 / set the cr0 register correctly and / override the BIOS setup + /* * If bit 21 of eflags can be flipped, then cpuid is present * and enabled. @@ -1193,6 +1103,7 @@ coma_bug: jmp cpu_done cpu_done: + popfl /* Restore original FLAGS */ popal /* Restore all registers */ @@ -1217,15 +1128,16 @@ cpu_done: cpu_486: pushl $__unsupported_cpu call panic - SET_SIZE(_start) + SET_SIZE(_locore_start) #endif /* __lint */ #endif /* !__amd64 */ /* - * For stack layout, see reg.h + * For stack layout, see privregs.h * When cmntrap gets called, the error code and trap number have been pushed. + * When cmntrap_pushed gets called, the entire struct regs has been pushed. */ #if defined(__lint) @@ -1243,14 +1155,28 @@ cmntrap() ENTRY_NP2(cmntrap, _cmntrap) - TRAP_PUSH + INTR_PUSH + ALTENTRY(cmntrap_pushed) + + movq %rsp, %rbp + + /* + * - if this is a #pf i.e. T_PGFLT, %r15 is live + * and contains the faulting address i.e. a copy of %cr2 + * + * - if this is a #db i.e. T_SGLSTP, %r15 is live + * and contains the value of %db6 + */ + + TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_TRAP) /* Uses labels 8 and 9 */ + TRACE_REGS(%rdi, %rsp, %rbx, %rcx) /* Uses label 9 */ + TRACE_STAMP(%rdi) /* Clobbers %eax, %edx, uses 9 */ /* * We must first check if DTrace has set its NOFAULT bit. This - * regrettably must happen before the TRAPTRACE data is recorded, - * because recording the TRAPTRACE data includes obtaining a stack - * trace -- which requires a call to getpcstack() and may induce - * recursion if an fbt::getpcstack: enabling is inducing the bad load. + * regrettably must happen before the trap stack is recorded, because + * this requires a call to getpcstack() and may induce recursion if an + * fbt::getpcstack: enabling is inducing the bad load. */ movl %gs:CPU_ID, %eax shlq $CPU_CORE_SHIFT, %rax @@ -1260,60 +1186,31 @@ cmntrap() testw $CPU_DTRACE_NOFAULT, %cx jnz .dtrace_induced - TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_TRAP) /* Uses labels 8 and 9 */ - TRACE_REGS(%rdi, %rsp, %rbx, %rcx) /* Uses label 9 */ - TRACE_STAMP(%rdi) /* Clobbers %eax, %edx, uses 9 */ - - /* - * Getting a stack trace as part of TRACE_STACK() requires a call to - * getpcstack(). Before we can do this, we must move our stack pointer - * into the base pointer, and we must save the value of %cr2. %cr2 - * must be saved before the call because getpcstack() may be - * instrumented by DTrace -- and any invalid load in the DTrace - * enabling will clobber %cr2. - */ - movq %rsp, %rbp - movq %cr2, %r12 - TRACE_STACK(%rdi) -/ XXX - check for NMIs???? - - / If this is a debug trap, save %dr6 in the pcb - cmpl $T_SGLSTP, REGOFF_TRAPNO(%rbp) - jne .L11 - movq %gs:CPU_LWP, %rax - orq %rax, %rax - jz .L11 /* null lwp pointer; can't happen? */ - movq %db6, %rcx - movq %rcx, LWP_PCB_DRSTAT(%rax) - movl $0, %ecx - movq %rcx, %db6 /* clear debug status register */ -.L11: movq %rbp, %rdi - movq %r12, %rsi + movq %r15, %rsi movl %gs:CPU_ID, %edx - / - / We know that this isn't a DTrace non-faulting load; we can now safely - / reenable interrupts. (In the case of pagefaults, we enter through an - / interrupt gate.) - / + /* + * We know that this isn't a DTrace non-faulting load; we can now safely + * reenable interrupts. (In the case of pagefaults, we enter through an + * interrupt gate.) + */ ENABLE_INTR_FLAGS call trap /* trap(rp, addr, cpuid) handles all traps */ - jmp _sys_rtt + .dtrace_induced: - movq %rsp, %rbp - testw $CPL_MASK, REGOFF_CS(%rbp) /* test CS for user-mode trap */ - jnz 2f /* if from user, panic */ + cmpw $KCS_SEL, REGOFF_CS(%rbp) /* test CS for user-mode trap */ + jne 2f /* if from user, panic */ cmpl $T_PGFLT, REGOFF_TRAPNO(%rbp) - je 0f /* if not a pagefault, panic */ + je 0f cmpl $T_GPFLT, REGOFF_TRAPNO(%rbp) - jne 3f + jne 3f /* if not PF or GP, panic */ /* * If we've taken a GPF, we don't (unfortunately) have the address that @@ -1326,8 +1223,7 @@ cmntrap() 0: orw $CPU_DTRACE_BADADDR, %cx movw %cx, CPUC_DTRACE_FLAGS(%rax) /* set fault to bad addr */ - movq %cr2, %rcx - movq %rcx, CPUC_DTRACE_ILLVAL(%rax) + movq %r15, CPUC_DTRACE_ILLVAL(%rax) /* fault addr is illegal value */ 1: movq REGOFF_RIP(%rbp), %rdi @@ -1336,7 +1232,8 @@ cmntrap() addq %rax, %r12 movq %r12, REGOFF_RIP(%rbp) INTR_POP - iretq + IRET + /*NOTREACHED*/ 2: leaq dtrace_badflags(%rip), %rdi xorl %eax, %eax @@ -1345,49 +1242,50 @@ cmntrap() leaq dtrace_badtrap(%rip), %rdi xorl %eax, %eax call panic - SET_SIZE(cmntrap) SET_SIZE(_cmntrap) #elif defined(__i386) + ENTRY_NP2(cmntrap, _cmntrap) INTR_PUSH - TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_TRAP) /* Uses labels 8 and 9 */ - TRACE_REGS(%edi, %esp, %ebx, %ecx) /* Uses label 9 */ - TRACE_STAMP(%edi) /* Clobbers %eax, %edx, uses 9 */ + ALTENTRY(cmntrap_pushed) movl %esp, %ebp -/ XXX - check for NMIs???? - - / If this is a debug trap, save %dr6 in the pcb - cmpl $T_SGLSTP, REGOFF_TRAPNO(%ebp) - jne .L11 - movl %gs:CPU_LWP, %eax - orl %eax, %eax - jz .L11 /* null lwp pointer; can't happen? */ - movl %db6, %ecx - movl %ecx, LWP_PCB_DRSTAT(%eax) - movl $0, %ecx - movl %ecx, %db6 /* clear debug status register */ -.L11: - pushl %gs:CPU_ID - movl %cr2, %eax / fault address for PGFLTs - pushl %eax - pushl %ebp + /* + * - if this is a #pf i.e. T_PGFLT, %esi is live + * and contains the faulting address i.e. a copy of %cr2 + * + * - if this is a #db i.e. T_SGLSTP, %esi is live + * and contains the value of %db6 + */ + + TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_TRAP) /* Uses labels 8 and 9 */ + TRACE_REGS(%edi, %esp, %ebx, %ecx) /* Uses label 9 */ + TRACE_STAMP(%edi) /* Clobbers %eax, %edx, uses 9 */ /* - * We must now check if DTrace has set its NOFAULT bit. + * We must first check if DTrace has set its NOFAULT bit. This + * regrettably must happen before the trap stack is recorded, because + * this requires a call to getpcstack() and may induce recursion if an + * fbt::getpcstack: enabling is inducing the bad load. */ movl %gs:CPU_ID, %eax shll $CPU_CORE_SHIFT, %eax addl $cpu_core, %eax movw CPUC_DTRACE_FLAGS(%eax), %cx testw $CPU_DTRACE_NOFAULT, %cx - jnz 0f + jnz .dtrace_induced + + TRACE_STACK(%edi) + + pushl %gs:CPU_ID + pushl %esi /* fault address for PGFLTs */ + pushl %ebp /* ®s */ /* * We know that this isn't a DTrace non-faulting load; we can now safely @@ -1398,18 +1296,17 @@ cmntrap() call trap /* trap(rp, addr, cpuid) handles all traps */ addl $12, %esp /* get argument off stack */ - jmp _sys_rtt -0: - testw $CPL_MASK, REGOFF_CS(%ebp) /* test CS for user-mode trap */ - jnz 2f /* if from user, panic */ +.dtrace_induced: + cmpw $KCS_SEL, REGOFF_CS(%ebp) /* test CS for user-mode trap */ + jne 2f /* if from user, panic */ cmpl $T_PGFLT, REGOFF_TRAPNO(%ebp) - je 0f /* if not a pagefault, panic */ + je 0f cmpl $T_GPFLT, REGOFF_TRAPNO(%ebp) - jne 3f + jne 3f /* if not PF or GP, panic */ /* * If we've taken a GPF, we don't (unfortunately) have the address that @@ -1419,30 +1316,26 @@ cmntrap() orw $CPU_DTRACE_ILLOP, %cx movw %cx, CPUC_DTRACE_FLAGS(%eax) jmp 1f - 0: orw $CPU_DTRACE_BADADDR, %cx movw %cx, CPUC_DTRACE_FLAGS(%eax) /* set fault to bad addr */ - movl %cr2, %ecx - movl %ecx, CPUC_DTRACE_ILLVAL(%eax) + movl %esi, CPUC_DTRACE_ILLVAL(%eax) /* fault addr is illegal value */ 1: pushl REGOFF_EIP(%ebp) call dtrace_instr_size - addl $16, %esp + addl $4, %esp movl REGOFF_EIP(%ebp), %ecx addl %eax, %ecx movl %ecx, REGOFF_EIP(%ebp) INTR_POP_KERNEL - iret + IRET 2: pushl $dtrace_badflags call panic - 3: pushl $dtrace_badtrap call panic - SET_SIZE(cmntrap) SET_SIZE(_cmntrap) @@ -1473,6 +1366,10 @@ void cmninttrap() {} +void +bop_trap_handler(void) +{} + #else /* __lint */ .globl trap /* C handler called below */ @@ -1482,42 +1379,63 @@ cmninttrap() ENTRY_NP(cmninttrap) INTR_PUSH + INTGATE_INIT_KERNEL_FLAGS TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_TRAP) /* Uses labels 8 and 9 */ TRACE_REGS(%rdi, %rsp, %rbx, %rcx) /* Uses label 9 */ TRACE_STAMP(%rdi) /* Clobbers %eax, %edx, uses 9 */ - DISABLE_INTR_FLAGS - movq %rsp, %rbp movl %gs:CPU_ID, %edx xorl %esi, %esi movq %rsp, %rdi call trap /* trap(rp, addr, cpuid) handles all traps */ - jmp _sys_rtt SET_SIZE(cmninttrap) + /* + * Handle traps early in boot. Just revectors into C quickly as + * these are always fatal errors. + */ + ENTRY(bop_trap_handler) + movq %rsp, %rdi + call bop_trap + SET_SIZE(bop_trap_handler) + #elif defined(__i386) ENTRY_NP(cmninttrap) INTR_PUSH - DISABLE_INTR_FLAGS + INTGATE_INIT_KERNEL_FLAGS + + TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_TRAP) /* Uses labels 8 and 9 */ + TRACE_REGS(%edi, %esp, %ebx, %ecx) /* Uses label 9 */ + TRACE_STAMP(%edi) /* Clobbers %eax, %edx, uses 9 */ movl %esp, %ebp - movl %esp, %ecx + TRACE_STACK(%edi) + pushl %gs:CPU_ID - pushl $0 /* fake cr2 (cmntrap is used for page faults) */ - pushl %ecx + pushl $0 + pushl %ebp call trap /* trap(rp, addr, cpuid) handles all traps */ - addl $12, %esp /* get argument off stack */ - + addl $12, %esp jmp _sys_rtt SET_SIZE(cmninttrap) + /* + * Handle traps early in boot. Just revectors into C quickly as + * these are always fatal errors. + */ + ENTRY(bop_trap_handler) + movl %esp, %eax + pushl %eax + call bop_trap + SET_SIZE(bop_trap_handler) + #endif /* __i386 */ #endif /* __lint */ @@ -1573,8 +1491,7 @@ dtrace_trap() pushl %eax pushl %ebp - pushl $F_ON - popfl + ENABLE_INTR_FLAGS call dtrace_user_probe /* dtrace_user_probe(rp, addr, cpuid) */ addl $12, %esp /* get argument off stack */ @@ -1649,7 +1566,7 @@ _lwp_rtt: xorl %eax, %eax call panic _no_pending_updates: - .string "%M%:%d lwp_rtt(lwp %p) but no RUPDATE_PENDING" + .string "locore.s:%d lwp_rtt(lwp %p) but no RUPDATE_PENDING" 1: #endif @@ -1668,228 +1585,58 @@ _no_pending_updates: movq REGOFF_RDX(%rsp), %rsi movq REGOFF_RAX(%rsp), %rdi call post_syscall /* post_syscall(rval1, rval2) */ - movq %cr0, %rax - orq $CR0_TS, %rax - movq %rax, %cr0 /* set up to take fault */ - /* on first use of fp */ + + /* + * set up to take fault on first use of fp + */ + STTS(%rdi) + + /* + * XXX - may want a fast path that avoids sys_rtt_common in the + * most common case. + */ ALTENTRY(_sys_rtt) - testw $CPL_MASK, REGOFF_CS(%rsp) /* test %cs for user mode return */ + CLI(%rax) /* disable interrupts */ + movq %rsp, %rdi /* pass rp to sys_rtt_common */ + call sys_rtt_common /* do common sys_rtt tasks */ + testq %rax, %rax /* returning to userland? */ jz sr_sup /* * Return to user */ + ASSERT_UPCALL_MASK_IS_SET cmpw $UCS_SEL, REGOFF_CS(%rsp) /* test for native (64-bit) lwp? */ je sys_rtt_syscall /* - * Return to 32-bit userland, checking for an AST, and (optionally) - * twerking any changing segment registers on the way out. + * Return to 32-bit userland */ ALTENTRY(sys_rtt_syscall32) - movq %gs:CPU_THREAD, %rax - cli /* disable interrupts */ - cmpb $0, T_ASTFLAG(%rax) /* test for signal or AST flag */ - jne _handle_ast - - movq T_LWP(%rax), %r14 - movl PCB_FLAGS(%r14), %edx - testl $RUPDATE_PENDING, %edx - jne _update_sregs - - /* - * The following label is branched to by sys_syscall32 handler - * so if iretq below #gp faults kern_gpfault can detect and - * handle it. - */ - ALTENTRY(_set_user32_regs) USER32_POP - iretq + IRET /*NOTREACHED*/ - + ALTENTRY(sys_rtt_syscall) /* - * Return to 64-bit userland, checking for an AST, and (optionally) - * twerking any changing segment registers on the way out. + * Return to 64-bit userland */ - ALTENTRY(sys_rtt_syscall) - movq %gs:CPU_THREAD, %rax - cli /* disable interrupts */ - cmpb $0, T_ASTFLAG(%rax) /* test for signal or AST flag */ - jne _handle_ast - - movq T_LWP(%rax), %r14 - movl PCB_FLAGS(%r14), %edx - testl $RUPDATE_PENDING, %edx - jne _update_sregs -_set_user_regs: USER_POP - iretq + IRET /*NOTREACHED*/ /* - * XX64 Don't understand why we ever come here. - * If we do come here then we can probably recover by just - * branching straight to _sys_rtt - */ -bad_set_user_regs: - leaq __bad_set_user_regs_msg(%rip), %rdi - movq %rsp, %rsi - movq REGOFF_CS(%rsp), %rdx - xorl %eax, %eax - call panic -__bad_set_user_regs_msg: - .string "bad_set_user_regs: rp=%lx rp->r_cs=%lx; how did that happen?" - - /* - * Update the segment registers with new values from the pcb - * - * We have to do this carefully, and in the following order, - * in case any of the selectors points at a bogus descriptor. - * If they do, we'll take a trap that will end in delivering - * the application a weird SIGSEGV via kern_gpfault(). - * - * This is particularly tricky for %gs. - * - * Note also the slightly brittle nature of the dependencies - * between this code and kern_gpfault(). - */ - ENTRY_NP(_update_sregs) - movw LWP_PCB_GS(%r14), %bx - movl $MSR_AMD_GSBASE, %ecx - rdmsr - movw %bx, %gs - /* - * If that instruction failed because the new %gs is a bad %gs, - * we'll be taking a trap but with the original %gs and %gsbase - * undamaged (i.e. pointing at curcpu). Otherwise, we've just - * mucked up the kernel's gsbase. Oops. Make the newly computed - * gsbase be the hidden gs, and fix the kernel's gsbase back again. - */ -#if defined(OPTERON_ERRATUM_88) - mfence -#endif - swapgs - wrmsr /* repair kernel gsbase */ - movw %bx, REGOFF_GS(%rsp) - /* - * Only override the descriptor base address if r_gs == LWPGS_SEL - * or if r_gs == NULL. - * - * A note on NULL descriptors -- 32-bit programs take faults if - * they deference NULL descriptors; however, when 64-bit programs - * load them into %fs or %gs, they DONT fault -- only the base - * address remains whatever it was from the last load. Urk. - * - * Avoid any leakage by setting the base address to an inaccessible - * region. - */ - cmpw $0, %bx - jne 0f - movl $0x80000000, LWP_PCB_GSBASE(%r14) - movl $0xffffffff, LWP_PCB_GSBASE+4(%r14) - jmp _set_gsbase -0: cmpw $LWPGS_SEL, %bx - jne 1f -_set_gsbase: - movl $MSR_AMD_KGSBASE, %ecx - movl LWP_PCB_GSBASE(%r14), %eax - movl LWP_PCB_GSBASE+4(%r14), %edx - wrmsr /* update hidden gsbase for userland */ - movl %eax, REGOFF_GSBASE(%rsp) - movl %edx, REGOFF_GSBASE+4(%rsp) -1: movw LWP_PCB_FS(%r14), %bx - movw %bx, %fs - movw %bx, REGOFF_FS(%rsp) - /* - * Only override the descriptor base address if r_fs == LWPFS_SEL - * or if r_fs == NULL. - */ - cmpw $0, %bx - jne 2f - movl $0x80000000, LWP_PCB_FSBASE(%r14) - movl $0xffffffff, LWP_PCB_FSBASE+4(%r14) - jmp _set_fsbase -2: cmpw $LWPFS_SEL, %bx - jne 3f -_set_fsbase: - movl $MSR_AMD_FSBASE, %ecx - movl LWP_PCB_FSBASE(%r14), %eax - movl LWP_PCB_FSBASE+4(%r14), %edx - wrmsr /* update fsbase for userland */ - movl %eax, REGOFF_FSBASE(%rsp) - movl %edx, REGOFF_FSBASE+4(%rsp) -3: - movw LWP_PCB_ES(%r14), %bx - movw %bx, %es - movw %bx, REGOFF_ES(%rsp) - movw LWP_PCB_DS(%r14), %bx - movw %bx, %ds - movw %bx, REGOFF_DS(%rsp) - andl $_BITNOT(RUPDATE_PENDING), PCB_FLAGS(%r14) - jmp _set_user_regs - .globl _update_sregs_done -_update_sregs_done: - /*NOTREACHED*/ - SET_SIZE(_update_sregs) - -_handle_ast: - /* Let trap() handle the AST */ - sti /* enable interrupts */ - movl $T_AST, REGOFF_TRAPNO(%rsp) /* set trap type to AST */ - movq %rsp, %rdi - xorl %esi, %esi - movl %gs:CPU_ID, %edx - call trap /* trap(rp, 0, cpuid) */ - jmp _sys_rtt - /*NOTREACHED*/ - - /* * Return to supervisor + * NOTE: to make the check in trap() that tests if we are executing + * segment register fixup/restore code work properly, sr_sup MUST be + * after _sys_rtt . */ ALTENTRY(sr_sup) - - /* Check for a kernel preemption request */ - cmpb $0, %gs:CPU_KPRUNRUN - jne sr_sup_preempt /* preemption */ - /* * Restore regs before doing iretq to kernel mode */ -set_sup_regs: - cmpw $KCS_SEL, REGOFF_CS(%rsp) /* test %cs for return to user mode */ - jne bad_set_user_regs /* ... (this should not be necessary) */ - - /* - * If we interrupted the mutex_exit() critical region we must - * reset the PC back to the beginning to prevent missed wakeups. - * See the comments in mutex_exit() for details. - */ - movq REGOFF_PC(%rsp), %rdx - leaq mutex_exit_critical_start(%rip), %r8 - subq %r8, %rdx - cmpq mutex_exit_critical_size(%rip), %rdx - jae .mutex_exit_check_done - movq %r8, REGOFF_PC(%rsp) - /* restart mutex_exit() */ -.mutex_exit_check_done: INTR_POP - iretq - -sr_sup_preempt: - movq %gs:CPU_THREAD, %rbx - cmpb $0, T_PREEMPT_LK(%rbx) /* Already in kpreempt? */ - jne set_sup_regs /* if so, get out of here */ - movb $1, T_PREEMPT_LK(%rbx) /* otherwise, set t_preempt_lk */ - - sti /* it's now safe to unmask interrupts */ - - movl $1, %edi /* indicate asynchronous call */ - call kpreempt /* kpreempt(1) */ - - cli /* re-mask interrupts */ - movb $0, T_PREEMPT_LK(%rbx) /* clear t_preempt_lk */ - - jmp set_sup_regs + IRET + /*NOTREACHED*/ SET_SIZE(sr_sup) SET_SIZE(lwp_rtt) SET_SIZE(lwp_rtt_initial) @@ -1929,94 +1676,42 @@ _lwp_rtt: pushl %eax call post_syscall /* post_syscall(rval1, rval2) */ addl $8, %esp - movl %cr0, %eax - orl $CR0_TS, %eax - movl %eax, %cr0 /* set up to take fault */ - /* on first use of fp */ + /* + * set up to take fault on first use of fp + */ + STTS(%eax) + + /* + * XXX - may want a fast path that avoids sys_rtt_common in the + * most common case. + */ ALTENTRY(_sys_rtt) - testw $CPL_MASK, REGOFF_CS(%esp) /* test CS for return to user mode */ + CLI(%eax) /* disable interrupts */ + pushl %esp /* pass rp to sys_rtt_common */ + call sys_rtt_common + addl $4, %esp /* pop arg */ + testl %eax, %eax /* test for return to user mode */ jz sr_sup /* * Return to User. */ - ALTENTRY(sys_rtt_syscall) - /* check for an AST that's posted to the lwp */ - movl %gs:CPU_THREAD, %eax - cli /* disable interrupts */ - cmpb $0, T_ASTFLAG(%eax) /* test for signal or AST flag */ - jne handle_ast - - - /* - * Restore user regs before returning to user mode. - */ - ALTENTRY(set_user_regs) INTR_POP_USER - iret - SET_SIZE(set_user_regs) - -handle_ast: - /* Let trap() handle the AST */ - sti /* enable interrupts */ - movl $T_AST, REGOFF_TRAPNO(%esp) /* set trap type to AST */ - movl %esp, %eax - pushl %gs:CPU_ID - pushl $0 - pushl %eax - call trap /* trap(rp, 0, cpuid) */ - addl $12, %esp - jmp _sys_rtt + IRET /* * Return to supervisor */ ALTENTRY(sr_sup) - /* Check for a kernel preemption request */ - cmpb $0, %gs:CPU_KPRUNRUN - jne sr_sup_preempt /* preemption */ - /* * Restore regs before doing iret to kernel mode */ -set_sup_regs: - cmpw $KGS_SEL, REGOFF_GS(%esp) /* test GS for return to user mode */ - jne set_user_regs /* ... (this should not be necessary) */ - - /* - * If we interrupted the mutex_exit() critical region we must - * reset the PC back to the beginning to prevent missed wakeups. - * See the comments in mutex_exit() for details. - */ - movl REGOFF_PC(%esp), %edx - subl $mutex_exit_critical_start, %edx - cmpl mutex_exit_critical_size, %edx - jae .mutex_exit_check_done - movl $mutex_exit_critical_start, REGOFF_PC(%esp) - /* restart mutex_exit() */ -.mutex_exit_check_done: INTR_POP_KERNEL - iret - -sr_sup_preempt: - movl %gs:CPU_THREAD, %ebx - cmpb $0, T_PREEMPT_LK(%ebx) /* Already in kpreempt? */ - jne set_sup_regs /* if so, get out of here */ - movb $1, T_PREEMPT_LK(%ebx) /* otherwise, set t_preempt_lk */ + IRET - sti /* it's now safe to unmask interrupts */ - - pushl $1 /* indicate asynchronous call */ - call kpreempt /* kpreempt(1) */ - addl $4, %esp - - cli /* re-mask interrupts */ - movb $0, T_PREEMPT_LK(%ebx) /* clear t_preempt_lk */ - - jmp set_sup_regs SET_SIZE(sr_sup) SET_SIZE(lwp_rtt) SET_SIZE(lwp_rtt_initial) @@ -2062,9 +1757,6 @@ freq_tsc(uint32_t *pit_counter) movq %rdi, %r9 /* save pit_counter */ pushq %rbx - pushfq - cli - / We have a TSC, but we have no way in general to know how reliable it is. / Usually a marginal TSC behaves appropriately unless not enough time / elapses between reads. A reliable TSC can be read as often and as rapidly @@ -2253,8 +1945,6 @@ freq_tsc_too_fast: freq_tsc_end: shlq $32, %rdx orq %rdx, %rax - / restore state of the interrupt flag - popfq popq %rbx leaveq @@ -2270,9 +1960,6 @@ freq_tsc_end: pushl %esi pushl %ebx - pushfl - cli - / We have a TSC, but we have no way in general to know how reliable it is. / Usually a marginal TSC behaves appropriately unless not enough time / elapses between reads. A reliable TSC can be read as often and as rapidly @@ -2460,14 +2147,10 @@ freq_tsc_too_fast: xorl %edx, %edx freq_tsc_end: - / restore state of the interrupt flag - popfl - popl %ebx popl %esi popl %edi popl %ebp - ret SET_SIZE(freq_tsc) @@ -2497,9 +2180,6 @@ freq_notsc(uint32_t *pit_counter) pushl %esi pushl %ebx - pushfl - cli - / initial count for the idivl loop movl $0x1000, %ecx @@ -2652,9 +2332,6 @@ freq_notsc_too_fast: xorl %edx, %edx freq_notsc_end: - / restore state of the interrupt flag - popfl - popl %ebx popl %esi popl %edi @@ -2663,128 +2340,6 @@ freq_notsc_end: ret SET_SIZE(freq_notsc) - / - / setup_121_andcall(funcp, argument) - / - / invokes funcp(argument) after having setup one to one mapping - / for the virtual address funcp to its physical address. - / This function cannot be invoked with PAE enabled, this could - / be used to enable PAE - / - ENTRY_NP(setup_121_andcall) - pushl %ebp - movl %esp, %ebp - pushl %ebx - movl 8(%ebp), %ecx / funcp - movl %ecx, %edx - shrl $MMU_STD_PAGESHIFT, %ecx - andl $MMU_L2_MASK, %ecx / pagetable index - movl %cr3, %eax - andl $MMU_STD_PAGEMASK, %eax / pagedirectory pointer - pushl %eax - shrl $MMU_STD_PAGESHIFT+NPTESHIFT, %edx - movl (%eax, %edx, 4), %eax / funcp's pagetable - testl $PTE_LARGEPAGE, %eax - je not_a_large_page - shrl $MMU_STD_PAGESHIFT, %eax - addl %eax, %ecx - movl %ecx, %edx - shll $MMU_STD_PAGESHIFT, %edx - orl $_CONST(PTE_SRWX|PTE_VALID), %edx - jmp got_pfn - -not_a_large_page: - andl $MMU_STD_PAGEMASK, %eax / ignore ref and other bits - movl (%eax, %ecx, 4), %ecx / pte entry - movl %ecx, %edx - shrl $MMU_STD_PAGESHIFT, %ecx /pfnum of funcp -got_pfn: - movl %ecx, %ebx - andl $MMU_L2_MASK, %ecx - shrl $NPTESHIFT, %ebx - movl 0(%esp), %eax - leal (%eax, %ebx, 4), %eax / new pde entry for the function - pushl %eax - movl (%eax), %eax - testl $PTE_VALID, %eax / is the pde entry valid - jne pagetable_isvalid - movl $one2one_pagetable, %ebx - addl $MMU_STD_PAGESIZE, %ebx / move to next 4k - shrl $MMU_STD_PAGESHIFT+NPTESHIFT, %ebx - movl 4(%esp), %eax - movl (%eax, %ebx, 4), %eax - testl $PTE_LARGEPAGE, %eax - je not_a_large_page1 - shrl $MMU_STD_PAGESHIFT, %eax - movl $one2one_pagetable, %ebx - addl $MMU_STD_PAGESIZE, %ebx / move to next 4k - shrl $MMU_STD_PAGESHIFT, %ebx - andl $MMU_L2_MASK, %ebx - addl %ebx, %eax - shll $MMU_STD_PAGESHIFT, %eax - orl $_CONST(PTE_SRWX|PTE_VALID), %eax - jmp got_pfn1 -not_a_large_page1: - andl $MMU_STD_PAGEMASK, %eax / ignore ref and other bits - movl $one2one_pagetable, %ebx - addl $MMU_STD_PAGESIZE, %ebx / move to next 4k - shrl $MMU_STD_PAGESHIFT, %ebx - andl $MMU_L2_MASK, %ebx - movl (%eax, %ebx, 4), %eax / pte entry for one2one_pagetable -got_pfn1: - movl 0(%esp), %ebx - movl %eax, (%ebx) / point pde entry at one2one_pagetable - movl $one2one_pagetable, %eax / load pagetable ptr - addl $MMU_STD_PAGESIZE, %eax / 4K aligned virtual address - andl $MMU_STD_PAGEMASK, %eax - movl $0, 4(%esp) / previous pde is invalid - jmp pagetable_madevalid -pagetable_isvalid: - movl %eax, 4(%esp) / save pde -pagetable_madevalid: - andl $MMU_STD_PAGEMASK, %eax / ignore lower 12 bits - - pushl (%eax, %ecx, 4) / save the old pagetable entry that - / belongs to boot - - movl %edx, (%eax, %ecx, 4) / We now have a 1-1 mapping for the - / function funcp - leal (%eax, %ecx, 4), %eax - pushl %eax / save the address of pagetable entry - / we patched above - - movl 8(%ebp), %eax / funcp - andl $MMU_PAGEOFFSET, %eax / pick the 4k offset - andl $MMU_STD_PAGEMASK, %edx - addl %edx, %eax - movl 12(%ebp), %ebx / argument - movl %cr3, %ecx - movl %ecx, %cr3 - call *%eax / jump to funcp(%eax) - / we have 1-1 mapping - / for this particular page, ret address - / still points to space in 0xe00xxxxx - - testl %eax, %eax - jne cr3_changed - popl %eax / pop the pagetable entry address - popl %ecx / pop the pagetable entry - movl %ecx, (%eax) / restore the pte that we destroyed - popl %eax / pop the pagedirectory address - popl %ecx / pop pde - movl %ecx, (%eax) / restore pde - movl %cr3, %eax - movl %eax, %cr3 - popl %ebx - popl %ebp - ret -cr3_changed: - addl $16, %esp / we had saved 4 arguments - popl %ebx - popl %ebp - ret - SET_SIZE(setup_121_andcall) - #endif /* __lint */ #endif /* !__amd64 */ @@ -2801,14 +2356,5 @@ cpu_vendor: .globl x86_type .globl x86_vendor #endif - .globl cr4_value - - /* - * pagetable that would allow a one to one mapping of the - * first 4K of kernel text. - * we allocate 8K so that we have a 4K pagetable aligned - * across 4K boundary - */ - .comm one2one_pagetable, 8192 #endif /* __lint */ diff --git a/usr/src/uts/i86pc/ml/mpcore.s b/usr/src/uts/i86pc/ml/mpcore.s index f1717a73f0..721761f01d 100644 --- a/usr/src/uts/i86pc/ml/mpcore.s +++ b/usr/src/uts/i86pc/ml/mpcore.s @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -29,6 +29,7 @@ #include <sys/asm_misc.h> #include <sys/regset.h> #include <sys/privregs.h> +#include <sys/x86_archext.h> #if !defined(__lint) #include <sys/segments.h> @@ -53,13 +54,13 @@ * */ -#if defined(lint) || defined(__lint) +#if defined(__lint) void real_mode_start(void) {} -#else /* lint */ +#else /* __lint */ #if defined(__amd64) @@ -299,10 +300,17 @@ kernel_cs_code: movq %rax, %cr0 /* set machine status word */ /* - * Before proceeding, enable usage of the page table NX bit if that's - * how the page tables are set up. + * Before going any further, enable usage of page table NX bit if + * that's how our page tables are set up. */ - call *set_nxe_func + movl x86_feature, %ecx + andl $X86_NX, %ecx + jz 1f + movl $MSR_AMD_EFER, %ecx + rdmsr + orl $AMD_EFER_NXE, %eax + wrmsr +1: /* * Complete the rest of the setup and call mp_startup(). @@ -546,10 +554,17 @@ kernel_cs_code: movq %rax, %cr0 /* set machine status word */ /* - * Before proceeding, enable usage of the page table NX bit if that's - * how the page tables are set up. + * Before going any further, enable usage of page table NX bit if + * that's how our page tables are set up. */ - call *set_nxe_func + movl x86_feature, %ecx + andl $X86_NX, %ecx + jz 1f + movl $MSR_AMD_EFER, %ecx + rdmsr + orl $AMD_EFER_NXE, %eax + wrmsr +1: /* * Complete the rest of the setup and call mp_startup(). @@ -643,7 +658,17 @@ kernel_cs_code: * Before going any further, enable usage of page table NX bit if * that's how our page tables are set up. */ - call *set_nxe_func + movl x86_feature, %ecx + andl $X86_NX, %ecx + jz 1f + movl %cr4, %ecx + andl $CR4_PAE, %ecx + jz 1f + movl $MSR_AMD_EFER, %ecx + rdmsr + orl $AMD_EFER_NXE, %eax + wrmsr +1: movl %gs:CPU_THREAD, %eax /* get thread ptr */ call *T_PC(%eax) /* call mp_startup */ /* not reached */ @@ -725,7 +750,17 @@ kernel_cs_code: * Before going any farther, enable usage of page table NX bit if * that's how our page tables are set up. */ - call *set_nxe_func + movl x86_feature, %ecx + andl $X86_NX, %ecx + jz 1f + movl %cr4, %ecx + andl $CR4_PAE, %ecx + jz 1f + movl $MSR_AMD_EFER, %ecx + rdmsr + orl $AMD_EFER_NXE, %eax + wrmsr +1: mov %gs:CPU_THREAD, %eax /* get thread ptr */ call *T_PC(%eax) /* call mp_startup */ /* not reached */ @@ -735,48 +770,4 @@ kernel_cs_code: SET_SIZE(real_mode_start) #endif /* __amd64 */ - -#endif /* lint */ - - -#if defined(lint) || defined(__lint) - -void -return_instr(void) -{} - -/*ARGSUSED*/ -void -send_dirint(int cpuix, int int_level) -{} - -#else /* lint */ - - /* - * Same for amd64 and i386. - */ - ENTRY_NP(return_instr) - rep; ret /* use 2 byte return instruction when branch target */ - /* AMD Software Optimization Guide - Section 6.2 */ - SET_SIZE(return_instr) - -#if defined(__amd64) - - /* - * jump indirect to the send_dirint - * function. Set to return if machine - * type module doesnt redirect it. - */ - ENTRY_NP(send_dirint) - jmp *send_dirintf(%rip) - SET_SIZE(send_dirint) - -#elif defined(__i386) - - ENTRY_NP(send_dirint) - jmp *send_dirintf - SET_SIZE(send_dirint) - -#endif /* __amd64 */ - -#endif /* lint */ +#endif /* __lint */ diff --git a/usr/src/uts/i86pc/ml/notes.s b/usr/src/uts/i86pc/ml/notes.s index 8212394028..72ae373813 100644 --- a/usr/src/uts/i86pc/ml/notes.s +++ b/usr/src/uts/i86pc/ml/notes.s @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,7 +18,7 @@ * * CDDL HEADER END * - * Copyright 2000 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -30,7 +29,8 @@ #if defined(lint) #include <sys/types.h> #else -#include <sys/mmu.h> + +#include "assym.h" / / Tell the booter that we'd like to load unix on a large page @@ -46,7 +46,7 @@ .name1_end: .align 4 .desc1_begin: - .4byte FOURMB_PAGESIZE + .4byte FOUR_MEG .desc1_end: .align 4 #endif diff --git a/usr/src/uts/i86pc/ml/offsets.in b/usr/src/uts/i86pc/ml/offsets.in index 2ed5b03b74..1c51a7c7d5 100644 --- a/usr/src/uts/i86pc/ml/offsets.in +++ b/usr/src/uts/i86pc/ml/offsets.in @@ -1,5 +1,5 @@ \ -\ Copyright 2006 Sun Microsystems, Inc. All rights reserved. +\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. \ Use is subject to license terms. \ \ CDDL HEADER START @@ -166,6 +166,7 @@ fpu_ctx fpu_flags FPU_CTX_FPU_FLAGS fxsave_state FXSAVE_STATE_SIZE + fx_fsw FXSAVE_STATE_FSW fx_mxcsr_mask FXSAVE_STATE_MXCSR_MASK @@ -290,10 +291,6 @@ rm_platter rm_cr4 CR4OFF rm_x86feature X86FEATURE -cpu_tables - ct_stack - ct_gdt - ddi_acc_impl ahi_acc_attr ACC_ATTR ahi_get8 ACC_GETB diff --git a/usr/src/uts/i86pc/ml/syscall_asm.s b/usr/src/uts/i86pc/ml/syscall_asm.s index 530cfcaf56..f43b9702d6 100644 --- a/usr/src/uts/i86pc/ml/syscall_asm.s +++ b/usr/src/uts/i86pc/ml/syscall_asm.s @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,6 +38,7 @@ #include <sys/psw.h> #include <sys/x86_archext.h> #include <sys/machbrand.h> +#include <sys/privregs.h> #if defined(__lint) @@ -383,20 +384,23 @@ size_t _allsyscalls_size; _watch_do_syscall: movl %esp, %ebp - pushl %eax / preserve across mstate call - MSTATE_TRANSITION(LMS_USER, LMS_SYSTEM) - popl %eax - + / Interrupts may be enabled here, so we must make sure this thread + / doesn't migrate off the CPU while it updates the CPU stats. + / + / XXX This is only true if we got here via call gate thru the LDT for + / old style syscalls. Perhaps this preempt++-- will go away soon? movl %gs:CPU_THREAD, %ebx - - / Interrupts are enabled here, so we must make sure this thread doesn't - / migrate off the CPU while it updates the CPU stats. addb $1, T_PREEMPT(%ebx) CPU_STATS_SYS_SYSCALL_INC subb $1, T_PREEMPT(%ebx) - / Set EFLAGS to standard kernel settings. ENABLE_INTR_FLAGS + + pushl %eax / preserve across mstate call + MSTATE_TRANSITION(LMS_USER, LMS_SYSTEM) + popl %eax + + movl %gs:CPU_THREAD, %ebx ASSERT_LWPTOREGS(%ebx, %esp) @@ -419,8 +423,8 @@ _syslcall_done: / / get back via iret / - cli - jmp set_user_regs + CLI(%edx) + jmp sys_rtt_syscall _full_syscall_presys: movl T_LWP(%ebx), %esi @@ -440,7 +444,7 @@ _full_syscall_postsys: call syscall_exit addl $12, %esp MSTATE_TRANSITION(LMS_SYSTEM, LMS_USER) - jmp sys_rtt_syscall + jmp _sys_rtt _syscall_fault: push $0xe / EFAULT @@ -729,6 +733,7 @@ watch_syscall(void) #else /* __lint */ ENTRY_NP(watch_syscall) + CLI(%eax) movl %gs:CPU_THREAD, %ebx movl T_STACK(%ebx), %esp / switch to the thread stack movl REGOFF_EAX(%esp), %eax / recover original syscall# diff --git a/usr/src/uts/i86pc/ml/syscall_asm_amd64.s b/usr/src/uts/i86pc/ml/syscall_asm_amd64.s index ce2f08f807..95f86bee20 100644 --- a/usr/src/uts/i86pc/ml/syscall_asm_amd64.s +++ b/usr/src/uts/i86pc/ml/syscall_asm_amd64.s @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -28,6 +28,7 @@ #include <sys/asm_linkage.h> #include <sys/asm_misc.h> #include <sys/regset.h> +#include <sys/privregs.h> #include <sys/psw.h> #include <sys/machbrand.h> @@ -354,12 +355,12 @@ size_t _allsyscalls_size; #else /* __lint */ ENTRY_NP2(brand_sys_syscall,_allsyscalls) - swapgs + SWAPGS BRAND_CALLBACK(BRAND_CB_SYSCALL) - swapgs + SWAPGS ALTENTRY(sys_syscall) - swapgs + SWAPGS movq %rsp, %gs:CPU_RTMP_RSP movq %r15, %gs:CPU_RTMP_R15 movq %gs:CPU_THREAD, %r15 @@ -428,7 +429,6 @@ size_t _allsyscalls_size; movq T_LWP(%r15), %r14 ASSERT_NO_RUPDATE_PENDING(%r14) - ENABLE_INTR_FLAGS MSTATE_TRANSITION(LMS_USER, LMS_SYSTEM) @@ -489,7 +489,7 @@ _syscall_invoke: * lwp got in ahead of us, it could change the segment * registers without us noticing before we return to userland. */ - cli + CLI(%r14) CHECK_POSTSYS_NE(%r15, %r14, %ebx) jne _syscall_post SIMPLE_SYSCALL_POSTSYS(%r15, %r14, %bx) @@ -524,7 +524,7 @@ _syscall_invoke: movq REGOFF_RIP(%rsp), %rcx movl REGOFF_RFL(%rsp), %r11d movq REGOFF_RSP(%rsp), %rsp - swapgs + SWAPGS sysretq _syscall_pre: @@ -545,7 +545,7 @@ _syscall_ill: jmp _syscall_post_call _syscall_post: - sti + STI /* * Sigh, our optimism wasn't justified, put it back to LMS_SYSTEM * so that we can account for the extra work it takes us to finish. @@ -556,7 +556,7 @@ _syscall_post_call: movq %r13, %rsi call post_syscall MSTATE_TRANSITION(LMS_SYSTEM, LMS_USER) - jmp sys_rtt_syscall + jmp _sys_rtt SET_SIZE(sys_syscall) SET_SIZE(brand_sys_syscall) @@ -572,12 +572,12 @@ sys_syscall32() #else /* __lint */ ENTRY_NP(brand_sys_syscall32) - swapgs + SWAPGS BRAND_CALLBACK(BRAND_CB_SYSCALL32) - swapgs + SWAPGS ALTENTRY(sys_syscall32) - swapgs + SWAPGS movl %esp, %r10d movq %gs:CPU_THREAD, %r15 movq T_STACK(%r15), %rsp @@ -590,7 +590,6 @@ sys_syscall32() movl $UDS_SEL, REGOFF_SS(%rsp) _syscall32_save: - movl %edi, REGOFF_RDI(%rsp) movl %esi, REGOFF_RSI(%rsp) movl %ebp, REGOFF_RBP(%rsp) @@ -711,7 +710,7 @@ _syscall32_save: * lwp got in ahead of us, it could change the segment * registers without us noticing before we return to userland. */ - cli + CLI(%r14) CHECK_POSTSYS_NE(%r15, %r14, %ebx) jne _full_syscall_postsys32 SIMPLE_SYSCALL_POSTSYS(%r15, %r14, %bx) @@ -738,7 +737,7 @@ _syscall32_save: sysretl _full_syscall_postsys32: - sti + STI /* * Sigh, our optimism wasn't justified, put it back to LMS_SYSTEM * so that we can account for the extra work it takes us to finish. @@ -749,7 +748,7 @@ _full_syscall_postsys32: movq %r13, %rdx /* rval2 - %edx */ call syscall_exit MSTATE_TRANSITION(LMS_SYSTEM, LMS_USER) - jmp sys_rtt_syscall32 + jmp _sys_rtt SET_SIZE(sys_syscall32) SET_SIZE(brand_sys_syscall32) @@ -805,7 +804,7 @@ sys_sysenter() #else /* __lint */ ENTRY_NP(brand_sys_sysenter) - swapgs + SWAPGS ALTENTRY(_brand_sys_sysenter_post_swapgs) BRAND_CALLBACK(BRAND_CB_SYSENTER) @@ -816,7 +815,7 @@ sys_sysenter() jmp _sys_sysenter_post_swapgs ALTENTRY(sys_sysenter) - swapgs + SWAPGS ALTENTRY(_sys_sysenter_post_swapgs) movq %gs:CPU_THREAD, %r15 @@ -1052,7 +1051,7 @@ sys_syscall_int() #else /* __lint */ ENTRY_NP(brand_sys_syscall_int) - swapgs + SWAPGS BRAND_CALLBACK(BRAND_CB_INT91) swapgs @@ -1067,6 +1066,7 @@ sys_syscall_int() * and use a faster return mechanism. */ movb $1, T_POST_SYS(%r15) + CLEAN_CS jmp _syscall32_save SET_SIZE(sys_syscall_int) SET_SIZE(brand_sys_syscall_int) @@ -1097,7 +1097,7 @@ sys_lcall32() #else /* __lint */ ENTRY_NP(sys_lcall32) - swapgs + SWAPGS pushq $0 pushq %rbp movq %rsp, %rbp diff --git a/usr/src/uts/i86pc/os/acpi_fw.h b/usr/src/uts/i86pc/os/acpi_fw.h new file mode 100644 index 0000000000..aead3dec37 --- /dev/null +++ b/usr/src/uts/i86pc/os/acpi_fw.h @@ -0,0 +1,148 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _ACPI_FW_H +#define _ACPI_FW_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +extern void process_acpi_properties(); + +#define ACPI_RSDP_SIG "RSD PTR " +#define ACPI_RSDP_SIG_LEN (8) +#define ACPI_TABLE_SIG_LEN (4) +#define ACPI_EBDA_SEG_ADDR (0x40e) +#define ACPI_EBDA_LEN (1024) + +#pragma pack(1) + +struct rsdp_v1 { + char sig[8]; + uint8_t checksum; + char oem_id[6]; + char revision; + uint32_t rsdt; +}; + +struct rsdp { + struct rsdp_v1 v1; + uint32_t len; + uint64_t xsdt; + uint8_t ext_checksum; + char reserved[3]; +}; + +struct table_header { + char sig[4]; + uint32_t len; + uint8_t revision; + uint8_t checksum; + char oem_id[6]; + char oem_table_id[8]; + uint32_t oem_revision; + uint32_t creator_id; + uint32_t creator_revision; +}; + +struct xsdt { + struct table_header hdr; + union { + uint32_t r[1]; + uint64_t x[1]; + } p; +}; + + +#define MADT_PROCESSOR 0 + +struct madt_processor { + uint8_t type; + uint8_t len; + uint8_t acpi_processor_id; + uint8_t apic_id; + uint32_t flags; +}; + +struct madt { + struct table_header hdr; + uint32_t lapic_addr; + uint32_t flags; + struct madt_processor list[1]; +}; + +struct srat_processor { + uint8_t domain1; + uint8_t apic_id; + uint32_t flags; + uint8_t local_sapic_eid; + uint8_t domain2[3]; + uint8_t reserved[4]; +}; + +struct srat_memory { + uint32_t domain; + uint8_t reserved1[2]; + uint64_t base_addr; + uint64_t len; + uint8_t reserved2[4]; + uint32_t flags; + uint8_t reserved3[8]; +}; + +struct srat_item { + uint8_t type; + uint8_t len; + union { + struct srat_processor p; + struct srat_memory m; + } i; +}; + +struct srat { + struct table_header hdr; + uint32_t reserved1; + uint8_t reserved2[8]; + struct srat_item list[1]; +}; + +#define SRAT_PROCESSOR (0) +#define SRAT_MEMORY (1) + +#define SRAT_ENABLED (1) +#define SRAT_HOT_PLUG (2) +#define SRAT_NON_VOLATILE (4) + + +#pragma pack() + +#ifdef __cplusplus +} +#endif + +#endif /* _ACPI_FW_H */ diff --git a/usr/src/uts/i86pc/os/cmi.c b/usr/src/uts/i86pc/os/cmi.c index fb1c494565..0e5129ebdc 100644 --- a/usr/src/uts/i86pc/os/cmi.c +++ b/usr/src/uts/i86pc/os/cmi.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -87,8 +87,8 @@ cmi_load_modctl(modctl_t *modp) } if ((ops = modlookup_by_modctl(modp, "_cmi_ops")) == NULL) { - cmn_err(CE_WARN, "CPU module %s is invalid: no _cmi_ops " - "found\n", modp->mod_modname); + cmn_err(CE_WARN, "cpu module '%s' is invalid: no _cmi_ops " + "found", modp->mod_modname); return (NULL); } @@ -197,8 +197,9 @@ cmi_load(cpu_t *cp) ((cmi = cmi_load_module(cp)) == NULL) || ((err = cmi->cmi_ops->cmi_init(cp, &data)) != 0 && err != ENOTSUP))) { - cmn_err(CE_WARN, "CPU module %s failed to init CPU %d: err=%d", - cmi ? cmi->cmi_modp->mod_modname : "<>", cp->cpu_id, err); + cmn_err(CE_WARN, + "cpu%d: failed to init cpu module '%s': err=%d", + cp->cpu_id, cmi ? cmi->cmi_modp->mod_modname : "<>", err); mutex_exit(&cmi_load_lock); return (-1); } @@ -206,8 +207,9 @@ cmi_load(cpu_t *cp) if ((cmi_force_generic || err != 0) && ((cmi = cmi_load_generic()) == NULL || (err = cmi->cmi_ops->cmi_init(cp, &data)) != 0)) { - cmn_err(CE_WARN, "CPU module %s failed to init CPU %d: err=%d", - cmi ? cmi->cmi_modp->mod_modname : "<>", cp->cpu_id, err); + cmn_err(CE_WARN, + "cpu%d: failed to init cpu module '%s': err=%d", + cp->cpu_id, cmi ? cmi->cmi_modp->mod_modname : "<>", err); mutex_exit(&cmi_load_lock); return (-1); } @@ -220,7 +222,7 @@ cmi_load(cpu_t *cp) mutex_exit(&cmi_load_lock); if (boothowto & RB_VERBOSE) { - printf("cpuid %d: initialized cpumod: %s\n", + printf("cpu%d: initialized cpu module '%s'\n", cp->cpu_id, cmi->cmi_modp->mod_modname); } @@ -231,7 +233,7 @@ void cmi_init(void) { if (cmi_load(CPU) < 0) - panic("failed to load module for CPU %u", CPU->cpu_id); + panic("failed to load module for cpu%d", CPU->cpu_id); } void diff --git a/usr/src/uts/i86pc/os/cpuid.c b/usr/src/uts/i86pc/os/cpuid.c index 094092ed0b..df93dde5e7 100644 --- a/usr/src/uts/i86pc/os/cpuid.c +++ b/usr/src/uts/i86pc/os/cpuid.c @@ -45,7 +45,6 @@ #include <sys/controlregs.h> #include <sys/auxv_386.h> #include <sys/bitmap.h> -#include <sys/controlregs.h> #include <sys/memnode.h> /* @@ -104,7 +103,6 @@ uint_t x86_feature = 0; uint_t x86_vendor = X86_VENDOR_IntelClone; uint_t x86_type = X86_TYPE_OTHER; -ulong_t cr4_value; uint_t pentiumpro_bug4046376; uint_t pentiumpro_bug4064495; @@ -158,12 +156,12 @@ struct cpuid_info { /* * supported feature information */ - uint32_t cpi_support[4]; + uint32_t cpi_support[5]; #define STD_EDX_FEATURES 0 #define AMD_EDX_FEATURES 1 #define TM_EDX_FEATURES 2 #define STD_ECX_FEATURES 3 - +#define AMD_ECX_FEATURES 4 /* * Synthesized information, where known. */ @@ -342,6 +340,14 @@ synth_info(struct cpuid_info *cpi) } /* + * Apply up various platform-dependent restrictions where the + * underlying platform restrictions mean the CPU can be marked + * as less capable than its cpuid instruction would imply. + */ + +#define platform_cpuid_mangle(vendor, eax, cp) /* nothing */ + +/* * Some undocumented ways of patching the results of the cpuid * instruction to permit running Solaris 10 on future cpus that * we don't currently support. Could be set to non-zero values @@ -353,6 +359,26 @@ uint32_t cpuid_feature_ecx_exclude; uint32_t cpuid_feature_edx_include; uint32_t cpuid_feature_edx_exclude; +void +cpuid_alloc_space(cpu_t *cpu) +{ + /* + * By convention, cpu0 is the boot cpu, which is set up + * before memory allocation is available. All other cpus get + * their cpuid_info struct allocated here. + */ + ASSERT(cpu->cpu_id != 0); + cpu->cpu_m.mcpu_cpi = + kmem_zalloc(sizeof (*cpu->cpu_m.mcpu_cpi), KM_SLEEP); +} + +void +cpuid_free_space(cpu_t *cpu) +{ + ASSERT(cpu->cpu_id != 0); + kmem_free(cpu->cpu_m.mcpu_cpi, sizeof (*cpu->cpu_m.mcpu_cpi)); +} + uint_t cpuid_pass1(cpu_t *cpu) { @@ -362,17 +388,14 @@ cpuid_pass1(cpu_t *cpu) struct cpuid_regs *cp; int xcpuid; + /* - * By convention, cpu0 is the boot cpu, which is called - * before memory allocation is available. Other cpus are - * initialized when memory becomes available. + * Space statically allocated for cpu0, ensure pointer is set */ if (cpu->cpu_id == 0) - cpu->cpu_m.mcpu_cpi = cpi = &cpuid_info0; - else - cpu->cpu_m.mcpu_cpi = cpi = - kmem_zalloc(sizeof (*cpi), KM_SLEEP); - + cpu->cpu_m.mcpu_cpi = &cpuid_info0; + cpi = cpu->cpu_m.mcpu_cpi; + ASSERT(cpi != NULL); cp = &cpi->cpi_std[0]; cp->cp_eax = 0; cpi->cpi_maxeax = __cpuid_insn(cp); @@ -615,13 +638,18 @@ cpuid_pass1(cpu_t *cpu) cp->cp_ecx &= mask_ecx; /* - * fold in fix ups + * apply any platform restrictions (we don't call this + * immediately after __cpuid_insn here, because we need the + * workarounds applied above first) */ + platform_cpuid_mangle(cpi->cpi_vendor, 1, cp); + /* + * fold in overrides from the "eeprom" mechanism + */ cp->cp_edx |= cpuid_feature_edx_include; cp->cp_edx &= ~cpuid_feature_edx_exclude; - cp->cp_ecx |= cpuid_feature_ecx_include; cp->cp_ecx &= ~cpuid_feature_ecx_exclude; @@ -646,10 +674,6 @@ cpuid_pass1(cpu_t *cpu) feature |= X86_PAE; if (cp->cp_edx & CPUID_INTC_EDX_CX8) feature |= X86_CX8; - /* - * Once this bit was thought questionable, but it looks like it's - * back, as of Application Note 485 March 2005 (24161829.pdf) - */ if (cp->cp_ecx & CPUID_INTC_ECX_CX16) feature |= X86_CX16; if (cp->cp_edx & CPUID_INTC_EDX_PAT) @@ -670,7 +694,7 @@ cpuid_pass1(cpu_t *cpu) feature |= X86_SSE3; } if (cp->cp_edx & CPUID_INTC_EDX_DE) - cr4_value |= CR4_DE; + feature |= X86_DE; if (feature & X86_PAE) cpi->cpi_pabits = 36; @@ -682,7 +706,7 @@ cpuid_pass1(cpu_t *cpu) * (AMD chose to set the HTT bit on their CMP processors, * even though they're not actually hyperthreaded. Thus it * takes a bit more work to figure out what's really going - * on ... see the handling of the CMP_LEGACY bit below) + * on ... see the handling of the CMP_LGCY bit below) */ if (cp->cp_edx & CPUID_INTC_EDX_HTT) { cpi->cpi_ncpu_per_chip = CPI_CPU_COUNT(cpi); @@ -742,6 +766,7 @@ cpuid_pass1(cpu_t *cpu) cp = &cpi->cpi_extd[1]; cp->cp_eax = 0x80000001; (void) __cpuid_insn(cp); + if (cpi->cpi_vendor == X86_VENDOR_AMD && cpi->cpi_family == 5 && cpi->cpi_model == 6 && @@ -756,6 +781,8 @@ cpuid_pass1(cpu_t *cpu) } } + platform_cpuid_mangle(cpi->cpi_vendor, 0x80000001, cp); + /* * Compute the additions to the kernel's feature word. */ @@ -763,17 +790,17 @@ cpuid_pass1(cpu_t *cpu) feature |= X86_NX; /* - * If both the HTT and CMP_LEGACY bits are set, + * If both the HTT and CMP_LGCY bits are set, * then we're not actually HyperThreaded. Read * "AMD CPUID Specification" for more details. */ if (cpi->cpi_vendor == X86_VENDOR_AMD && (feature & X86_HTT) && - (cp->cp_ecx & CPUID_AMD_ECX_CMP_LEGACY)) { + (cp->cp_ecx & CPUID_AMD_ECX_CMP_LGCY)) { feature &= ~X86_HTT; feature |= X86_CMP; } -#if defined(_LP64) +#if defined(__amd64) /* * It's really tricky to support syscall/sysret in * the i386 kernel; we rely on sysenter/sysexit @@ -791,6 +818,8 @@ cpuid_pass1(cpu_t *cpu) if (x86_vendor == X86_VENDOR_AMD) feature &= ~X86_SEP; #endif + if (cp->cp_edx & CPUID_AMD_EDX_TSCP) + feature |= X86_TSCP; break; default: break; @@ -806,6 +835,7 @@ cpuid_pass1(cpu_t *cpu) cp->cp_eax = 4; cp->cp_ecx = 0; (void) __cpuid_insn(cp); + platform_cpuid_mangle(cpi->cpi_vendor, 4, cp); } /*FALLTHROUGH*/ case X86_VENDOR_AMD: @@ -814,6 +844,8 @@ cpuid_pass1(cpu_t *cpu) cp = &cpi->cpi_extd[8]; cp->cp_eax = 0x80000008; (void) __cpuid_insn(cp); + platform_cpuid_mangle(cpi->cpi_vendor, 0x80000008, cp); + /* * Virtual and physical address limits from * cpuid override previously guessed values. @@ -848,7 +880,6 @@ cpuid_pass1(cpu_t *cpu) cpi->cpi_ncore_per_chip = 1; break; } - } /* @@ -856,6 +887,7 @@ cpuid_pass1(cpu_t *cpu) */ if (cpi->cpi_ncore_per_chip > 1) feature |= X86_CMP; + /* * If the number of cores is the same as the number * of CPUs, then we cannot have HyperThreading. @@ -980,6 +1012,7 @@ cpuid_pass2(cpu_t *cpu) for (n = 2, cp = &cpi->cpi_std[2]; n < nmax; n++, cp++) { cp->cp_eax = n; (void) __cpuid_insn(cp); + platform_cpuid_mangle(cpi->cpi_vendor, n, cp); switch (n) { case 2: /* @@ -1052,6 +1085,7 @@ cpuid_pass2(cpu_t *cpu) for (n = 2, cp = &cpi->cpi_extd[2]; n < nmax; cp++, n++) { cp->cp_eax = 0x80000000 + n; (void) __cpuid_insn(cp); + platform_cpuid_mangle(cpi->cpi_vendor, 0x80000000 + n, cp); switch (n) { case 2: case 3: @@ -1641,10 +1675,8 @@ cpuid_pass4(cpu_t *cpu) hwcap_flags |= AV_386_CMOV; if (*ecx & CPUID_INTC_ECX_MON) hwcap_flags |= AV_386_MON; -#if defined(CPUID_INTC_ECX_CX16) if (*ecx & CPUID_INTC_ECX_CX16) hwcap_flags |= AV_386_CX16; -#endif } if (x86_feature & X86_HTT) @@ -1655,13 +1687,39 @@ cpuid_pass4(cpu_t *cpu) switch (cpi->cpi_vendor) { struct cpuid_regs cp; - uint32_t *edx; + uint32_t *edx, *ecx; + + case X86_VENDOR_Intel: + /* + * Seems like Intel duplicated what we necessary + * here to make the initial crop of 64-bit OS's work. + * Hopefully, those are the only "extended" bits + * they'll add. + */ + /*FALLTHROUGH*/ - case X86_VENDOR_Intel: /* sigh */ case X86_VENDOR_AMD: edx = &cpi->cpi_support[AMD_EDX_FEATURES]; + ecx = &cpi->cpi_support[AMD_ECX_FEATURES]; *edx = CPI_FEATURES_XTD_EDX(cpi); + *ecx = CPI_FEATURES_XTD_ECX(cpi); + + /* + * [these features require explicit kernel support] + */ + switch (cpi->cpi_vendor) { + case X86_VENDOR_Intel: + break; + + case X86_VENDOR_AMD: + if ((x86_feature & X86_TSCP) == 0) + *edx &= ~CPUID_AMD_EDX_TSCP; + break; + + default: + break; + } /* * [no explicit support required beyond @@ -1671,25 +1729,46 @@ cpuid_pass4(cpu_t *cpu) *edx &= ~(CPUID_AMD_EDX_MMXamd | CPUID_AMD_EDX_3DNow | CPUID_AMD_EDX_3DNowx); - if ((x86_feature & X86_ASYSC) == 0) - *edx &= ~CPUID_AMD_EDX_SYSC; if ((x86_feature & X86_NX) == 0) *edx &= ~CPUID_AMD_EDX_NX; -#if !defined(_LP64) +#if !defined(__amd64) *edx &= ~CPUID_AMD_EDX_LM; #endif /* * Now map the supported feature vector to * things that we think userland will care about. */ +#if defined(__amd64) if (*edx & CPUID_AMD_EDX_SYSC) hwcap_flags |= AV_386_AMD_SYSC; +#endif if (*edx & CPUID_AMD_EDX_MMXamd) hwcap_flags |= AV_386_AMD_MMX; if (*edx & CPUID_AMD_EDX_3DNow) hwcap_flags |= AV_386_AMD_3DNow; if (*edx & CPUID_AMD_EDX_3DNowx) hwcap_flags |= AV_386_AMD_3DNowx; + + switch (cpi->cpi_vendor) { + case X86_VENDOR_AMD: + if (*edx & CPUID_AMD_EDX_TSCP) + hwcap_flags |= AV_386_TSCP; + if (*ecx & CPUID_AMD_ECX_AHF64) + hwcap_flags |= AV_386_AHF; + break; + + case X86_VENDOR_Intel: + /* + * Aarrgh. + * Intel uses a different bit in the same word. + */ + if (*ecx & CPUID_INTC_ECX_AHF64) + hwcap_flags |= AV_386_AHF; + break; + + default: + break; + } break; case X86_VENDOR_TM: @@ -1790,8 +1869,18 @@ cpuid_syscall32_insn(cpu_t *cpu) { ASSERT(cpuid_checkpass((cpu == NULL ? CPU : cpu), 1)); - if (x86_feature & X86_ASYSC) - return (x86_vendor != X86_VENDOR_Intel); + if (cpu == NULL) + cpu = CPU; + + /*CSTYLED*/ + { + struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi; + + if (cpi->cpi_vendor == X86_VENDOR_AMD && + cpi->cpi_xmaxeax >= 0x80000001 && + (CPI_FEATURES_XTD_EDX(cpi) & CPUID_AMD_EDX_SYSC)) + return (1); + } return (0); } @@ -2226,6 +2315,7 @@ add_cache_prop(dev_info_t *devi, const char *label, const char *type, static const char l1_icache_str[] = "l1-icache"; static const char l1_dcache_str[] = "l1-dcache"; static const char l2_cache_str[] = "l2-cache"; +static const char l3_cache_str[] = "l3-cache"; static const char itlb4k_str[] = "itlb-4K"; static const char dtlb4k_str[] = "dtlb-4K"; static const char itlb4M_str[] = "itlb-4M"; @@ -2245,6 +2335,7 @@ static const struct cachetab { const char *ct_label; } intel_ctab[] = { /* maintain descending order! */ + { 0xb4, 4, 0, 256, dtlb4k_str }, { 0xb3, 4, 0, 128, dtlb4k_str }, { 0xb0, 4, 0, 128, itlb4k_str }, { 0x87, 8, 64, 1024*1024, l2_cache_str}, @@ -2253,7 +2344,6 @@ static const struct cachetab { { 0x84, 8, 32, 1024*1024, l2_cache_str}, { 0x83, 8, 32, 512*1024, l2_cache_str}, { 0x82, 8, 32, 256*1024, l2_cache_str}, - { 0x81, 8, 32, 128*1024, l2_cache_str}, /* suspect! */ { 0x7f, 2, 64, 512*1024, l2_cache_str}, { 0x7d, 8, 64, 2*1024*1024, sl2_cache_str}, { 0x7c, 8, 64, 1024*1024, sl2_cache_str}, @@ -2261,6 +2351,7 @@ static const struct cachetab { { 0x7a, 8, 64, 256*1024, sl2_cache_str}, { 0x79, 8, 64, 128*1024, sl2_cache_str}, { 0x78, 8, 64, 1024*1024, l2_cache_str}, + { 0x73, 8, 0, 64*1024, itrace_str}, { 0x72, 8, 0, 32*1024, itrace_str}, { 0x71, 8, 0, 16*1024, itrace_str}, { 0x70, 8, 0, 12*1024, itrace_str}, @@ -2274,13 +2365,23 @@ static const struct cachetab { { 0x52, 0, 0, 256, itlb424_str}, { 0x51, 0, 0, 128, itlb424_str}, { 0x50, 0, 0, 64, itlb424_str}, + { 0x4d, 16, 64, 16*1024*1024, l3_cache_str}, + { 0x4c, 12, 64, 12*1024*1024, l3_cache_str}, + { 0x4b, 16, 64, 8*1024*1024, l3_cache_str}, + { 0x4a, 12, 64, 6*1024*1024, l3_cache_str}, + { 0x49, 16, 64, 4*1024*1024, l3_cache_str}, + { 0x47, 8, 64, 8*1024*1024, l3_cache_str}, + { 0x46, 4, 64, 4*1024*1024, l3_cache_str}, { 0x45, 4, 32, 2*1024*1024, l2_cache_str}, { 0x44, 4, 32, 1024*1024, l2_cache_str}, { 0x43, 4, 32, 512*1024, l2_cache_str}, { 0x42, 4, 32, 256*1024, l2_cache_str}, { 0x41, 4, 32, 128*1024, l2_cache_str}, + { 0x3e, 4, 64, 512*1024, sl2_cache_str}, + { 0x3d, 6, 64, 384*1024, sl2_cache_str}, { 0x3c, 4, 64, 256*1024, sl2_cache_str}, { 0x3b, 2, 64, 128*1024, sl2_cache_str}, + { 0x3a, 6, 64, 192*1024, sl2_cache_str}, { 0x39, 4, 64, 128*1024, sl2_cache_str}, { 0x30, 8, 64, 32*1024, l1_icache_str}, { 0x2c, 8, 64, 32*1024, l1_dcache_str}, @@ -2289,6 +2390,7 @@ static const struct cachetab { { 0x23, 8, 64, 1024*1024, sl3_cache_str}, { 0x22, 4, 64, 512*1024, sl3_cache_str}, { 0x0c, 4, 32, 16*1024, l1_dcache_str}, + { 0x0b, 4, 0, 4, itlb4M_str}, { 0x0a, 2, 32, 8*1024, l1_dcache_str}, { 0x08, 4, 32, 16*1024, l1_icache_str}, { 0x06, 4, 32, 8*1024, l1_icache_str}, diff --git a/usr/src/uts/i86pc/os/dtrace_subr.c b/usr/src/uts/i86pc/os/dtrace_subr.c index 00da457012..7e369be269 100644 --- a/usr/src/uts/i86pc/os/dtrace_subr.c +++ b/usr/src/uts/i86pc/os/dtrace_subr.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -373,3 +373,13 @@ dtrace_safe_defer_signal(void) return (1); } + +/* + * Additional artificial frames for the machine type. For i86pc, we're already + * accounted for, so return 0. + */ +int +dtrace_mach_aframes(void) +{ + return (0); +} diff --git a/usr/src/uts/i86pc/os/fakebop.c b/usr/src/uts/i86pc/os/fakebop.c new file mode 100644 index 0000000000..06b308e6e6 --- /dev/null +++ b/usr/src/uts/i86pc/os/fakebop.c @@ -0,0 +1,1503 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * This file contains the functionality that mimics the boot operations + * on SPARC systems or the old boot.bin/multiboot programs on x86 systems. + * The x86 kernel now does everything on its own. + */ + +#include <sys/types.h> +#include <sys/bootconf.h> +#include <sys/bootsvcs.h> +#include <sys/bootinfo.h> +#include <sys/multiboot.h> +#include <sys/bootvfs.h> +#include <sys/bootprops.h> +#include <sys/varargs.h> +#include <sys/param.h> +#include <sys/machparam.h> +#include <sys/archsystm.h> +#include <sys/boot_console.h> +#include <sys/cmn_err.h> +#include <sys/systm.h> +#include <sys/promif.h> +#include <sys/archsystm.h> +#include <sys/x86_archext.h> +#include <sys/kobj.h> +#include <sys/privregs.h> +#include <sys/sysmacros.h> +#include <sys/ctype.h> +#include <vm/kboot_mmu.h> +#include <vm/hat_pte.h> +#include "acpi_fw.h" + +static int have_console = 0; /* set once primitive console is initialized */ +static char *boot_args = ""; + +/* + * Debugging macros + */ +static uint_t kbm_debug = 0; +#define DBG_MSG(s) { if (kbm_debug) bop_printf(NULL, "%s", s); } +#define DBG(x) { if (kbm_debug) \ + bop_printf(NULL, "%s is %" PRIx64 "\n", #x, (uint64_t)(x)); \ + } + +#define PUT_STRING(s) { \ + char *cp; \ + for (cp = (s); *cp; ++cp) \ + bcons_putchar(*cp); \ + } + +struct xboot_info *xbootp; /* boot info from "glue" code in low memory */ +bootops_t bootop; /* simple bootops we'll pass on to kernel */ +struct bsys_mem bm; + +static uintptr_t next_virt; /* next available virtual address */ +static paddr_t next_phys; /* next available physical address from dboot */ +static paddr_t high_phys = -(paddr_t)1; /* last used physical address */ + +/* + * buffer for vsnprintf for console I/O + */ +#define BUFFERSIZE 256 +static char buffer[BUFFERSIZE]; +/* + * stuff to store/report/manipulate boot property settings. + */ +typedef struct bootprop { + struct bootprop *bp_next; + char *bp_name; + uint_t bp_vlen; + char *bp_value; +} bootprop_t; + +static bootprop_t *bprops = NULL; +static char *curr_page = NULL; /* ptr to avail bprop memory */ +static int curr_space = 0; /* amount of memory at curr_page */ + +/* + * some allocator statistics + */ +static ulong_t total_bop_alloc_scratch = 0; +static ulong_t total_bop_alloc_kernel = 0; + +static void build_firmware_properties(void); + +/* + * Allocate aligned physical memory at boot time. This allocator allocates + * from the highest possible addresses. This avoids exhausting memory that + * would be useful for DMA buffers. + */ +paddr_t +do_bop_phys_alloc(uint64_t size, uint64_t align) +{ + paddr_t pa = 0; + paddr_t start; + paddr_t end; + struct memlist *ml = (struct memlist *)xbootp->bi_phys_install; + + /* + * Be careful if high memory usage is limited in startup.c + * Since there are holes in the low part of the physical address + * space we can treat physmem as a pfn (not just a pgcnt) and + * get a conservative upper limit. + */ + extern pgcnt_t physmem; + if (physmem != 0 && high_phys > pfn_to_pa(physmem)) + high_phys = pfn_to_pa(physmem); + + /* + * find the highest available memory in physinstalled + */ + size = P2ROUNDUP(size, align); + for (; ml; ml = ml->next) { + start = ml->address; + end = P2ALIGN(start + ml->size, align); + if (start < next_phys) + start = next_phys; + if (end > high_phys) + end = P2ALIGN(high_phys, align); + + if (end <= start) + continue; + if (end - start < size) + continue; + + if (end - size > pa) + pa = end - size; + } + if (pa != 0) { + high_phys = pa; + return (pa); + } + panic("do_bop_phys_alloc(0x%" PRIx64 ", 0x%" PRIx64 ") Out of memory\n", + size, align); + /*NOTREACHED*/ +} + +static uintptr_t +alloc_vaddr(size_t size, paddr_t align) +{ + uintptr_t rv; + + next_virt = P2ROUNDUP(next_virt, (uintptr_t)align); + rv = (uintptr_t)next_virt; + next_virt += size; + return (rv); +} + +/* + * Allocate virtual memory. The size is always rounded up to a multiple + * of base pagesize. + */ + +/*ARGSUSED*/ +static caddr_t +do_bsys_alloc(bootops_t *bop, caddr_t virthint, size_t size, int align) +{ + paddr_t a = align; /* same type as pa for masking */ + uint_t pgsize; + paddr_t pa; + uintptr_t va; + ssize_t s; /* the aligned size */ + uint_t level; + uint_t is_kernel = (virthint != 0); + + if (a < MMU_PAGESIZE) + a = MMU_PAGESIZE; + else if (!ISP2(a)) + prom_panic("do_bsys_alloc() incorrect alignment"); + size = P2ROUNDUP(size, MMU_PAGESIZE); + + /* + * Use the next aligned virtual address if we weren't given one. + */ + if (virthint == NULL) { + virthint = (caddr_t)alloc_vaddr(size, a); + total_bop_alloc_scratch += size; + } else { + total_bop_alloc_kernel += size; + } + + /* + * allocate the physical memory + */ + pa = do_bop_phys_alloc(size, a); + + /* + * Add the mappings to the page tables, try large pages first. + */ + va = (uintptr_t)virthint; + s = size; + level = 1; + pgsize = xbootp->bi_use_pae ? TWO_MEG : FOUR_MEG; + if (xbootp->bi_use_largepage && a == pgsize) { + while (IS_P2ALIGNED(pa, pgsize) && IS_P2ALIGNED(va, pgsize) && + s >= pgsize) { + kbm_map(va, pa, level, is_kernel); + va += pgsize; + pa += pgsize; + s -= pgsize; + } + } + + /* + * Map remaining pages use small mappings + */ + level = 0; + pgsize = MMU_PAGESIZE; + while (s > 0) { + kbm_map(va, pa, level, is_kernel); + va += pgsize; + pa += pgsize; + s -= pgsize; + } + return (virthint); +} + +/* + * Free virtual memory - we'll just ignore these. + */ +/*ARGSUSED*/ +static void +do_bsys_free(bootops_t *bop, caddr_t virt, size_t size) +{ + bop_printf(NULL, "do_bsys_free(virt=0x%p, size=0x%lx) ignored\n", + (void *)virt, size); +} + +/* + * Old interface + */ +/*ARGSUSED*/ +static caddr_t +do_bsys_ealloc( + bootops_t *bop, + caddr_t virthint, + size_t size, + int align, + int flags) +{ + prom_panic("unsupported call to BOP_EALLOC()\n"); + return (0); +} + + +static void +bsetprop(char *name, int nlen, void *value, int vlen) +{ + uint_t size; + uint_t need_size; + bootprop_t *b; + + /* + * align the size to 16 byte boundary + */ + size = sizeof (bootprop_t) + nlen + 1 + vlen; + size = (size + 0xf) & ~0xf; + if (size > curr_space) { + need_size = (size + (MMU_PAGEOFFSET)) & MMU_PAGEMASK; + curr_page = do_bsys_alloc(NULL, 0, need_size, MMU_PAGESIZE); + curr_space = need_size; + } + + /* + * use a bootprop_t at curr_page and link into list + */ + b = (bootprop_t *)curr_page; + curr_page += sizeof (bootprop_t); + curr_space -= sizeof (bootprop_t); + b->bp_next = bprops; + bprops = b; + + /* + * follow by name and ending zero byte + */ + b->bp_name = curr_page; + bcopy(name, curr_page, nlen); + curr_page += nlen; + *curr_page++ = 0; + curr_space -= nlen + 1; + + /* + * copy in value, but no ending zero byte + */ + b->bp_value = curr_page; + b->bp_vlen = vlen; + if (vlen > 0) { + bcopy(value, curr_page, vlen); + curr_page += vlen; + curr_space -= vlen; + } + + /* + * align new values of curr_page, curr_space + */ + while (curr_space & 0xf) { + ++curr_page; + --curr_space; + } +} + +static void +bsetprops(char *name, char *value) +{ + bsetprop(name, strlen(name), value, strlen(value) + 1); +} + +static void +bsetprop64(char *name, uint64_t value) +{ + bsetprop(name, strlen(name), (void *)&value, sizeof (value)); +} + +static void +bsetpropsi(char *name, int value) +{ + char prop_val[32]; + + (void) snprintf(prop_val, sizeof (prop_val), "%d", value); + bsetprops(name, prop_val); +} + +/* + * to find the size of the buffer to allocate + */ +/*ARGSUSED*/ +static int +do_bsys_getproplen(bootops_t *bop, char *name) +{ + bootprop_t *b; + + for (b = bprops; b; b = b->bp_next) { + if (strcmp(name, b->bp_name) != 0) + continue; + return (b->bp_vlen); + } + return (-1); +} + +/* + * get the value associated with this name + */ +/*ARGSUSED*/ +static int +do_bsys_getprop(bootops_t *bop, char *name, void *value) +{ + bootprop_t *b; + + for (b = bprops; b; b = b->bp_next) { + if (strcmp(name, b->bp_name) != 0) + continue; + bcopy(b->bp_value, value, b->bp_vlen); + return (0); + } + return (-1); +} + +/* + * get the name of the next property in succession from the standalone + */ +/*ARGSUSED*/ +static char * +do_bsys_nextprop(bootops_t *bop, char *name) +{ + bootprop_t *b; + + /* + * A null name is a special signal for the 1st boot property + */ + if (name == NULL || strlen(name) == 0) { + if (bprops == NULL) + return (NULL); + return (bprops->bp_name); + } + + for (b = bprops; b; b = b->bp_next) { + if (name != b->bp_name) + continue; + b = b->bp_next; + if (b == NULL) + return (NULL); + return (b->bp_name); + } + return (NULL); +} + +/* + * 2nd part of building the table of boot properties. This includes: + * - values from /boot/solaris/bootenv.rc (ie. eeprom(1m) values) + * + * lines look like one of: + * ^$ + * ^# comment till end of line + * setprop name 'value' + * setprop name value + * setprop name "value" + * + * we do single character I/O since this is really just looking at memory + */ +void +boot_prop_finish(void) +{ + int fd; + char *line; + int c; + int bytes_read; + char *name; + int n_len; + char *value; + int v_len; + char *inputdev; /* these override the comand line if serial ports */ + char *outputdev; + char *consoledev; + + DBG_MSG("Opening /boot/solaris/bootenv.rc\n"); + fd = BRD_OPEN(bfs_ops, "/boot/solaris/bootenv.rc", 0); + DBG(fd); + + line = do_bsys_alloc(NULL, NULL, MMU_PAGESIZE, MMU_PAGESIZE); + while (fd >= 0) { + + /* + * get a line + */ + for (c = 0; ; ++c) { + bytes_read = BRD_READ(bfs_ops, fd, line + c, 1); + if (bytes_read == 0) { + if (c == 0) + goto done; + break; + } + if (line[c] == '\n') + break; + } + line[c] = 0; + + /* + * ignore comment lines + */ + c = 0; + while (ISSPACE(line[c])) + ++c; + if (line[c] == '#' || line[c] == 0) + continue; + + /* + * must have "setprop " or "setprop\t" + */ + if (strncmp(line + c, "setprop ", 8) != 0 && + strncmp(line + c, "setprop\t", 8) != 0) + continue; + c += 8; + while (ISSPACE(line[c])) + ++c; + if (line[c] == 0) + continue; + + /* + * gather up the property name + */ + name = line + c; + n_len = 0; + while (line[c] && !ISSPACE(line[c])) + ++n_len, ++c; + + /* + * gather up the value, if any + */ + value = ""; + v_len = 0; + while (ISSPACE(line[c])) + ++c; + if (line[c] != 0) { + value = line + c; + while (line[c] && !ISSPACE(line[c])) + ++v_len, ++c; + } + + if (v_len >= 2 && value[0] == value[v_len - 1] && + (value[0] == '\'' || value[0] == '"')) { + ++value; + v_len -= 2; + } + name[n_len] = 0; + if (v_len > 0) + value[v_len] = 0; + else + continue; + + /* + * ignore "boot-file" property, it's now meaningless + */ + if (strcmp(name, "boot-file") == 0) + continue; + if (strcmp(name, "boot-args") == 0 && + strlen(boot_args) > 0) + continue; + + /* + * If console was explicitly set on the command line it will + * override a setting in bootenv.rc + */ + if (strcmp(name, "console") == 0 && + do_bsys_getproplen(NULL, "console") > 0) + continue; + + bsetprop(name, n_len, value, v_len + 1); + } +done: + if (fd >= 0) + BRD_CLOSE(bfs_ops, fd); + + /* + * check to see if we have to override the default value of the console + */ + inputdev = line; + v_len = do_bsys_getproplen(NULL, "input-device"); + if (v_len > 0) + (void) do_bsys_getprop(NULL, "input-device", inputdev); + else + v_len = 0; + inputdev[v_len] = 0; + + outputdev = inputdev + v_len + 1; + v_len = do_bsys_getproplen(NULL, "output-device"); + if (v_len > 0) + (void) do_bsys_getprop(NULL, "output-device", outputdev); + else + v_len = 0; + outputdev[v_len] = 0; + + consoledev = outputdev + v_len + 1; + v_len = do_bsys_getproplen(NULL, "console"); + if (v_len > 0) + (void) do_bsys_getprop(NULL, "console", consoledev); + else + v_len = 0; + consoledev[v_len] = 0; + bcons_init2(inputdev, outputdev, consoledev); + + if (strstr((char *)xbootp->bi_cmdline, "prom_debug") || kbm_debug) { + value = line; + bop_printf(NULL, "\nBoot properties:\n"); + name = ""; + while ((name = do_bsys_nextprop(NULL, name)) != NULL) { + bop_printf(NULL, "\t0x%p %s = ", (void *)name, name); + (void) do_bsys_getprop(NULL, name, value); + v_len = do_bsys_getproplen(NULL, name); + bop_printf(NULL, "len=%d ", v_len); + value[v_len] = 0; + bop_printf(NULL, "%s\n", value); + } + } +} + +/* + * print formatted output + */ +/*PRINTFLIKE2*/ +/*ARGSUSED*/ +void +bop_printf(bootops_t *bop, char *fmt, ...) +{ + va_list ap; + + if (have_console == 0) + return; + + va_start(ap, fmt); + (void) vsnprintf(buffer, BUFFERSIZE, fmt, ap); + va_end(ap); + PUT_STRING(buffer); +} + +/* + * Another panic() variant; this one can be used even earlier during boot than + * prom_panic(). + */ +/*PRINTFLIKE1*/ +void +bop_panic(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + bop_printf(NULL, fmt, ap); + va_end(ap); + + bop_printf(NULL, "\nPress any key to reboot.\n"); + (void) bcons_getchar(); + bop_printf(NULL, "Resetting...\n"); + reset(); +} + +/* + * Do a real mode interrupt BIOS call + */ +typedef struct bios_regs { + unsigned short ax, bx, cx, dx, si, di, bp, es, ds; +} bios_regs_t; +typedef int (*bios_func_t)(int, bios_regs_t *); + +/*ARGSUSED*/ +static void +do_bsys_doint(bootops_t *bop, int intnum, struct bop_regs *rp) +{ + static int firsttime = 1; + bios_func_t bios_func = (bios_func_t)(void *)(uintptr_t)0x5000; + bios_regs_t br; + + /* + * The first time we do this, we have to copy the pre-packaged + * low memory bios call code image into place. + */ + if (firsttime) { + extern char bios_image[]; + extern uint32_t bios_size; + + bcopy(bios_image, (void *)bios_func, bios_size); + firsttime = 0; + } + + br.ax = rp->eax.word.ax; + br.bx = rp->ebx.word.bx; + br.cx = rp->ecx.word.cx; + br.dx = rp->edx.word.dx; + br.bp = rp->ebp.word.bp; + br.si = rp->esi.word.si; + br.di = rp->edi.word.di; + br.ds = rp->ds; + br.es = rp->es; + + DBG_MSG("Doing BIOS call..."); + rp->eflags = bios_func(intnum, &br); + DBG_MSG("done\n"); + + rp->eax.word.ax = br.ax; + rp->ebx.word.bx = br.bx; + rp->ecx.word.cx = br.cx; + rp->edx.word.dx = br.dx; + rp->ebp.word.bp = br.bp; + rp->esi.word.si = br.si; + rp->edi.word.di = br.di; + rp->ds = br.ds; + rp->es = br.es; +} + +static struct boot_syscalls bop_sysp = { + bcons_getchar, + bcons_putchar, + bcons_ischar, +}; + +static char *whoami; + +#define BUFLEN 64 + +static void +setup_rarp_props(struct sol_netinfo *sip) +{ + char buf[BUFLEN]; /* to hold ip/mac addrs */ + uint8_t *val; + + val = (uint8_t *)&sip->sn_ciaddr; + (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d", + val[0], val[1], val[2], val[3]); + bsetprops(BP_HOST_IP, buf); + + val = (uint8_t *)&sip->sn_siaddr; + (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d", + val[0], val[1], val[2], val[3]); + bsetprops(BP_SERVER_IP, buf); + + if (sip->sn_giaddr != 0) { + val = (uint8_t *)&sip->sn_giaddr; + (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d", + val[0], val[1], val[2], val[3]); + bsetprops(BP_ROUTER_IP, buf); + } + + if (sip->sn_netmask != 0) { + val = (uint8_t *)&sip->sn_netmask; + (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d", + val[0], val[1], val[2], val[3]); + bsetprops(BP_SUBNET_MASK, buf); + } + + if (sip->sn_mactype != 4 || sip->sn_maclen != 6) { + bop_printf(NULL, "unsupported mac type %d, mac len %d\n", + sip->sn_mactype, sip->sn_maclen); + } else { + val = sip->sn_macaddr; + (void) snprintf(buf, BUFLEN, "%x:%x:%x:%x:%x:%x", + val[0], val[1], val[2], val[3], val[4], val[5]); + bsetprops(BP_BOOT_MAC, buf); + } +} + +/* + * 1st pass at building the table of boot properties. This includes: + * - values set on the command line: -B a=x,b=y,c=z .... + * - known values we just compute (ie. from xbootp) + * - values from /boot/solaris/bootenv.rc (ie. eeprom(1m) values) + * + * the grub command line looked like: + * kernel boot-file [-B prop=value[,prop=value]...] [boot-args] + * + * whoami is the same as boot-file + */ +static void +build_boot_properties(void) +{ + char *name; + int name_len; + char *value; + int value_len; + static int stdout_val = 0; + struct boot_modules *bm; + char *propbuf; + int quoted = 0; + int boot_arg_len; + uchar_t boot_device; + char str[3]; + multiboot_info_t *mbi; + int netboot; + struct sol_netinfo *sip; + + /* + * These have to be done first, so that kobj_mount_root() works + */ + DBG_MSG("Building boot properties\n"); + propbuf = do_bsys_alloc(NULL, NULL, MMU_PAGESIZE, 0); + DBG((uintptr_t)propbuf); + if (xbootp->bi_module_cnt > 0) { + bm = xbootp->bi_modules; + bsetprop64("ramdisk_start", (uint64_t)(uintptr_t)bm->bm_addr); + bsetprop64("ramdisk_end", (uint64_t)(uintptr_t)bm->bm_addr + + bm->bm_size); + } + + DBG_MSG("Parsing command line for boot properties\n"); + value = xbootp->bi_cmdline; + + /* + * allocate memory to collect boot_args into + */ + boot_arg_len = strlen(xbootp->bi_cmdline) + 1; + boot_args = do_bsys_alloc(NULL, NULL, boot_arg_len, MMU_PAGESIZE); + boot_args[0] = 0; + boot_arg_len = 0; + + while (ISSPACE(*value)) + ++value; + /* + * value now points at the boot-file + */ + value_len = 0; + while (value[value_len] && !ISSPACE(value[value_len])) + ++value_len; + if (value_len > 0) { + whoami = propbuf; + bcopy(value, whoami, value_len); + whoami[value_len] = 0; + bsetprops("boot-file", whoami); + /* + * strip leading path stuff from whoami, so running from + * PXE/miniroot makes sense. + */ + if (strstr(whoami, "/platform/") != NULL) + whoami = strstr(whoami, "/platform/"); + bsetprops("whoami", whoami); + } + + /* + * Values forcibly set boot propertiex on the command line via -B. + * Allow use of quotes in values. Other stuff goes on kernel + * command line. + */ + name = value + value_len; + while (*name != 0) { + /* + * anything not " -B" is copied to the command line + */ + if (!ISSPACE(name[0]) || name[1] != '-' || name[2] != 'B') { + boot_args[boot_arg_len++] = *name; + boot_args[boot_arg_len] = 0; + ++name; + continue; + } + + /* + * skip the " -B" and following white space + */ + name += 3; + while (ISSPACE(*name)) + ++name; + while (*name && !ISSPACE(*name)) { + value = strstr(name, "="); + if (value == NULL) + break; + name_len = value - name; + ++value; + value_len = 0; + quoted = 0; + for (; ; ++value_len) { + if (!value[value_len]) + break; + + /* + * is this value quoted? + */ + if (value_len == 0 && + (value[0] == '\'' || value[0] == '"')) { + quoted = value[0]; + ++value_len; + } + + /* + * In the quote accept any character, + * but look for ending quote. + */ + if (quoted) { + if (value[value_len] == quoted) + quoted = 0; + continue; + } + + /* + * a comma or white space ends the value + */ + if (value[value_len] == ',' || + ISSPACE(value[value_len])) + break; + } + + if (value_len == 0) { + bsetprop(name, name_len, "true", 5); + } else { + char *v = value; + int l = value_len; + if (v[0] == v[l - 1] && + (v[0] == '\'' || v[0] == '"')) { + ++v; + l -= 2; + } + bcopy(v, propbuf, l); + propbuf[l] = '\0'; + bsetprop(name, name_len, propbuf, + l + 1); + } + name = value + value_len; + while (*name == ',') + ++name; + } + } + + /* + * set boot-args property + */ + bsetprops("boot-args", boot_args); + + /* + * set the BIOS boot device from GRUB + */ + netboot = 0; + mbi = xbootp->bi_mb_info; + if (mbi != NULL && mbi->flags & 0x2) { + boot_device = mbi->boot_device >> 24; + if (boot_device == 0x20) + netboot++; + str[0] = (boot_device >> 4) + '0'; + str[1] = (boot_device & 0xf) + '0'; + str[2] = 0; + bsetprops("bios-boot-device", str); + } else { + netboot = 1; + } + + /* + * In the netboot case, drives_info is overloaded with the dhcp ack. + * This is not multiboot compliant and requires special pxegrub! + */ + if (netboot && mbi->drives_length != 0) { + sip = (struct sol_netinfo *)(uintptr_t)mbi->drives_addr; + if (sip->sn_infotype == SN_TYPE_BOOTP) + bsetprop("bootp-response", sizeof ("bootp-response"), + (void *)(uintptr_t)mbi->drives_addr, + mbi->drives_length); + else if (sip->sn_infotype == SN_TYPE_BOOTP) + setup_rarp_props(sip); + } + bsetprop("stdout", strlen("stdout"), + &stdout_val, sizeof (stdout_val)); + + /* + * more conjured up values for made up things.... + */ + bsetprops("mfg-name", "i86pc"); + bsetprops("impl-arch-name", "i86pc"); + + /* + * Build firmware-provided system properties + */ + build_firmware_properties(); + + /* + * Find out what these are: + * - cpuid_feature_ecx_include + * - cpuid_feature_ecx_exclude + * - cpuid_feature_edx_include + * - cpuid_feature_edx_exclude + * + * Find out what these are in multiboot: + * - bootp-response + * - netdev-path + * - fstype + */ +} + +/* + * Install a temporary IDT that lets us catch errors in the boot time code. + * We shouldn't get any faults at all while this is installed, so we'll + * just generate a traceback and exit. + */ +#ifdef __amd64 +static const int bcode_sel = B64CODE_SEL; +#else +static const int bcode_sel = B32CODE_SEL; +#endif + +/* + * simple description of a stack frame (args are 32 bit only currently) + */ +typedef struct bop_frame { + struct bop_frame *old_frame; + pc_t retaddr; + long arg[1]; +} bop_frame_t; + +void +bop_traceback(bop_frame_t *frame) +{ + pc_t pc; + int cnt; + int a; + char *ksym; + ulong_t off; + + bop_printf(NULL, "Stack traceback:\n"); + for (cnt = 0; cnt < 30; ++cnt) { /* up to 30 frames */ + pc = frame->retaddr; + if (pc == 0) + break; + ksym = kobj_getsymname(pc, &off); + if (ksym) + bop_printf(NULL, " %s+%lx", ksym, off); + else + bop_printf(NULL, " 0x%lx", pc); + + frame = frame->old_frame; + if (frame == 0) { + bop_printf(NULL, "\n"); + break; + } + for (a = 0; a < 6; ++a) { /* try for 6 args */ +#if defined(__i386) + if ((void *)&frame->arg[a] == (void *)frame->old_frame) + break; + if (a == 0) + bop_printf(NULL, "("); + else + bop_printf(NULL, ","); + bop_printf(NULL, "0x%lx", frame->arg[a]); +#endif + } + bop_printf(NULL, ")\n"); + } +} + +struct trapframe { + ulong_t frame_ptr; /* %[er]bp pushed by our code */ + ulong_t error_code; /* optional */ + ulong_t inst_ptr; + ulong_t code_seg; + ulong_t flags_reg; +#ifdef __amd64 + ulong_t stk_ptr; + ulong_t stk_seg; +#endif +}; + +void +bop_trap(struct trapframe *tf) +{ + bop_frame_t fakeframe; + static int depth = 0; + + /* + * Check for an infinite loop of traps. Avoid bop_printf() here to + * reduce code path and further possibility of failure. + */ + if (++depth > 2) { + PUT_STRING("Nested trap, calling reset()\n"); + reset(); + } + + /* + * adjust the tf for optional error_code by detecting the code selector + */ + if (tf->code_seg != bcode_sel) + tf = (struct trapframe *)((uintptr_t)tf - sizeof (ulong_t)); + + bop_printf(NULL, "Unexpected trap\n"); + bop_printf(NULL, "instruction pointer 0x%lx\n", tf->inst_ptr); + bop_printf(NULL, "error code, optional 0x%lx\n", + tf->error_code & 0xffffffff); + bop_printf(NULL, "code segment 0x%lx\n", tf->code_seg & 0xffff); + bop_printf(NULL, "flags register 0x%lx\n", tf->flags_reg); +#ifdef __amd64 + bop_printf(NULL, "return %%rsp 0x%lx\n", tf->stk_ptr); + bop_printf(NULL, "return %%ss 0x%lx\n", tf->stk_seg & 0xffff); +#endif + fakeframe.old_frame = (bop_frame_t *)tf->frame_ptr; + fakeframe.retaddr = (pc_t)tf->inst_ptr; + bop_printf(NULL, "Attempting stack backtrace:\n"); + bop_traceback(&fakeframe); + bop_panic("unexpected trap in early boot"); +} + +extern void bop_trap_handler(void); + +static gate_desc_t bop_idt[NIDT]; + +static desctbr_t bop_idt_info; + +static void +bop_idt_init(void) +{ + int t; + + bzero(&bop_idt, sizeof (bop_idt)); + for (t = 0; t < NIDT; ++t) { + set_gatesegd(&bop_idt[t], &bop_trap_handler, bcode_sel, + SDT_SYSIGT, SEL_KPL); + } + bop_idt_info.dtr_limit = sizeof (bop_idt) - 1; + bop_idt_info.dtr_base = (uintptr_t)&bop_idt; + wr_idtr(&bop_idt_info); +} + +/* + * This is where we enter the kernel. It dummies up the boot_ops and + * boot_syscalls vectors and jumps off to _kobj_boot() + */ +void +_start(struct xboot_info *xbp) +{ + bootops_t *bops = &bootop; + extern void _kobj_boot(); + + /* + * 1st off - initialize the console for any error messages + */ + xbootp = xbp; + bcons_init((void *)xbootp->bi_cmdline); + have_console = 1; + + /* + * enable debugging + */ + if (strstr((char *)xbootp->bi_cmdline, "kbm_debug")) + kbm_debug = 1; + + DBG_MSG("\n\n*** Entered Solaris in _start() cmdline is: "); + DBG_MSG((char *)xbootp->bi_cmdline); + DBG_MSG("\n\n\n"); + + /* + * Install an IDT to catch early pagefaults (shouldn't have any). + * Also needed for kmdb. + */ + bop_idt_init(); + + /* + * only physinstalled is still used by startup. + */ + bm.physinstalled = xbp->bi_phys_install; + bm.physavail = NULL; + + /* + * initialize the boot time allocator + */ + next_phys = xbootp->bi_next_paddr; + DBG(next_phys); + next_virt = (uintptr_t)xbootp->bi_next_vaddr; + DBG(next_virt); + DBG_MSG("Initializing boot time memory management..."); + kbm_init(xbootp); + DBG_MSG("done\n"); + + /* + * Fill in the bootops vector + */ + bops->bsys_version = BO_VERSION; + bops->boot_mem = &bm; + bops->bsys_alloc = do_bsys_alloc; + bops->bsys_free = do_bsys_free; + bops->bsys_getproplen = do_bsys_getproplen; + bops->bsys_getprop = do_bsys_getprop; + bops->bsys_nextprop = do_bsys_nextprop; + bops->bsys_printf = bop_printf; + bops->bsys_doint = do_bsys_doint; + + /* + * BOP_EALLOC() is no longer needed + */ + bops->bsys_ealloc = do_bsys_ealloc; + + /* + * + */ + DBG_MSG("Initializing boot properties:\n"); + build_boot_properties(); + + if (strstr((char *)xbootp->bi_cmdline, "prom_debug") || kbm_debug) { + char *name; + char *value; + int len; + + value = do_bsys_alloc(NULL, NULL, MMU_PAGESIZE, MMU_PAGESIZE); + bop_printf(NULL, "\nBoot properties:\n"); + name = ""; + while ((name = do_bsys_nextprop(NULL, name)) != NULL) { + bop_printf(NULL, "\t0x%p %s = ", (void *)name, name); + (void) do_bsys_getprop(NULL, name, value); + len = do_bsys_getproplen(NULL, name); + bop_printf(NULL, "len=%d ", len); + value[len] = 0; + bop_printf(NULL, "%s\n", value); + } + } + + /* + * jump into krtld... + */ + _kobj_boot(&bop_sysp, NULL, bops, NULL); +} + + +/*ARGSUSED*/ +static caddr_t +no_more_alloc(bootops_t *bop, caddr_t virthint, size_t size, int align) +{ + panic("Attempt to bsys_alloc() too late\n"); + return (NULL); +} + +/*ARGSUSED*/ +static void +no_more_free(bootops_t *bop, caddr_t virt, size_t size) +{ + panic("Attempt to bsys_free() too late\n"); +} + +void +bop_no_more_mem(void) +{ + DBG(total_bop_alloc_scratch); + DBG(total_bop_alloc_kernel); + bootops->bsys_alloc = no_more_alloc; + bootops->bsys_free = no_more_free; +} + + +/* + * Set ACPI firmware properties + */ + +static caddr_t +vmap_phys(size_t length, paddr_t pa) +{ + paddr_t start, end; + caddr_t va; + size_t len, page; + + start = P2ALIGN(pa, MMU_PAGESIZE); + end = P2ROUNDUP(pa + length, MMU_PAGESIZE); + len = end - start; + va = (caddr_t)alloc_vaddr(len, MMU_PAGESIZE); + for (page = 0; page < len; page += MMU_PAGESIZE) + kbm_map((uintptr_t)va + page, start + page, 0, 0); + return (va + (pa & MMU_PAGEOFFSET)); +} + +static uint8_t +checksum_table(uint8_t *tp, size_t len) +{ + uint8_t sum = 0; + + while (len-- > 0) + sum += *tp++; + + return (sum); +} + +static int +valid_rsdp(struct rsdp *rp) +{ + + /* validate the V1.x checksum */ + if (checksum_table((uint8_t *)&rp->v1, sizeof (struct rsdp_v1)) != 0) + return (0); + + /* If pre-ACPI 2.0, this is a valid RSDP */ + if (rp->v1.revision < 2) + return (1); + + /* validate the V2.x checksum */ + if (checksum_table((uint8_t *)rp, sizeof (struct rsdp)) != 0) + return (0); + + return (1); +} + +/* + * Scan memory range for an RSDP; + * see ACPI 3.0 Spec, 5.2.5.1 + */ +static struct rsdp * +scan_rsdp(paddr_t start, paddr_t end) +{ + size_t len = end - start + 1; + caddr_t ptr; + + ptr = vmap_phys(len, start); + while (len > 0) { + if (strncmp(ptr, ACPI_RSDP_SIG, ACPI_RSDP_SIG_LEN) == 0) + if (valid_rsdp((struct rsdp *)ptr)) + return ((struct rsdp *)ptr); + ptr += 16; + len -= 16; + } + + return (NULL); +} + +/* + * Refer to ACPI 3.0 Spec, section 5.2.5.1 to understand this function + */ +static struct rsdp * +find_rsdp() { + struct rsdp *rsdp; + uint16_t *ebda_seg; + paddr_t ebda_addr; + + /* + * Get the EBDA segment and scan the first 1K + */ + ebda_seg = (uint16_t *)vmap_phys(sizeof (uint16_t), ACPI_EBDA_SEG_ADDR); + ebda_addr = *ebda_seg << 4; + rsdp = scan_rsdp(ebda_addr, ebda_addr + ACPI_EBDA_LEN - 1); + if (rsdp == NULL) + /* if EBDA doesn't contain RSDP, look in BIOS memory */ + rsdp = scan_rsdp(0xe0000, 0xfffff); + return (rsdp); +} + +static struct table_header * +map_fw_table(paddr_t table_addr) +{ + struct table_header *tp; + size_t len = MAX(sizeof (struct table_header), MMU_PAGESIZE); + + /* + * Map at least a page; if the table is larger than this, remap it + */ + tp = (struct table_header *)vmap_phys(len, table_addr); + if (tp->len > len) + tp = (struct table_header *)vmap_phys(tp->len, table_addr); + return (tp); +} + +static struct table_header * +find_fw_table(char *signature) +{ + static int revision = 0; + static struct xsdt *xsdt; + static int len; + paddr_t xsdt_addr; + struct rsdp *rsdp; + struct table_header *tp; + paddr_t table_addr; + int n; + + if (strlen(signature) != ACPI_TABLE_SIG_LEN) + return (NULL); + + /* + * Reading the ACPI 3.0 Spec, section 5.2.5.3 will help + * understand this code. If we haven't already found the RSDT/XSDT, + * revision will be 0. Find the RSDP and check the revision + * to find out whether to use the RSDT or XSDT. If revision is + * 0 or 1, use the RSDT and set internal revision to 1; if it is 2, + * use the XSDT. If the XSDT address is 0, though, fall back to + * revision 1 and use the RSDT. + */ + if (revision == 0) { + if ((rsdp = (struct rsdp *)find_rsdp()) != NULL) { + revision = rsdp->v1.revision; + switch (revision) { + case 2: + /* + * Use the XSDT unless BIOS is buggy and + * claims to be rev 2 but has a null XSDT + * address + */ + xsdt_addr = rsdp->xsdt; + if (xsdt_addr != 0) + break; + /* FALLTHROUGH */ + case 0: + /* treat RSDP rev 0 as revision 1 internally */ + revision = 1; + /* FALLTHROUGH */ + case 1: + /* use the RSDT for rev 0/1 */ + xsdt_addr = rsdp->v1.rsdt; + break; + default: + /* unknown revision */ + revision = 0; + break; + } + } + if (revision == 0) + return (NULL); + + /* cache the XSDT info */ + xsdt = (struct xsdt *)map_fw_table(xsdt_addr); + len = (xsdt->hdr.len - sizeof (xsdt->hdr)) / + ((revision == 1) ? sizeof (uint32_t) : sizeof (uint64_t)); + } + + /* + * Scan the table headers looking for a signature match + */ + for (n = 0; n < len; n++) { + table_addr = (revision == 1) ? xsdt->p.r[n] : xsdt->p.x[n]; + if (table_addr == 0) + continue; + tp = map_fw_table(table_addr); + if (strncmp(tp->sig, signature, ACPI_TABLE_SIG_LEN) == 0) { + return (tp); + } + } + return (NULL); +} + +static void +process_madt(struct madt *tp) +{ + struct madt_processor *cpu, *end; + uint32_t cpu_count = 0; + + /* + * User-set boot-ncpus overrides firmware count + */ + if (do_bsys_getproplen(NULL, "boot-ncpus") >= 0) + return; + + if (tp != NULL) { + end = (struct madt_processor *)(tp->hdr.len + (uintptr_t)tp); + cpu = tp->list; + while (cpu < end) { + if (cpu->type == MADT_PROCESSOR) + if (cpu->flags & 1) + cpu_count++; + + cpu = (struct madt_processor *) + (cpu->len + (uintptr_t)cpu); + } + bsetpropsi("boot-ncpus", cpu_count); + } + +} + +static void +process_srat(struct srat *tp) +{ + struct srat_item *item, *end; + int i; + int proc_num, mem_num; +#pragma pack(1) + struct { + uint32_t domain; + uint32_t apic_id; + uint32_t sapic_id; + } processor; + struct { + uint32_t domain; + uint64_t addr; + uint64_t length; + uint32_t flags; + } memory; +#pragma pack() + char prop_name[30]; + + if (tp == NULL) + return; + + proc_num = mem_num = 0; + end = (struct srat_item *)(tp->hdr.len + (uintptr_t)tp); + item = tp->list; + while (item < end) { + switch (item->type) { + case SRAT_PROCESSOR: + if (!(item->i.p.flags & SRAT_ENABLED)) + break; + processor.domain = item->i.p.domain1; + for (i = 0; i < 3; i++) + processor.domain += + item->i.p.domain2[i] << ((i + 1) * 8); + processor.apic_id = item->i.p.apic_id; + processor.sapic_id = item->i.p.local_sapic_eid; + (void) snprintf(prop_name, 30, "acpi-srat-processor-%d", + proc_num); + bsetprop(prop_name, strlen(prop_name), &processor, + sizeof (processor)); + proc_num++; + break; + case SRAT_MEMORY: + if (!(item->i.m.flags & SRAT_ENABLED)) + break; + memory.domain = item->i.m.domain; + memory.addr = item->i.m.base_addr; + memory.length = item->i.m.len; + memory.flags = item->i.m.flags; + (void) snprintf(prop_name, 30, "acpi-srat-memory-%d", + mem_num); + bsetprop(prop_name, strlen(prop_name), &memory, + sizeof (memory)); + mem_num++; + break; + } + + item = (struct srat_item *) + (item->len + (caddr_t)item); + } +} + +static void +build_firmware_properties(void) +{ + struct table_header *tp; + + if (tp = find_fw_table("APIC")) + process_madt((struct madt *)tp); + + if (tp = find_fw_table("SRAT")) + process_srat((struct srat *)tp); +} + +/* + * fake up a boot property for USB serial console early boot output + */ +void * +usbser_init(size_t size) +{ + static char *p = NULL; + + p = do_bsys_alloc(NULL, NULL, size, MMU_PAGESIZE); + *p = 0; + bsetprop("usb-serial-buf", strlen("usb-serial-buf") + 1, + &p, sizeof (p)); + return (p); +} diff --git a/usr/src/uts/i86pc/os/fpu_subr.c b/usr/src/uts/i86pc/os/fpu_subr.c new file mode 100644 index 0000000000..dee40885e7 --- /dev/null +++ b/usr/src/uts/i86pc/os/fpu_subr.c @@ -0,0 +1,193 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Floating point configuration. + */ + +#include <sys/types.h> +#include <sys/regset.h> +#include <sys/privregs.h> +#include <sys/x86_archext.h> +#include <sys/archsystm.h> +#include <sys/fp.h> +#include <sys/cmn_err.h> + +#define XMM_ALIGN 16 + +/* + * If fpu_exists is non-zero, fpu_probe will attempt to use any + * hardware FPU (subject to other constraints, see below). If + * fpu_exists is zero, fpu_probe will report that there is no + * FPU even if there is one. + */ +int fpu_exists = 1; + +int fp_kind = FP_387; + +/* + * The variable fpu_ignored is provided to allow other code to + * determine whether emulation is being done because there is + * no FPU or because of an override requested via /etc/system. + */ +int fpu_ignored = 0; + +/* + * Used by ppcopy and ppzero to determine whether or not to use the + * SSE-based pagecopy and pagezero routines + */ +int use_sse_pagecopy = 0; +int use_sse_pagezero = 0; +int use_sse_copy = 0; + +#if defined(__i386) + +/* + * The variable fpu_pentium_fdivbug is provided to allow other code to + * determine whether the system contains a Pentium with the FDIV problem. + */ +int fpu_pentium_fdivbug = 0; + +#endif + + +#define ENABLE_SSE() setcr4(CR4_ENABLE_SSE_FLAGS(getcr4())) +#define DISABLE_SSE() setcr4(CR4_DISABLE_SSE_FLAGS(getcr4())) + +/* + * Try and figure out what kind of FP capabilities we have, and + * set up the control registers accordingly. + */ +void +fpu_probe(void) +{ + do { + if (fpu_initial_probe() != 0) + continue; + + if (fpu_exists == 0) { + fpu_ignored = 1; + continue; + } + +#if defined(__i386) + fpu_pentium_fdivbug = fpu_probe_pentium_fdivbug(); + /* + * The test does some real floating point operations. + * Reset it back to previous state. + */ + (void) fpu_initial_probe(); + + if (fpu_pentium_fdivbug != 0) { + fpu_ignored = 1; + continue; + } +#endif + + /* + * Check and see if the fpu is present by looking + * at the "extension type" bit. (While this used to + * indicate a 387DX coprocessor in days gone by, + * it's forced on by modern implementations for + * compatibility.) + */ + if ((getcr0() & CR0_ET) == 0) + continue; + +#if defined(__amd64) + /* + * SSE and SSE2 are required for the 64-bit ABI. + * + * If they're not present, we can in principal run + * 32-bit userland, though 64-bit processes will be hosed. + * + * (Perhaps we should complain more about this case!) + */ + if ((x86_feature & X86_SSE|X86_SSE2) == (X86_SSE|X86_SSE2)) { + fp_kind = __FP_SSE; + ENABLE_SSE(); + } +#elif defined(__i386) + /* + * SSE and SSE2 are both optional, and we patch kernel + * code to exploit it when present. + */ + if (x86_feature & X86_SSE) { + fp_kind = __FP_SSE; + fpsave_ctxt = fpxsave_ctxt; + patch_sse(); + if (x86_feature & X86_SSE2) + patch_sse2(); + ENABLE_SSE(); + } else { + x86_feature &= ~X86_SSE2; + /* + * (Just in case the BIOS decided we wanted SSE + * enabled when we didn't. See 4965674.) + */ + DISABLE_SSE(); + } +#endif + if (x86_feature & X86_SSE2) { + use_sse_pagecopy = use_sse_pagezero = use_sse_copy = 1; + } + + if (fp_kind == __FP_SSE) { + struct fxsave_state *fx; + uint8_t fxsave_state[sizeof (struct fxsave_state) + + XMM_ALIGN]; + + /* + * Extract the mxcsr mask from our first fxsave + */ + fx = (void *)(((uintptr_t)(&fxsave_state[0]) + + XMM_ALIGN) & ~(XMM_ALIGN - 1ul)); + + fx->fx_mxcsr_mask = 0; + fxsave_insn(fx); + if (fx->fx_mxcsr_mask != 0) { + /* + * Override default mask initialized in fpu.c + */ + sse_mxcsr_mask = fx->fx_mxcsr_mask; + } + } + + setcr0(CR0_ENABLE_FPU_FLAGS(getcr0())); + return; + /*CONSTANTCONDITION*/ + } while (0); + + /* + * No FPU hardware present + */ + setcr0(CR0_DISABLE_FPU_FLAGS(getcr0())); + DISABLE_SSE(); + fp_kind = FP_NO; + fpu_exists = 0; +} diff --git a/usr/src/uts/intel/ia32/os/arch_kdi.c b/usr/src/uts/i86pc/os/hold_page.c index 2ac020245a..1c11bc80f1 100644 --- a/usr/src/uts/intel/ia32/os/arch_kdi.c +++ b/usr/src/uts/i86pc/os/hold_page.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,22 +18,25 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" -/* - * The architecture-generic portion of the Kernel/Debugger (KDI) interface. - */ +#include <sys/hold_page.h> -#include <sys/param.h> -#include <sys/kdi_impl.h> +/*ARGSUSED*/ +int +plat_hold_page(pfn_t pfn, int lock, page_t **pp_ret) +{ + return (PLAT_HOLD_OK); +} -uintptr_t -kdi_get_userlimit(void) +/*ARGSUSED*/ +void +plat_release_page(page_t *pp) { - return (_userlimit); } diff --git a/usr/src/uts/i86pc/os/intr.c b/usr/src/uts/i86pc/os/intr.c index 30352a3908..598d608f1a 100644 --- a/usr/src/uts/i86pc/os/intr.c +++ b/usr/src/uts/i86pc/os/intr.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -48,49 +48,23 @@ #include <sys/pool_pset.h> #include <sys/zone.h> #include <sys/bitmap.h> +#include <sys/archsystm.h> +#include <sys/machsystm.h> +#include <sys/ontrap.h> +#include <sys/x86_archext.h> +#include <sys/promif.h> -#if defined(__amd64) -#if defined(__lint) /* - * atomic_btr32() is a gcc __inline__ function, defined in <asm/bitmap.h> - * For lint purposes, define it here. + * Set cpu's base SPL level to the highest active interrupt level */ -uint_t -atomic_btr32(uint32_t *pending, uint_t pil) -{ - return (*pending &= ~(1 << pil)); -} -#else - -extern uint_t atomic_btr32(uint32_t *pending, uint_t pil); - -#endif - -/* - * This code is amd64-only for now, but as time permits, we should - * use this on i386 too. - */ - -/* - * Some questions to ponder: - * - in several of these routines, we make multiple calls to tsc_read() - * without invoking functions .. couldn't we just reuse the same - * timestamp sometimes? - * - if we have the inline, we can probably make set_base_spl be a - * C routine too. - */ - -static uint_t -bsrw_insn(uint16_t mask) +void +set_base_spl(void) { - uint_t index = sizeof (mask) * NBBY - 1; + struct cpu *cpu = CPU; + uint16_t active = (uint16_t)cpu->cpu_intr_actv; - ASSERT(mask != 0); - - while ((mask & (1 << index)) == 0) - index--; - return (index); + cpu->cpu_base_spl = active == 0 ? 0 : bsrw_insn(active); } /* @@ -103,12 +77,13 @@ bsrw_insn(uint16_t mask) * Called with interrupts masked. * The 'pil' is already set to the appropriate level for rp->r_trapno. */ -int +static int hilevel_intr_prolog(struct cpu *cpu, uint_t pil, uint_t oldpil, struct regs *rp) { struct machcpu *mcpu = &cpu->cpu_m; uint_t mask; hrtime_t intrtime; + hrtime_t now = tsc_read(); ASSERT(pil > LOCK_LEVEL); @@ -134,7 +109,7 @@ hilevel_intr_prolog(struct cpu *cpu, uint_t pil, uint_t oldpil, struct regs *rp) */ nestpil = bsrw_insn((uint16_t)mask); ASSERT(nestpil < pil); - intrtime = tsc_read() - + intrtime = now - mcpu->pil_high_start[nestpil - (LOCK_LEVEL + 1)]; mcpu->intrstat[nestpil][0] += intrtime; cpu->cpu_intracct[cpu->cpu_mstate] += intrtime; @@ -153,7 +128,7 @@ hilevel_intr_prolog(struct cpu *cpu, uint_t pil, uint_t oldpil, struct regs *rp) * is non-zero. */ if ((t->t_flag & T_INTR_THREAD) != 0 && t->t_intr_start != 0) { - intrtime = tsc_read() - t->t_intr_start; + intrtime = now - t->t_intr_start; mcpu->intrstat[t->t_pil][0] += intrtime; cpu->cpu_intracct[cpu->cpu_mstate] += intrtime; t->t_intr_start = 0; @@ -163,7 +138,7 @@ hilevel_intr_prolog(struct cpu *cpu, uint_t pil, uint_t oldpil, struct regs *rp) /* * Store starting timestamp in CPU structure for this PIL. */ - mcpu->pil_high_start[pil - (LOCK_LEVEL + 1)] = tsc_read(); + mcpu->pil_high_start[pil - (LOCK_LEVEL + 1)] = now; ASSERT((cpu->cpu_intr_actv & (1 << pil)) == 0); @@ -194,12 +169,13 @@ hilevel_intr_prolog(struct cpu *cpu, uint_t pil, uint_t oldpil, struct regs *rp) * * Called with interrupts masked */ -int +static int hilevel_intr_epilog(struct cpu *cpu, uint_t pil, uint_t oldpil, uint_t vecnum) { struct machcpu *mcpu = &cpu->cpu_m; uint_t mask; hrtime_t intrtime; + hrtime_t now = tsc_read(); ASSERT(mcpu->mcpu_pri == pil); @@ -226,7 +202,7 @@ hilevel_intr_epilog(struct cpu *cpu, uint_t pil, uint_t oldpil, uint_t vecnum) ASSERT(mcpu->pil_high_start[pil - (LOCK_LEVEL + 1)] != 0); - intrtime = tsc_read() - mcpu->pil_high_start[pil - (LOCK_LEVEL + 1)]; + intrtime = now - mcpu->pil_high_start[pil - (LOCK_LEVEL + 1)]; mcpu->intrstat[pil][0] += intrtime; cpu->cpu_intracct[cpu->cpu_mstate] += intrtime; @@ -244,7 +220,7 @@ hilevel_intr_epilog(struct cpu *cpu, uint_t pil, uint_t oldpil, uint_t vecnum) */ nestpil = bsrw_insn((uint16_t)mask); ASSERT(nestpil < pil); - mcpu->pil_high_start[nestpil - (LOCK_LEVEL + 1)] = tsc_read(); + mcpu->pil_high_start[nestpil - (LOCK_LEVEL + 1)] = now; /* * (Another high-level interrupt is active below this one, * so there is no need to check for an interrupt @@ -260,7 +236,7 @@ hilevel_intr_epilog(struct cpu *cpu, uint_t pil, uint_t oldpil, uint_t vecnum) kthread_t *t = cpu->cpu_thread; if (t->t_flag & T_INTR_THREAD) - t->t_intr_start = tsc_read(); + t->t_intr_start = now; } mcpu->mcpu_pri = oldpil; @@ -274,11 +250,12 @@ hilevel_intr_epilog(struct cpu *cpu, uint_t pil, uint_t oldpil, uint_t vecnum) * executing an interrupt thread. The new stack pointer of the * interrupt thread (which *must* be switched to) is returned. */ -caddr_t +static caddr_t intr_thread_prolog(struct cpu *cpu, caddr_t stackptr, uint_t pil) { struct machcpu *mcpu = &cpu->cpu_m; kthread_t *t, *volatile it; + hrtime_t now = tsc_read(); ASSERT(pil > 0); ASSERT((cpu->cpu_intr_actv & (1 << pil)) == 0); @@ -293,7 +270,7 @@ intr_thread_prolog(struct cpu *cpu, caddr_t stackptr, uint_t pil) */ t = cpu->cpu_thread; if ((t->t_flag & T_INTR_THREAD) && t->t_intr_start != 0) { - hrtime_t intrtime = tsc_read() - t->t_intr_start; + hrtime_t intrtime = now - t->t_intr_start; mcpu->intrstat[t->t_pil][0] += intrtime; cpu->cpu_intracct[cpu->cpu_mstate] += intrtime; t->t_intr_start = 0; @@ -326,7 +303,7 @@ intr_thread_prolog(struct cpu *cpu, caddr_t stackptr, uint_t pil) cpu->cpu_thread = it; /* new curthread on this cpu */ it->t_pil = (uchar_t)pil; it->t_pri = intr_pri + (pri_t)pil; - it->t_intr_start = tsc_read(); + it->t_intr_start = now; return (it->t_stk); } @@ -339,7 +316,7 @@ int intr_thread_cnt; /* * Called with interrupts disabled */ -void +static void intr_thread_epilog(struct cpu *cpu, uint_t vec, uint_t oldpil) { struct machcpu *mcpu = &cpu->cpu_m; @@ -347,12 +324,13 @@ intr_thread_epilog(struct cpu *cpu, uint_t vec, uint_t oldpil) kthread_t *it = cpu->cpu_thread; /* curthread */ uint_t pil, basespl; hrtime_t intrtime; + hrtime_t now = tsc_read(); pil = it->t_pil; cpu->cpu_stats.sys.intr[pil - 1]++; ASSERT(it->t_intr_start != 0); - intrtime = tsc_read() - it->t_intr_start; + intrtime = now - it->t_intr_start; mcpu->intrstat[pil][0] += intrtime; cpu->cpu_intracct[cpu->cpu_mstate] += intrtime; @@ -389,6 +367,7 @@ intr_thread_epilog(struct cpu *cpu, uint_t vec, uint_t oldpil) mcpu->mcpu_pri = basespl; (*setlvlx)(basespl, vec); (void) splhigh(); + sti(); it->t_state = TS_FREE; /* * Return interrupt thread to pool @@ -396,6 +375,7 @@ intr_thread_epilog(struct cpu *cpu, uint_t vec, uint_t oldpil) it->t_link = cpu->cpu_intr_thread; cpu->cpu_intr_thread = it; swtch(); + panic("intr_thread_epilog: swtch returned"); /*NOTREACHED*/ } @@ -410,23 +390,81 @@ intr_thread_epilog(struct cpu *cpu, uint_t vec, uint_t oldpil) pil = MAX(oldpil, basespl); mcpu->mcpu_pri = pil; (*setlvlx)(pil, vec); - t->t_intr_start = tsc_read(); + t->t_intr_start = now; cpu->cpu_thread = t; } /* - * Called with interrupts disabled by an interrupt thread to determine - * how much time has elapsed. See interrupt.s:intr_get_time() for detailed - * theory of operation. + * intr_get_time() is a resource for interrupt handlers to determine how + * much time has been spent handling the current interrupt. Such a function + * is needed because higher level interrupts can arrive during the + * processing of an interrupt. intr_get_time() only returns time spent in the + * current interrupt handler. + * + * The caller must be calling from an interrupt handler running at a pil + * below or at lock level. Timings are not provided for high-level + * interrupts. + * + * The first time intr_get_time() is called while handling an interrupt, + * it returns the time since the interrupt handler was invoked. Subsequent + * calls will return the time since the prior call to intr_get_time(). Time + * is returned as ticks. Use tsc_scalehrtime() to convert ticks to nsec. + * + * Theory Of Intrstat[][]: + * + * uint64_t intrstat[pil][0..1] is an array indexed by pil level, with two + * uint64_ts per pil. + * + * intrstat[pil][0] is a cumulative count of the number of ticks spent + * handling all interrupts at the specified pil on this CPU. It is + * exported via kstats to the user. + * + * intrstat[pil][1] is always a count of ticks less than or equal to the + * value in [0]. The difference between [1] and [0] is the value returned + * by a call to intr_get_time(). At the start of interrupt processing, + * [0] and [1] will be equal (or nearly so). As the interrupt consumes + * time, [0] will increase, but [1] will remain the same. A call to + * intr_get_time() will return the difference, then update [1] to be the + * same as [0]. Future calls will return the time since the last call. + * Finally, when the interrupt completes, [1] is updated to the same as [0]. + * + * Implementation: + * + * intr_get_time() works much like a higher level interrupt arriving. It + * "checkpoints" the timing information by incrementing intrstat[pil][0] + * to include elapsed running time, and by setting t_intr_start to rdtsc. + * It then sets the return value to intrstat[pil][0] - intrstat[pil][1], + * and updates intrstat[pil][1] to be the same as the new value of + * intrstat[pil][0]. + * + * In the normal handling of interrupts, after an interrupt handler returns + * and the code in intr_thread() updates intrstat[pil][0], it then sets + * intrstat[pil][1] to the new value of intrstat[pil][0]. When [0] == [1], + * the timings are reset, i.e. intr_get_time() will return [0] - [1] which + * is 0. + * + * Whenever interrupts arrive on a CPU which is handling a lower pil + * interrupt, they update the lower pil's [0] to show time spent in the + * handler that they've interrupted. This results in a growing discrepancy + * between [0] and [1], which is returned the next time intr_get_time() is + * called. Time spent in the higher-pil interrupt will not be returned in + * the next intr_get_time() call from the original interrupt, because + * the higher-pil interrupt's time is accumulated in intrstat[higherpil][]. */ uint64_t -intr_thread_get_time(struct cpu *cpu) +intr_get_time(void) { - struct machcpu *mcpu = &cpu->cpu_m; - kthread_t *t = cpu->cpu_thread; + struct cpu *cpu; + struct machcpu *mcpu; + kthread_t *t; uint64_t time, delta, ret; - uint_t pil = t->t_pil; + uint_t pil; + cli(); + cpu = CPU; + mcpu = &cpu->cpu_m; + t = cpu->cpu_thread; + pil = t->t_pil; ASSERT((cpu->cpu_intr_actv & CPU_INTR_ACTV_HIGH_LEVEL_MASK) == 0); ASSERT(t->t_flag & T_INTR_THREAD); ASSERT(pil != 0); @@ -442,10 +480,11 @@ intr_thread_get_time(struct cpu *cpu) mcpu->intrstat[pil][1] = time; cpu->cpu_intracct[cpu->cpu_mstate] += delta; + sti(); return (ret); } -caddr_t +static caddr_t dosoftint_prolog( struct cpu *cpu, caddr_t stackptr, @@ -455,6 +494,7 @@ dosoftint_prolog( kthread_t *t, *volatile it; struct machcpu *mcpu = &cpu->cpu_m; uint_t pil; + hrtime_t now; top: ASSERT(st_pending == mcpu->mcpu_softinfo.st_pending); @@ -489,8 +529,8 @@ top: * but at this point, correctness is critical, so we slavishly * emulate the i386 port. */ - if (atomic_btr32((uint32_t *)&mcpu->mcpu_softinfo.st_pending, pil) - == 0) { + if (atomic_btr32((uint32_t *) + &mcpu->mcpu_softinfo.st_pending, pil) == 0) { st_pending = mcpu->mcpu_softinfo.st_pending; goto top; } @@ -498,6 +538,8 @@ top: mcpu->mcpu_pri = pil; (*setspl)(pil); + now = tsc_read(); + /* * Get set to run interrupt thread. * There should always be an interrupt thread since we @@ -509,7 +551,7 @@ top: /* t_intr_start could be zero due to cpu_intr_swtch_enter. */ t = cpu->cpu_thread; if ((t->t_flag & T_INTR_THREAD) && t->t_intr_start != 0) { - hrtime_t intrtime = tsc_read() - t->t_intr_start; + hrtime_t intrtime = now - t->t_intr_start; mcpu->intrstat[pil][0] += intrtime; cpu->cpu_intracct[cpu->cpu_mstate] += intrtime; t->t_intr_start = 0; @@ -548,18 +590,19 @@ top: */ it->t_pil = (uchar_t)pil; it->t_pri = (pri_t)pil + intr_pri; - it->t_intr_start = tsc_read(); + it->t_intr_start = now; return (it->t_stk); } -void +static void dosoftint_epilog(struct cpu *cpu, uint_t oldpil) { struct machcpu *mcpu = &cpu->cpu_m; kthread_t *t, *it; uint_t pil, basespl; hrtime_t intrtime; + hrtime_t now = tsc_read(); it = cpu->cpu_thread; pil = it->t_pil; @@ -568,7 +611,7 @@ dosoftint_epilog(struct cpu *cpu, uint_t oldpil) ASSERT(cpu->cpu_intr_actv & (1 << pil)); cpu->cpu_intr_actv &= ~(1 << pil); - intrtime = tsc_read() - it->t_intr_start; + intrtime = now - it->t_intr_start; mcpu->intrstat[pil][0] += intrtime; cpu->cpu_intracct[cpu->cpu_mstate] += intrtime; @@ -587,21 +630,24 @@ dosoftint_epilog(struct cpu *cpu, uint_t oldpil) it->t_link = cpu->cpu_intr_thread; cpu->cpu_intr_thread = it; (void) splhigh(); + sti(); swtch(); /*NOTREACHED*/ + panic("dosoftint_epilog: swtch returned"); } it->t_link = cpu->cpu_intr_thread; cpu->cpu_intr_thread = it; it->t_state = TS_FREE; cpu->cpu_thread = t; if (t->t_flag & T_INTR_THREAD) - t->t_intr_start = tsc_read(); + t->t_intr_start = now; basespl = cpu->cpu_base_spl; pil = MAX(oldpil, basespl); mcpu->mcpu_pri = pil; (*setspl)(pil); } + /* * Make the interrupted thread 'to' be runnable. * @@ -624,8 +670,6 @@ intr_passivate( return (it->t_pil); } -#endif /* __amd64 */ - /* * Create interrupt kstats for this CPU. */ @@ -758,3 +802,341 @@ cpu_intr_swtch_exit(kthread_id_t t) ts = t->t_intr_start; } while (cas64(&t->t_intr_start, ts, tsc_read()) != ts); } + +/* + * Dispatch a hilevel interrupt (one above LOCK_LEVEL) + */ +/*ARGSUSED*/ +static void +dispatch_hilevel(uint_t vector, uint_t arg2) +{ + sti(); + av_dispatch_autovect(vector); + cli(); +} + +/* + * Dispatch a soft interrupt + */ +/*ARGSUSED*/ +static void +dispatch_softint(uint_t oldpil, uint_t arg2) +{ + struct cpu *cpu = CPU; + + sti(); + av_dispatch_softvect((int)cpu->cpu_thread->t_pil); + cli(); + + /* + * Must run softint_epilog() on the interrupt thread stack, since + * there may not be a return from it if the interrupt thread blocked. + */ + dosoftint_epilog(cpu, oldpil); +} + +/* + * Dispatch a normal interrupt + */ +static void +dispatch_hardint(uint_t vector, uint_t oldipl) +{ + struct cpu *cpu = CPU; + + sti(); + av_dispatch_autovect(vector); + cli(); + + /* + * Must run intr_thread_epilog() on the interrupt thread stack, since + * there may not be a return from it if the interrupt thread blocked. + */ + intr_thread_epilog(cpu, vector, oldipl); +} + +/* + * Deliver any softints the current interrupt priority allows. + * Called with interrupts disabled. + */ +void +dosoftint(struct regs *regs) +{ + struct cpu *cpu = CPU; + int oldipl; + caddr_t newsp; + + while (cpu->cpu_softinfo.st_pending) { + oldipl = cpu->cpu_pri; + newsp = dosoftint_prolog(cpu, (caddr_t)regs, + cpu->cpu_softinfo.st_pending, oldipl); + /* + * If returned stack pointer is NULL, priority is too high + * to run any of the pending softints now. + * Break out and they will be run later. + */ + if (newsp == NULL) + break; + switch_sp_and_call(newsp, dispatch_softint, oldipl, 0); + } +} + +/* + * Interrupt service routine, called with interrupts disabled. + */ +/*ARGSUSED*/ +void +do_interrupt(struct regs *rp, trap_trace_rec_t *ttp) +{ + struct cpu *cpu = CPU; + int newipl, oldipl = cpu->cpu_pri; + uint_t vector; + caddr_t newsp; + +#ifdef TRAPTRACE + ttp->ttr_marker = TT_INTERRUPT; + ttp->ttr_ipl = 0xff; + ttp->ttr_pri = oldipl; + ttp->ttr_spl = cpu->cpu_base_spl; + ttp->ttr_vector = 0xff; +#endif /* TRAPTRACE */ + + /* + * If it's a softint go do it now. + */ + if (rp->r_trapno == T_SOFTINT) { + dosoftint(rp); + ASSERT(!interrupts_enabled()); + return; + } + + /* + * Raise the interrupt priority. + */ + newipl = (*setlvl)(oldipl, (int *)&rp->r_trapno); +#ifdef TRAPTRACE + ttp->ttr_ipl = newipl; +#endif /* TRAPTRACE */ + + /* + * Bail if it is a spurious interrupt + */ + if (newipl == -1) + return; + cpu->cpu_pri = newipl; + vector = rp->r_trapno; +#ifdef TRAPTRACE + ttp->ttr_vector = vector; +#endif /* TRAPTRACE */ + if (newipl > LOCK_LEVEL) { + /* + * High priority interrupts run on this cpu's interrupt stack. + */ + if (hilevel_intr_prolog(cpu, newipl, oldipl, rp) == 0) { + newsp = cpu->cpu_intr_stack; + switch_sp_and_call(newsp, dispatch_hilevel, vector, 0); + } else { /* already on the interrupt stack */ + dispatch_hilevel(vector, 0); + } + (void) hilevel_intr_epilog(cpu, newipl, oldipl, vector); + } else { + /* + * Run this interrupt in a separate thread. + */ + newsp = intr_thread_prolog(cpu, (caddr_t)rp, newipl); + switch_sp_and_call(newsp, dispatch_hardint, vector, oldipl); + } + + /* + * Deliver any pending soft interrupts. + */ + if (cpu->cpu_softinfo.st_pending) + dosoftint(rp); +} + +/* + * Common tasks always done by _sys_rtt, called with interrupts disabled. + * Returns 1 if returning to userland, 0 if returning to system mode. + */ +int +sys_rtt_common(struct regs *rp) +{ + kthread_t *tp; + extern void mutex_exit_critical_start(); + extern long mutex_exit_critical_size; + +loop: + + /* + * Check if returning to user + */ + tp = CPU->cpu_thread; + if (USERMODE(rp->r_cs)) { + /* + * Check if AST pending. + */ + if (tp->t_astflag) { + /* + * Let trap() handle the AST + */ + sti(); + rp->r_trapno = T_AST; + trap(rp, (caddr_t)0, CPU->cpu_id); + cli(); + goto loop; + } + +#if defined(__amd64) + /* + * We are done if segment registers do not need updating. + */ + if ((tp->t_lwp->lwp_pcb.pcb_flags & RUPDATE_PENDING) == 0) + return (1); + + if (update_sregs(rp, tp->t_lwp)) { + /* + * 1 or more of the selectors is bad. + * Deliver a SIGSEGV. + */ + proc_t *p = ttoproc(tp); + + sti(); + mutex_enter(&p->p_lock); + tp->t_lwp->lwp_cursig = SIGSEGV; + mutex_exit(&p->p_lock); + psig(); + tp->t_sig_check = 1; + cli(); + } + tp->t_lwp->lwp_pcb.pcb_flags &= ~RUPDATE_PENDING; + +#endif /* __amd64 */ + return (1); + } + + /* + * Here if we are returning to supervisor mode. + * Check for a kernel preemption request. + */ + if (CPU->cpu_kprunrun && (rp->r_ps & PS_IE)) { + + /* + * Do nothing if already in kpreempt + */ + if (!tp->t_preempt_lk) { + tp->t_preempt_lk = 1; + sti(); + kpreempt(1); /* asynchronous kpreempt call */ + cli(); + tp->t_preempt_lk = 0; + } + } + + /* + * If we interrupted the mutex_exit() critical region we must + * reset the PC back to the beginning to prevent missed wakeups + * See the comments in mutex_exit() for details. + */ + if ((uintptr_t)rp->r_pc - (uintptr_t)mutex_exit_critical_start < + mutex_exit_critical_size) { + rp->r_pc = (greg_t)mutex_exit_critical_start; + } + return (0); +} + +void +send_dirint(int cpuid, int int_level) +{ + (*send_dirintf)(cpuid, int_level); +} + +/* + * do_splx routine, takes new ipl to set + * returns the old ipl. + * We are careful not to set priority lower than CPU->cpu_base_pri, + * even though it seems we're raising the priority, it could be set + * higher at any time by an interrupt routine, so we must block interrupts + * and look at CPU->cpu_base_pri + */ +int +do_splx(int newpri) +{ + ulong_t flag; + cpu_t *cpu; + int curpri, basepri; + + flag = intr_clear(); + cpu = CPU; /* ints are disabled, now safe to cache cpu ptr */ + curpri = cpu->cpu_m.mcpu_pri; + basepri = cpu->cpu_base_spl; + if (newpri < basepri) + newpri = basepri; + cpu->cpu_m.mcpu_pri = newpri; + (*setspl)(newpri); + /* + * If we are going to reenable interrupts see if new priority level + * allows pending softint delivery. + */ + if ((flag & PS_IE) && + bsrw_insn((uint16_t)cpu->cpu_softinfo.st_pending) > newpri) + fakesoftint(); + ASSERT(!interrupts_enabled()); + intr_restore(flag); + return (curpri); +} + +/* + * Common spl raise routine, takes new ipl to set + * returns the old ipl, will not lower ipl. + */ +int +splr(int newpri) +{ + ulong_t flag; + cpu_t *cpu; + int curpri, basepri; + + flag = intr_clear(); + cpu = CPU; /* ints are disabled, now safe to cache cpu ptr */ + curpri = cpu->cpu_m.mcpu_pri; + /* + * Only do something if new priority is larger + */ + if (newpri > curpri) { + basepri = cpu->cpu_base_spl; + if (newpri < basepri) + newpri = basepri; + cpu->cpu_m.mcpu_pri = newpri; + (*setspl)(newpri); + /* + * See if new priority level allows pending softint delivery + */ + if ((flag & PS_IE) && + bsrw_insn((uint16_t)cpu->cpu_softinfo.st_pending) > newpri) + fakesoftint(); + } + intr_restore(flag); + return (curpri); +} + +int +getpil(void) +{ + return (CPU->cpu_m.mcpu_pri); +} + +int +interrupts_enabled(void) +{ + ulong_t flag; + + flag = getflags(); + return ((flag & PS_IE) == PS_IE); +} + +#ifdef DEBUG +void +assert_ints_enabled(void) +{ + ASSERT(!interrupts_unleashed || interrupts_enabled()); +} +#endif /* DEBUG */ diff --git a/usr/src/uts/i86pc/os/mach_kdi.c b/usr/src/uts/i86pc/os/mach_kdi.c index c07ec41f92..ce8255cdd8 100644 --- a/usr/src/uts/i86pc/os/mach_kdi.c +++ b/usr/src/uts/i86pc/os/mach_kdi.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -40,173 +39,172 @@ #include <sys/smp_impldefs.h> #include <sys/psm_types.h> #include <sys/segments.h> +#include <sys/archsystm.h> +#include <sys/controlregs.h> +#include <sys/trap.h> +#include <sys/kobj.h> +#include <sys/kobj_impl.h> +#include <sys/mach_mmu.h> -static void -kdi_system_claim(void) -{ - psm_notifyf(PSM_DEBUG_ENTER); -} - -static void -kdi_system_release(void) -{ - psm_notifyf(PSM_DEBUG_EXIT); -} - -static cpu_t * -kdi_gdt2cpu(uintptr_t gdtbase) +void +kdi_idt_write(gate_desc_t *gate, uint_t vec) { - cpu_t *cp = cpu_list; + gate_desc_t *idt = CPU->cpu_m.mcpu_idt; - if (cp == NULL) - return (NULL); + /* + * See kdi_idtr_set(). + */ + if (idt == NULL) { + desctbr_t idtr; + rd_idtr(&idtr); + idt = (gate_desc_t *)idtr.dtr_base; + } - do { - if (gdtbase == (uintptr_t)cp->cpu_gdt) - return (cp); - } while ((cp = cp->cpu_next) != cpu_list); + idt[vec] = *gate; +} - return (NULL); +ulong_t +kdi_dreg_get(int reg) +{ + switch (reg) { + case 0: + return (kdi_getdr0()); + case 1: + return (kdi_getdr1()); + case 2: + return (kdi_getdr2()); + case 3: + return (kdi_getdr3()); + case 6: + return (kdi_getdr6()); + case 7: + return (kdi_getdr7()); + default: + panic("invalid debug register dr%d", reg); + /*NOTREACHED*/ + } } -#if defined(__amd64) -static uintptr_t -kdi_gdt2gsbase(uintptr_t gdtbase) -{ - return ((uintptr_t)kdi_gdt2cpu(gdtbase)); +void +kdi_dreg_set(int reg, ulong_t value) +{ + switch (reg) { + case 0: + kdi_setdr0(value); + break; + case 1: + kdi_setdr1(value); + break; + case 2: + kdi_setdr2(value); + break; + case 3: + kdi_setdr3(value); + break; + case 6: + kdi_setdr6(value); + break; + case 7: + kdi_setdr7(value); + break; + default: + panic("invalid debug register dr%d", reg); + /*NOTREACHED*/ + } } -#endif -static void -kdi_cpu_iter(void (*iter)(cpu_t *, uint_t), uint_t arg) +void +kdi_flush_caches(void) { - cpu_t *cp; - - mutex_enter(&cpu_lock); + reload_cr3(); +} - cp = cpu_list; - do { - iter(cp, arg); - } while ((cp = cp->cpu_next) != cpu_list); +extern void kdi_slave_entry(void); - mutex_exit(&cpu_lock); +void +kdi_stop_slaves(int cpu, int doxc) +{ + if (doxc) + kdi_xc_others(cpu, kdi_slave_entry); } -static gate_desc_t * -curidt(void) +/* + * On i86pc, slaves busy-loop, so we don't need to do anything here. + */ +void +kdi_start_slaves(void) { - desctbr_t idtdesc; - rd_idtr(&idtdesc); - return ((gate_desc_t *)idtdesc.dtr_base); } -static void -kdi_idt_init_gate(gate_desc_t *gate, void (*hdlr)(void), uint_t dpl, - int useboot) +void +kdi_slave_wait(void) { - bzero(gate, sizeof (gate_desc_t)); +} + +/* + * Caution. + * These routines are called -extremely- early, during kmdb initialization. + * + * Many common kernel functions assume that %gs has been initialized, + * and fail horribly if it hasn't. At this point, the boot code has + * reserved a descriptor for us (KMDBGS_SEL) in it's GDT; arrange for it + * to point at a dummy cpu_t, temporarily at least. + * + * Note that kmdb entry relies on the fake cpu_t having zero cpu_idt/cpu_id. + */ #if defined(__amd64) - set_gatesegd(gate, hdlr, (useboot ? B64CODE_SEL : KCS_SEL), 0, - SDT_SYSIGT, dpl); -#else - set_gatesegd(gate, hdlr, (useboot ? BOOTCODE_SEL : KCS_SEL), 0, - SDT_SYSIGT, dpl); -#endif -} -static void -kdi_idt_read(gate_desc_t *idt, gate_desc_t *gatep, uint_t vec) +void * +boot_kdi_tmpinit(void) { - if (idt == NULL) - idt = curidt(); - *gatep = idt[vec]; -} + cpu_t *cpu = kobj_zalloc(sizeof (*cpu), KM_TMP); + uintptr_t old; -static void -kdi_idt_write(gate_desc_t *idt, gate_desc_t *gate, uint_t vec) -{ - if (idt == NULL) - idt = curidt(); - idt[vec] = *gate; -} + cpu->cpu_self = cpu; -static gate_desc_t * -kdi_cpu2idt(cpu_t *cp) -{ - if (cp == NULL) - cp = CPU; - return (cp->cpu_idt); + old = (uintptr_t)rdmsr(MSR_AMD_GSBASE); + wrmsr(MSR_AMD_GSBASE, (uint64_t)cpu); + return ((void *)old); } void -kdi_flush_caches(void) +boot_kdi_tmpfini(void *old) { - reload_cr3(); + wrmsr(MSR_AMD_GSBASE, (uint64_t)old); } -static int -kdi_get_cpuinfo(uint_t *vendorp, uint_t *familyp, uint_t *modelp) -{ - desctbr_t gdtr; - cpu_t *cpu; +#elif defined(__i386) - /* - * CPU doesn't work until the GDT and gs/GSBASE have been set up. - * Boot-loaded kmdb will call us well before then, so we have to - * find the current cpu_t the hard way. - */ - rd_gdtr(&gdtr); - if ((cpu = kdi_gdt2cpu(gdtr.dtr_base)) == NULL || - !cpuid_checkpass(cpu, 1)) - return (EAGAIN); /* cpuid isn't done yet */ +void * +boot_kdi_tmpinit(void) +{ + cpu_t *cpu = kobj_zalloc(sizeof (*cpu), KM_TMP); + uintptr_t old; + desctbr_t b_gdtr; + user_desc_t *bgdt; - *vendorp = cpuid_getvendor(cpu); - *familyp = cpuid_getfamily(cpu); - *modelp = cpuid_getmodel(cpu); + cpu->cpu_self = cpu; - return (0); -} + rd_gdtr(&b_gdtr); + bgdt = (user_desc_t *)(b_gdtr.dtr_base); -static void -kdi_plat_call(void (*platfn)(void)) -{ - if (platfn != NULL) - platfn(); -} + set_usegd(&bgdt[GDT_BGSTMP], + cpu, sizeof (*cpu), SDT_MEMRWA, SEL_KPL, SDP_BYTES, SDP_OP32); -void -mach_kdi_init(kdi_t *kdi) -{ - kdi->kdi_plat_call = kdi_plat_call; - kdi->mkdi_get_cpuinfo = kdi_get_cpuinfo; - kdi->mkdi_xc_initialized = kdi_xc_initialized; - kdi->mkdi_xc_others = kdi_xc_others; - kdi->mkdi_get_userlimit = kdi_get_userlimit; - - kdi->mkdi_idt_init_gate = kdi_idt_init_gate; - kdi->mkdi_idt_read = kdi_idt_read; - kdi->mkdi_idt_write = kdi_idt_write; - kdi->mkdi_cpu2idt = kdi_cpu2idt; - - kdi->mkdi_shutdownp = &psm_shutdownf; -#if defined(__amd64) - kdi->mkdi_gdt2gsbase = &kdi_gdt2gsbase; -#endif + /* + * Now switch %gs to point at it. + */ + old = getgs(); + setgs(KMDBGS_SEL); - kdi->mkdi_cpu_iter = kdi_cpu_iter; + return ((void *)old); } -/*ARGSUSED*/ void -mach_kdi_fini(kdi_t *kdi) +boot_kdi_tmpfini(void *old) { - hat_kdi_fini(); + setgs((uintptr_t)old); } -void -plat_kdi_init(kdi_t *kdi) -{ - kdi->pkdi_system_claim = kdi_system_claim; - kdi->pkdi_system_release = kdi_system_release; -} +#endif /* __i386 */ diff --git a/usr/src/uts/i86pc/os/machdep.c b/usr/src/uts/i86pc/os/machdep.c index 3a84df1063..bc2da7f363 100644 --- a/usr/src/uts/i86pc/os/machdep.c +++ b/usr/src/uts/i86pc/os/machdep.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -60,7 +60,6 @@ #include <sys/cmn_err.h> #include <sys/utsname.h> #include <sys/debug.h> -#include <sys/kdi_impl.h> #include <sys/dumphdr.h> #include <sys/bootconf.h> @@ -82,7 +81,6 @@ #include <sys/stack.h> #include <sys/trap.h> #include <sys/pic.h> -#include <sys/mmu.h> #include <vm/hat.h> #include <vm/anon.h> #include <vm/as.h> @@ -115,7 +113,9 @@ #include <sys/x86_archext.h> #include <sys/pool_pset.h> #include <sys/autoconf.h> -#include <sys/kdi.h> +#include <sys/mem.h> +#include <sys/dumphdr.h> +#include <sys/compress.h> #ifdef TRAPTRACE #include <sys/traptrace.h> @@ -264,8 +264,6 @@ resume_other_cpus() xc_release_cpus(); } -extern void mp_halt(char *); - void stop_other_cpus() { @@ -275,12 +273,12 @@ stop_other_cpus() ASSERT(cpuid < NCPU); /* - * xc_trycall will attempt to make all other CPUs execute mp_halt, + * xc_trycall will attempt to make all other CPUs execute mach_cpu_halt, * and will return immediately regardless of whether or not it was * able to make them do it. */ CPUSET_ALL_BUT(xcset, cpuid); - xc_trycall(NULL, NULL, NULL, xcset, (int (*)())mp_halt); + xc_trycall(NULL, NULL, NULL, xcset, (int (*)())mach_cpu_halt); } /* @@ -322,7 +320,7 @@ debug_enter( prom_printf("%s\n", msg); if (boothowto & RB_DEBUG) - kdi_dvec_enter(); + kmdb_enter(); if (dtrace_debugger_fini != NULL) (*dtrace_debugger_fini)(); @@ -363,20 +361,6 @@ halt(char *s) } /* - * Enter monitor. Called via cross-call from stop_other_cpus(). - */ -void -mp_halt(char *msg) -{ - if (msg) - prom_printf("%s\n", msg); - - /*CONSTANTCONDITION*/ - while (1) - ; -} - -/* * Initiate interrupt redistribution. */ void @@ -431,7 +415,7 @@ int sysp_getchar() { int i; - int s; + ulong_t s; if (cons_polledio == NULL) { /* Uh oh */ @@ -450,7 +434,7 @@ sysp_getchar() void sysp_putchar(int c) { - int s; + ulong_t s; /* * We have no alternative but to drop the output on the floor. @@ -469,7 +453,7 @@ int sysp_ischar() { int i; - int s; + ulong_t s; if (cons_polledio == NULL || cons_polledio->cons_polledio_ischar == NULL) @@ -759,7 +743,8 @@ panic_idle(void) splx(ipltospl(CLOCK_LEVEL)); (void) setjmp(&curthread->t_pcb); - for (;;); + for (;;) + ; } /* @@ -826,8 +811,7 @@ panic_dump_hw(int spl) /*ARGSUSED*/ void plat_tod_fault(enum tod_fault_type tod_bad) -{ -} +{} /*ARGSUSED*/ int @@ -874,7 +858,6 @@ void tenmicrosec(void) { extern int tsc_gethrtime_initted; - int i; if (tsc_gethrtime_initted) { hrtime_t start, end; @@ -884,6 +867,8 @@ tenmicrosec(void) end = gethrtime(); } } else { + int i; + /* * Artificial loop to induce delay. */ @@ -979,3 +964,58 @@ get_cpu_mstate(cpu_t *cpu, hrtime_t *times) } scalehrtime(×[CMS_SYSTEM]); } + + +/* + * This is a version of the rdmsr instruction that allows + * an error code to be returned in the case of failure. + */ +int +checked_rdmsr(uint_t msr, uint64_t *value) +{ + if ((x86_feature & X86_MSR) == 0) + return (ENOTSUP); + *value = rdmsr(msr); + return (0); +} + +/* + * This is a version of the wrmsr instruction that allows + * an error code to be returned in the case of failure. + */ +int +checked_wrmsr(uint_t msr, uint64_t value) +{ + if ((x86_feature & X86_MSR) == 0) + return (ENOTSUP); + wrmsr(msr, value); + return (0); +} + +/* + * Return true if the given page VA can be read via /dev/kmem. + */ +/*ARGSUSED*/ +int +plat_mem_valid_page(uintptr_t pageaddr, uio_rw_t rw) +{ + return (0); +} + +int +dump_plat_addr() +{ + return (0); +} + +void +dump_plat_pfn() +{ +} + +/*ARGSUSED*/ +int +dump_plat_data(void *dump_cbuf) +{ + return (0); +} diff --git a/usr/src/uts/i86pc/os/memscrub.c b/usr/src/uts/i86pc/os/memscrub.c index 2e73a2a694..322573ff91 100644 --- a/usr/src/uts/i86pc/os/memscrub.c +++ b/usr/src/uts/i86pc/os/memscrub.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -101,7 +100,7 @@ #include <vm/hat_i86.h> static caddr_t memscrub_window; -static void *memscrub_pte; +static hat_mempte_t memscrub_pte; /* * Global Data: diff --git a/usr/src/uts/i86pc/os/mlsetup.c b/usr/src/uts/i86pc/os/mlsetup.c index 067f417551..f946ed2f5a 100644 --- a/usr/src/uts/i86pc/os/mlsetup.c +++ b/usr/src/uts/i86pc/os/mlsetup.c @@ -26,6 +26,7 @@ #pragma ident "%Z%%M% %I% %E% SMI" #include <sys/types.h> +#include <sys/sysmacros.h> #include <sys/disp.h> #include <sys/promif.h> #include <sys/clock.h> @@ -50,31 +51,13 @@ #include <sys/machsystm.h> #include <sys/ontrap.h> #include <sys/bootconf.h> -#include <sys/kdi.h> +#include <sys/kdi_machimpl.h> #include <sys/archsystm.h> #include <sys/promif.h> #include <sys/bootconf.h> #include <sys/kobj.h> #include <sys/kobj_lex.h> #include <sys/pci_cfgspace.h> -#if defined(__amd64) -#include <sys/bootsvcs.h> - -/* - * XX64 This stuff deals with switching stacks in case a trapping - * thread wants to call back into boot -after- boot has lost track - * of the mappings but before the kernel owns the console. - * - * (A better way to hide this would be to add a 'this' pointer to - * every boot syscall so that vmx could get at the resulting save - * area.) - */ - -struct boot_syscalls *_vmx_sysp; -static struct boot_syscalls __kbootsvcs; -extern struct boot_syscalls *sysp; -extern void _stack_safe_putchar(int c); -#endif /* * some globals for patching the result of cpuid @@ -89,17 +72,11 @@ extern uint32_t cpuid_feature_edx_exclude; /* * Dummy spl priority masks */ -static unsigned char dummy_cpu_pri[MAXIPL + 1] = { +static unsigned char dummy_cpu_pri[MAXIPL + 1] = { 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf }; -/* - * External Routines: - */ - -extern void init_tables(void); - static uint32_t bootprop_getval(char *name) @@ -128,29 +105,6 @@ mlsetup(struct regs *rp) ASSERT_STACK_ALIGNED(); -#if defined(__amd64) - -#if (BS_VERSION > 4) - /* - * When new boot_syscalls are added to the vector, this routine - * must be modified to copy them into the kernel's copy of the - * vector. - */ -#error mlsetup() must be updated for amd64 to support new boot_syscalls -#endif /* (BS_VERSION > 4) */ - - /* - * XX64 This remaps vmx's putchar to use the kernel's version - * that switches stacks before diving into vmx - * See explanation/complaints in commentary above. - */ - _vmx_sysp = sysp; - sysp = &__kbootsvcs; - - sysp->bsvc_getchar = _vmx_sysp->bsvc_getchar; - sysp->bsvc_putchar = _stack_safe_putchar; - sysp->bsvc_ischar = _vmx_sysp->bsvc_ischar; -#endif /* * initialize cpu_self */ @@ -188,46 +142,15 @@ mlsetup(struct regs *rp) * want to set the feature bits to correspond to the feature * minimum) this value may be altered. */ - x86_feature = cpuid_pass1(cpu[0]); /* * Initialize idt0, gdt0, ldt0_default, ktss0 and dftss. */ - init_tables(); - -#if defined(__amd64) - /*CSTYLED*/ - { - /* - * setup %gs for the kernel - */ - wrmsr(MSR_AMD_GSBASE, (uint64_t)&cpus[0]); - /* - * XX64 We should never dereference off "other gsbase" or - * "fsbase". So, we should arrange to point FSBASE and - * KGSBASE somewhere truly awful e.g. point it at the last - * valid address below the hole so that any attempts to index - * off them cause an exception. - * - * For now, point it at 8G -- at least it should be unmapped - * until some 64-bit processes run. - */ - wrmsr(MSR_AMD_FSBASE, 0x200000000UL); - wrmsr(MSR_AMD_KGSBASE, 0x200000000UL); - } + init_desctbls(); -#elif defined(__i386) - /* - * enable large page support right here. - */ - if (x86_feature & X86_LARGEPAGE) { - cr4_value |= CR4_PSE; - if (x86_feature & X86_PGE) - cr4_value |= CR4_PGE; - setup_121_andcall(enable_big_page_support, cr4_value); - } +#if defined(__i386) /* * Some i386 processors do not implement the rdtsc instruction, * or at least they do not implement it correctly. @@ -238,7 +161,22 @@ mlsetup(struct regs *rp) */ if (x86_feature & X86_TSC) patch_tsc(); -#endif +#endif /* __i386 */ + + /* + * While we're thinking about the TSC, let's set up %cr4 so that + * userland can issue rdtsc, and initialize the TSC_AUX value + * (the cpuid) for the rdtscp instruction on appropriately + * capable hardware. + */ + if (x86_feature & X86_TSC) + setcr4(getcr4() & ~CR4_TSD); + + if (x86_feature & X86_TSCP) + (void) wrmsr(MSR_AMD_TSCAUX, 0); + + if (x86_feature & X86_DE) + setcr4(getcr4() | CR4_DE); /* * initialize t0 @@ -264,7 +202,7 @@ mlsetup(struct regs *rp) THREAD_ONPROC(&t0, CPU); lwp0.lwp_thread = &t0; - lwp0.lwp_regs = (void *) rp; + lwp0.lwp_regs = (void *)rp; lwp0.lwp_procp = &p0; t0.t_tid = p0.p_lwpcnt = p0.p_lwprcnt = p0.p_lwpid = 1; @@ -290,24 +228,15 @@ mlsetup(struct regs *rp) CPU->cpu_id = 0; - CPU->cpu_tss = &ktss0; - CPU->cpu_pri = 12; /* initial PIL for the boot CPU */ - CPU->cpu_gdt = gdt0; - /* * The kernel doesn't use LDTs unless a process explicitly requests one. */ p0.p_ldt_desc = zero_sdesc; /* - * Kernel IDT. - */ - CPU->cpu_idt = idt0; - - /* - * Initialize thread/cpu microstate accounting here + * Initialize thread/cpu microstate accounting */ init_mstate(&t0, LMS_SYSTEM); init_cpu_mstate(CPU, CMS_SYSTEM); @@ -317,6 +246,23 @@ mlsetup(struct regs *rp) */ cpu_list_init(CPU); + /* + * Now that we have taken over the GDT, IDT and have initialized + * active CPU list it's time to inform kmdb if present. + */ + if (boothowto & RB_DEBUG) + kdi_idt_sync(); + + /* + * If requested (boot -d) drop into kmdb. + * + * This must be done after cpu_list_init() on the 64-bit kernel + * since taking a trap requires that we re-compute gsbase based + * on the cpu list. + */ + if (boothowto & RB_DEBUGENTER) + kmdb_enter(); + cpu_vm_data_init(CPU); /* lgrp_init() needs PCI config space access */ @@ -333,16 +279,8 @@ mlsetup(struct regs *rp) boot_ncpus = bootprop_getval("boot-ncpus"); - /* - * To avoid wasting kernel memory, we're temporarily limiting the - * total number of processors to 32 by default until we get the - * capability to scan ACPI tables early on boot to detect how many - * processors are actually present. However, 64-bit systems - * can be booted with up to 64 processors by setting "boot-ncpus" - * boot property to 64. - */ if (boot_ncpus <= 0 || boot_ncpus > NCPU) - boot_ncpus = 32; + boot_ncpus = NCPU; max_ncpus = boot_max_ncpus = boot_ncpus; diff --git a/usr/src/uts/i86pc/os/mp_call.c b/usr/src/uts/i86pc/os/mp_call.c index 0dd9e9db4c..581dcbd631 100644 --- a/usr/src/uts/i86pc/os/mp_call.c +++ b/usr/src/uts/i86pc/os/mp_call.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,9 +18,10 @@ * * CDDL HEADER END */ + /* - * Copyright (c) 1990-1993, 1999 by Sun Microsystems, Inc. - * All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -32,6 +32,8 @@ #include <sys/cpuvar.h> #include <sys/machsystm.h> #include <sys/systm.h> +#include <sys/promif.h> +#include <sys/x_call.h> /* * Interrupt another CPU. @@ -46,10 +48,12 @@ void poke_cpu(int cpun) { + if (panicstr) + return; /* * We don't need to receive an ACK from the CPU being poked, * so just send out a directed interrupt. */ - if (!panicstr) - send_dirint(cpun, XC_CPUPOKE_PIL); + XC_TRACE(TT_XC_POKE_CPU, -1, cpun); + send_dirint(cpun, XC_CPUPOKE_PIL); } diff --git a/usr/src/uts/i86pc/os/mp_implfuncs.c b/usr/src/uts/i86pc/os/mp_implfuncs.c index 5032c16b20..cad5365b08 100644 --- a/usr/src/uts/i86pc/os/mp_implfuncs.c +++ b/usr/src/uts/i86pc/os/mp_implfuncs.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -212,7 +211,7 @@ psm_map_phys_new(paddr_t addr, size_t len, int prot) return (0); pgoffset = addr & MMU_PAGEOFFSET; - base = addr - pgoffset; + base = addr; npages = mmu_btopr(len + pgoffset); cvaddr = device_arena_alloc(ptob(npages), VM_NOSLEEP); if (cvaddr == NULL) @@ -331,12 +330,14 @@ mod_infopsm(struct modlpsm *modl, struct modlinkage *modlp, int *p0) return (0); } +#define DEFAULT_PSM_MODULE "uppc" + static char * psm_get_impl_module(int first) { static char **pnamep; static char *psm_impl_module_list[] = { - "uppc", + DEFAULT_PSM_MODULE, (char *)0 }; static void *mhdl = NULL; diff --git a/usr/src/uts/i86pc/os/mp_machdep.c b/usr/src/uts/i86pc/os/mp_machdep.c index c2e3123a24..f7d3a802f7 100644 --- a/usr/src/uts/i86pc/os/mp_machdep.c +++ b/usr/src/uts/i86pc/os/mp_machdep.c @@ -40,8 +40,10 @@ #include <sys/cpuvar.h> #include <sys/pghw.h> #include <sys/disp.h> -#include <sys/cpu.h> #include <sys/archsystm.h> +#include <sys/machsystm.h> +#include <sys/param.h> +#include <sys/promif.h> #include <sys/mach_intr.h> #define OFFSETOF(s, m) (size_t)(&(((s *)0)->m)) @@ -60,27 +62,21 @@ static void mach_fixcpufreq(void); static int mach_clkinit(int, int *); static void mach_smpinit(void); static void mach_set_softintr(int ipl, struct av_softinfo *); -static void mach_cpu_start(int cpun); static int mach_softlvl_to_vect(int ipl); static void mach_get_platform(int owner); static void mach_construct_info(); static int mach_translate_irq(dev_info_t *dip, int irqno); static int mach_intr_ops(dev_info_t *, ddi_intr_handle_impl_t *, psm_intr_op_t, int *); -static timestruc_t mach_tod_get(void); -static void mach_tod_set(timestruc_t ts); static void mach_notify_error(int level, char *errmsg); static hrtime_t dummy_hrtime(void); static void dummy_scalehrtime(hrtime_t *); -static void cpu_halt(void); +static void cpu_idle(void); static void cpu_wakeup(cpu_t *, int); /* * External reference functions */ extern void return_instr(); -extern timestruc_t (*todgetf)(void); -extern void (*todsetf)(timestruc_t); -extern long gmt_lag; extern uint64_t freq_tsc(uint32_t *); #if defined(__i386) extern uint64_t freq_notsc(uint32_t *); @@ -92,18 +88,17 @@ extern int cpuid_get_chipid(cpu_t *); /* * PSM functions initialization */ -void (*psm_shutdownf)(int, int) = return_instr; -void (*psm_preshutdownf)(int, int) = return_instr; -void (*psm_notifyf)(int) = return_instr; -void (*psm_set_idle_cpuf)(int) = return_instr; -void (*psm_unset_idle_cpuf)(int) = return_instr; +void (*psm_shutdownf)(int, int) = (void (*)(int, int))return_instr; +void (*psm_preshutdownf)(int, int) = (void (*)(int, int))return_instr; +void (*psm_notifyf)(int) = (void (*)(int))return_instr; +void (*psm_set_idle_cpuf)(int) = (void (*)(int))return_instr; +void (*psm_unset_idle_cpuf)(int) = (void (*)(int))return_instr; void (*psminitf)() = mach_init; void (*picinitf)() = return_instr; int (*clkinitf)(int, int *) = (int (*)(int, int *))return_instr; -void (*cpu_startf)() = return_instr; int (*ap_mlsetup)() = (int (*)(void))return_instr; void (*send_dirintf)() = return_instr; -void (*setspl)(int) = return_instr; +void (*setspl)(int) = (void (*)(int))return_instr; int (*addspl)(int, int, int, int) = (int (*)(int, int, int, int))return_instr; int (*delspl)(int, int, int, int) = (int (*)(int, int, int, int))return_instr; void (*setsoftint)(int, struct av_softinfo *)= @@ -118,8 +113,6 @@ hrtime_t (*gethrtimeunscaledf)(void) = dummy_hrtime; void (*scalehrtimef)(hrtime_t *) = dummy_scalehrtime; int (*psm_translate_irq)(dev_info_t *, int) = mach_translate_irq; void (*gethrestimef)(timestruc_t *) = pc_gethrestime; -int (*psm_todgetf)(todinfo_t *) = (int (*)(todinfo_t *))return_instr; -int (*psm_todsetf)(todinfo_t *) = (int (*)(todinfo_t *))return_instr; void (*psm_notify_error)(int, char *) = (void (*)(int, char *))NULL; int (*psm_get_clockirq)(int) = NULL; int (*psm_get_ipivect)(int, int) = NULL; @@ -146,25 +139,10 @@ static struct psm_ops *mach_set[4] = {&mach_ops, NULL, NULL, NULL}; static ushort_t mach_ver[4] = {0, 0, 0, 0}; /* - * If non-zero, idle cpus will "halted" when there's + * If non-zero, idle cpus will become "halted" when there's * no work to do. */ -int halt_idle_cpus = 1; - -#if defined(__amd64) -/* - * If non-zero, will use cr8 for interrupt priority masking - * We declare this here since install_spl is called from here - * (where this is checked). - */ -int intpri_use_cr8 = 0; -#endif /* __amd64 */ - -#ifdef _SIMULATOR_SUPPORT - -int simulator_run = 0; /* patch to non-zero if running under simics */ - -#endif /* _SIMULATOR_SUPPORT */ +int idle_cpu_use_hlt = 1; /*ARGSUSED*/ @@ -271,10 +249,10 @@ dummy_scalehrtime(hrtime_t *ticks) {} /* - * Halt the present CPU until awoken via an interrupt + * Idle the present CPU until awoken via an interrupt */ static void -cpu_halt(void) +cpu_idle(void) { cpu_t *cpup = CPU; processorid_t cpun = cpup->cpu_id; @@ -339,7 +317,7 @@ cpu_halt(void) * This means that the ordering of the poke and the clearing * of the bit by cpu_wakeup is important. * cpu_wakeup() must clear, then poke. - * cpu_halt() must disable interrupts, then check for the bit. + * cpu_idle() must disable interrupts, then check for the bit. */ cli(); @@ -364,12 +342,7 @@ cpu_halt(void) return; } - /* - * Call the halt sequence: - * sti - * hlt - */ - i86_halt(); + mach_cpu_idle(); /* * We're no longer halted @@ -404,7 +377,7 @@ cpu_wakeup(cpu_t *cpu, int bound) /* * We may find the current CPU present in the halted cpuset * if we're in the context of an interrupt that occurred - * before we had a chance to clear our bit in cpu_halt(). + * before we had a chance to clear our bit in cpu_idle(). * Poking ourself is obviously unnecessary, since if * we're here, we're not halted. */ @@ -449,6 +422,8 @@ cpu_wakeup(cpu_t *cpu, int bound) poke_cpu(cpu_found); } +void (*cpu_pause_handler)(volatile char *) = NULL; + static int mp_disable_intr(int cpun) { @@ -533,7 +508,7 @@ mach_get_platform(int owner) static void mach_construct_info() { - register struct psm_sw *swp; + struct psm_sw *swp; int mach_cnt[PSM_OWN_OVERRIDE+1] = {0}; int conflict_owner = 0; @@ -584,7 +559,7 @@ mach_construct_info() static void mach_init() { - register struct psm_ops *pops; + struct psm_ops *pops; mach_construct_info(); @@ -604,14 +579,22 @@ mach_init() psm_translate_irq = pops->psm_translate_irq; if (pops->psm_intr_ops) psm_intr_ops = pops->psm_intr_ops; - if (pops->psm_tod_get) { - todgetf = mach_tod_get; - psm_todgetf = pops->psm_tod_get; - } - if (pops->psm_tod_set) { - todsetf = mach_tod_set; - psm_todsetf = pops->psm_tod_set; - } + +#if defined(PSMI_1_2) || defined(PSMI_1_3) || defined(PSMI_1_4) + /* + * Time-of-day functionality now handled in TOD modules. + * (Warn about PSM modules that think that we're going to use + * their ops vectors.) + */ + if (pops->psm_tod_get) + cmn_err(CE_WARN, "obsolete psm_tod_get op %p", + (void *)pops->psm_tod_get); + + if (pops->psm_tod_set) + cmn_err(CE_WARN, "obsolete psm_tod_set op %p", + (void *)pops->psm_tod_set); +#endif + if (pops->psm_notify_error) { psm_notify_error = mach_notify_error; notify_error = pops->psm_notify_error; @@ -623,13 +606,8 @@ mach_init() * Initialize the dispatcher's function hooks * to enable CPU halting when idle */ -#if defined(_SIMULATOR_SUPPORT) - if (halt_idle_cpus && !simulator_run) - idle_cpu = cpu_halt; -#else - if (halt_idle_cpus) - idle_cpu = cpu_halt; -#endif /* _SIMULATOR_SUPPORT */ + if (idle_cpu_use_hlt) + idle_cpu = cpu_idle; mach_smpinit(); } @@ -654,7 +632,6 @@ mach_smpinit(void) mp_cpus = cpumask; /* MP related routines */ - cpu_startf = mach_cpu_start; ap_mlsetup = pops->psm_post_cpu_start; send_dirintf = pops->psm_send_ipi; @@ -696,15 +673,8 @@ mach_smpinit(void) * Set the dispatcher hook to enable cpu "wake up" * when a thread becomes runnable. */ -#if defined(_SIMULATOR_SUPPORT) - if (halt_idle_cpus && !simulator_run) { - disp_enq_thread = cpu_wakeup; - } -#else - if (halt_idle_cpus) { + if (idle_cpu_use_hlt) disp_enq_thread = cpu_wakeup; - } -#endif /* _SIMULATOR_SUPPORT */ if (pops->psm_disable_intr) psm_disable_intr = pops->psm_disable_intr; @@ -727,10 +697,6 @@ static void mach_picinit() { struct psm_ops *pops; - extern void install_spl(void); /* XXX: belongs in a header file */ -#if defined(__amd64) && defined(DEBUG) - extern void *spl_patch, *slow_spl, *setsplhi_patch, *slow_setsplhi; -#endif pops = mach_set[0]; @@ -743,17 +709,8 @@ mach_picinit() /* set interrupt mask for current ipl */ setspl = pops->psm_setspl; + cli(); setspl(CPU->cpu_pri); - - /* Install proper spl routine now that we can Program the PIC */ -#if defined(__amd64) - /* - * It would be better if we could check this at compile time - */ - ASSERT(((uintptr_t)&slow_setsplhi - (uintptr_t)&setsplhi_patch < 128) && - ((uintptr_t)&slow_spl - (uintptr_t)&spl_patch < 128)); -#endif - install_spl(); } uint_t cpu_freq; /* MHz */ @@ -786,7 +743,9 @@ mach_getcpufreq(void) * We have a TSC. freq_tsc() knows how to measure the number * of clock cycles sampled against the PIT. */ + ulong_t flags = clear_int_flag(); processor_clks = freq_tsc(&pit_counter); + restore_int_flag(flags); return (mach_calchz(pit_counter, &processor_clks)); } else if (x86_vendor == X86_VENDOR_Cyrix || x86_type == X86_TYPE_P5) { #if defined(__amd64) @@ -797,7 +756,9 @@ mach_getcpufreq(void) * for which freq_notsc() knows how to measure the number of * elapsed clock cycles sampled against the PIT */ + ulong_t flags = clear_int_flag(); processor_clks = freq_notsc(&pit_counter); + restore_int_flag(flags); return (mach_calchz(pit_counter, &processor_clks)); #endif /* __i386 */ } @@ -939,19 +900,12 @@ machhztomhz(uint64_t cpu_freq_hz) static int mach_clkinit(int preferred_mode, int *set_mode) { - register struct psm_ops *pops; + struct psm_ops *pops; int resolution; pops = mach_set[0]; -#ifdef _SIMULATOR_SUPPORT - if (!simulator_run) - cpu_freq_hz = mach_getcpufreq(); - else - cpu_freq_hz = 40000000; /* use 40 Mhz (hack for simulator) */ -#else cpu_freq_hz = mach_getcpufreq(); -#endif /* _SIMULATOR_SUPPORT */ cpu_freq = machhztomhz(cpu_freq_hz); @@ -1013,7 +967,7 @@ mach_clkinit(int preferred_mode, int *set_mode) static void mach_psm_set_softintr(int ipl, struct av_softinfo *pending) { - register struct psm_ops *pops; + struct psm_ops *pops; /* invoke hardware interrupt */ pops = mach_set[0]; @@ -1021,10 +975,10 @@ mach_psm_set_softintr(int ipl, struct av_softinfo *pending) } static int -mach_softlvl_to_vect(register int ipl) +mach_softlvl_to_vect(int ipl) { - register int softvect; - register struct psm_ops *pops; + int softvect; + struct psm_ops *pops; pops = mach_set[0]; @@ -1050,9 +1004,9 @@ mach_softlvl_to_vect(register int ipl) } static void -mach_set_softintr(register int ipl, struct av_softinfo *pending) +mach_set_softintr(int ipl, struct av_softinfo *pending) { - register struct psm_ops *pops; + struct psm_ops *pops; /* set software pending bits */ av_set_softint_pending(ipl, pending); @@ -1066,14 +1020,24 @@ mach_set_softintr(register int ipl, struct av_softinfo *pending) (*pops->psm_set_softintr)(ipl); } -static void -mach_cpu_start(register int cpun) -{ - struct psm_ops *pops; +#ifdef DEBUG +/* + * This is here to allow us to simulate cpus that refuse to start. + */ +cpuset_t cpufailset; +#endif - pops = mach_set[0]; +int +mach_cpu_start(struct cpu *cp, void *ctx) +{ + struct psm_ops *pops = mach_set[0]; + processorid_t id = cp->cpu_id; - (*pops->psm_cpu_start)(cpun, rm_platter_va); +#ifdef DEBUG + if (CPU_IN_SET(cpufailset, id)) + return (0); +#endif + return ((*pops->psm_cpu_start)(id, ctx)); } /*ARGSUSED*/ @@ -1083,53 +1047,6 @@ mach_translate_irq(dev_info_t *dip, int irqno) return (irqno); /* default to NO translation */ } -static timestruc_t -mach_tod_get(void) -{ - timestruc_t ts; - todinfo_t tod; - static int mach_range_warn = 1; /* warn only once */ - - ASSERT(MUTEX_HELD(&tod_lock)); - - /* The year returned from is the last 2 digit only */ - if ((*psm_todgetf)(&tod)) { - ts.tv_sec = 0; - ts.tv_nsec = 0; - tod_fault_reset(); - return (ts); - } - - /* assume that we wrap the rtc year back to zero at 2000 */ - if (tod.tod_year < 69) { - if (mach_range_warn && tod.tod_year > 38) { - cmn_err(CE_WARN, "hardware real-time clock is out " - "of range -- time needs to be reset"); - mach_range_warn = 0; - } - tod.tod_year += 100; - } - - /* tod_to_utc uses 1900 as base for the year */ - ts.tv_sec = tod_to_utc(tod) + gmt_lag; - ts.tv_nsec = 0; - - return (ts); -} - -static void -mach_tod_set(timestruc_t ts) -{ - todinfo_t tod = utc_to_tod(ts.tv_sec - gmt_lag); - - ASSERT(MUTEX_HELD(&tod_lock)); - - if (tod.tod_year >= 100) - tod.tod_year -= 100; - - (*psm_todsetf)(&tod); -} - static void mach_notify_error(int level, char *errmsg) { diff --git a/usr/src/uts/i86pc/os/mp_pc.c b/usr/src/uts/i86pc/os/mp_pc.c new file mode 100644 index 0000000000..293750e1ec --- /dev/null +++ b/usr/src/uts/i86pc/os/mp_pc.c @@ -0,0 +1,287 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Welcome to the world of the "real mode platter". + * See also startup.c, mpcore.s and apic.c for related routines. + */ + +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/cpuvar.h> +#include <sys/kmem.h> +#include <sys/archsystm.h> +#include <sys/machsystm.h> +#include <sys/controlregs.h> +#include <sys/x86_archext.h> +#include <sys/smp_impldefs.h> +#include <sys/sysmacros.h> +#include <sys/mach_mmu.h> +#include <sys/promif.h> +#include <sys/cpu.h> + +extern void real_mode_start(void); +extern void real_mode_end(void); + +/* + * Fill up the real mode platter to make it easy for real mode code to + * kick it off. This area should really be one passed by boot to kernel + * and guaranteed to be below 1MB and aligned to 16 bytes. Should also + * have identical physical and virtual address in paged mode. + */ +static ushort_t *warm_reset_vector = NULL; + +int +mach_cpucontext_init(void) +{ + ushort_t *vec; + + if (!(vec = (ushort_t *)psm_map_phys(WARM_RESET_VECTOR, + sizeof (vec), PROT_READ | PROT_WRITE))) + return (-1); + /* + * setup secondary cpu bios boot up vector + */ + *vec = (ushort_t)((caddr_t) + ((struct rm_platter *)rm_platter_va)->rm_code - rm_platter_va + + ((ulong_t)rm_platter_va & 0xf)); + vec[1] = (ushort_t)(rm_platter_pa >> 4); + warm_reset_vector = vec; + + bcopy((caddr_t)real_mode_start, + (caddr_t)((rm_platter_t *)rm_platter_va)->rm_code, + (size_t)real_mode_end - (size_t)real_mode_start); + + return (0); +} + +void +mach_cpucontext_fini(void) +{ + if (warm_reset_vector) + psm_unmap_phys((caddr_t)warm_reset_vector, + sizeof (warm_reset_vector)); + hat_unload(kas.a_hat, (caddr_t)(uintptr_t)rm_platter_pa, MMU_PAGESIZE, + HAT_UNLOAD); +} + +#if defined(__amd64) +extern void *long_mode_64(void); +#endif /* __amd64 */ + +void * +mach_cpucontext_alloc(struct cpu *cp) +{ + rm_platter_t *rm = (rm_platter_t *)rm_platter_va; + struct cpu_tables *ct; + struct tss *ntss; + + /* + * Allocate space for page directory, stack, tss, gdt and idt. + * The page directory has to be page aligned + */ + ct = kmem_zalloc(sizeof (*ct), KM_SLEEP); + if ((uintptr_t)ct & ~MMU_STD_PAGEMASK) + panic("mp_startup_init: cpu%d misaligned tables", cp->cpu_id); + + ntss = cp->cpu_tss = &ct->ct_tss; + +#if defined(__amd64) + + /* + * #DF (double fault). + */ + ntss->tss_ist1 = (uint64_t)&ct->ct_stack[sizeof (ct->ct_stack)]; + +#elif defined(__i386) + + ntss->tss_esp0 = ntss->tss_esp1 = ntss->tss_esp2 = ntss->tss_esp = + (uint32_t)&ct->ct_stack[sizeof (ct->ct_stack)]; + + ntss->tss_ss0 = ntss->tss_ss1 = ntss->tss_ss2 = ntss->tss_ss = KDS_SEL; + + ntss->tss_eip = (uint32_t)cp->cpu_thread->t_pc; + + ntss->tss_cs = KCS_SEL; + ntss->tss_ds = ntss->tss_es = KDS_SEL; + ntss->tss_fs = KFS_SEL; + ntss->tss_gs = KGS_SEL; + +#endif /* __i386 */ + + /* + * Set I/O bit map offset equal to size of TSS segment limit + * for no I/O permission map. This will cause all user I/O + * instructions to generate #gp fault. + */ + ntss->tss_bitmapbase = sizeof (*ntss); + + /* + * Setup kernel tss. + */ + set_syssegd((system_desc_t *)&cp->cpu_gdt[GDT_KTSS], cp->cpu_tss, + sizeof (*cp->cpu_tss) -1, SDT_SYSTSS, SEL_KPL); + + /* + * Now copy all that we've set up onto the real mode platter + * for the real mode code to digest as part of starting the cpu. + */ + + rm->rm_idt_base = cp->cpu_idt; + rm->rm_idt_lim = sizeof (idt0) - 1; + rm->rm_gdt_base = cp->cpu_gdt; + rm->rm_gdt_lim = ((sizeof (*cp->cpu_gdt) * NGDT)) -1; + + rm->rm_pdbr = getcr3(); + rm->rm_cpu = cp->cpu_id; + rm->rm_x86feature = x86_feature; + rm->rm_cr4 = getcr4(); + +#if defined(__amd64) + + if (getcr3() > 0xffffffffUL) + panic("Cannot initialize CPUs; kernel's 64-bit page tables\n" + "located above 4G in physical memory (@ 0x%lx)", getcr3()); + + /* + * Setup pseudo-descriptors for temporary GDT and IDT for use ONLY + * by code in real_mode_start(): + * + * GDT[0]: NULL selector + * GDT[1]: 64-bit CS: Long = 1, Present = 1, bits 12, 11 = 1 + * + * Clear the IDT as interrupts will be off and a limit of 0 will cause + * the CPU to triple fault and reset on an NMI, seemingly as reasonable + * a course of action as any other, though it may cause the entire + * platform to reset in some cases... + */ + rm->rm_temp_gdt[0] = 0; + rm->rm_temp_gdt[TEMPGDT_KCODE64] = 0x20980000000000ULL; + + rm->rm_temp_gdt_lim = (ushort_t)(sizeof (rm->rm_temp_gdt) - 1); + rm->rm_temp_gdt_base = rm_platter_pa + + (uint32_t)offsetof(rm_platter_t, rm_temp_gdt); + rm->rm_temp_idt_lim = 0; + rm->rm_temp_idt_base = 0; + + /* + * Since the CPU needs to jump to protected mode using an identity + * mapped address, we need to calculate it here. + */ + rm->rm_longmode64_addr = rm_platter_pa + + ((uint32_t)long_mode_64 - (uint32_t)real_mode_start); +#endif /* __amd64 */ + + return (ct); +} + +/*ARGSUSED*/ +void +mach_cpucontext_free(struct cpu *cp, void *arg, int err) +{ + struct cpu_tables *ct = arg; + + ASSERT(&ct->ct_tss == cp->cpu_tss); + + switch (err) { + case 0: + break; + case ETIMEDOUT: + /* + * The processor was poked, but failed to start before + * we gave up waiting for it. In case it starts later, + * don't free anything. + */ + break; + default: + /* + * Some other, passive, error occurred. + */ + kmem_free(ct, sizeof (*ct)); + cp->cpu_tss = NULL; + break; + } +} + +/* + * "Enter monitor." Called via cross-call from stop_other_cpus(). + */ +void +mach_cpu_halt(char *msg) +{ + if (msg) + prom_printf("%s\n", msg); + + /*CONSTANTCONDITION*/ + while (1) + ; +} + +void +mach_cpu_idle(void) +{ + i86_halt(); +} + +void +mach_cpu_pause(volatile char *safe) +{ + /* + * This cpu is now safe. + */ + *safe = PAUSE_WAIT; + membar_enter(); /* make sure stores are flushed */ + + /* + * Now we wait. When we are allowed to continue, safe + * will be set to PAUSE_IDLE. + */ + while (*safe != PAUSE_IDLE) + SMT_PAUSE(); +} + +/* + * Power on CPU. + */ +/*ARGSUSED*/ +int +mp_cpu_poweron(struct cpu *cp) +{ + ASSERT(MUTEX_HELD(&cpu_lock)); + return (ENOTSUP); /* not supported */ +} + +/* + * Power off CPU. + */ +/*ARGSUSED*/ +int +mp_cpu_poweroff(struct cpu *cp) +{ + ASSERT(MUTEX_HELD(&cpu_lock)); + return (ENOTSUP); /* not supported */ +} diff --git a/usr/src/uts/i86pc/os/mp_startup.c b/usr/src/uts/i86pc/os/mp_startup.c index 5fd2325888..96a3a1e628 100644 --- a/usr/src/uts/i86pc/os/mp_startup.c +++ b/usr/src/uts/i86pc/os/mp_startup.c @@ -18,6 +18,7 @@ * * CDDL HEADER END */ + /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -32,7 +33,6 @@ #include <sys/param.h> #include <sys/proc.h> #include <sys/disp.h> -#include <sys/mmu.h> #include <sys/class.h> #include <sys/cmn_err.h> #include <sys/debug.h> @@ -42,9 +42,9 @@ #include <sys/var.h> #include <sys/vtrace.h> #include <vm/hat.h> -#include <sys/mmu.h> #include <vm/as.h> #include <vm/seg_kmem.h> +#include <vm/seg_kp.h> #include <sys/segments.h> #include <sys/kmem.h> #include <sys/stack.h> @@ -60,10 +60,12 @@ #include <sys/archsystm.h> #include <sys/fp.h> #include <sys/reboot.h> -#include <sys/kdi.h> +#include <sys/kdi_machimpl.h> #include <vm/hat_i86.h> #include <sys/memnode.h> #include <sys/pci_cfgspace.h> +#include <sys/mach_mmu.h> +#include <sys/sysmacros.h> #include <sys/cpu_module.h> struct cpu cpus[1]; /* CPU data */ @@ -71,15 +73,15 @@ struct cpu *cpu[NCPU] = {&cpus[0]}; /* pointers to all CPUs */ cpu_core_t cpu_core[NCPU]; /* cpu_core structures */ /* - * Useful for disabling MP bring-up for an MP capable kernel - * (a kernel that was built with MP defined) + * Useful for disabling MP bring-up on a MP capable system. */ int use_mp = 1; /* - * To be set by a PSM to indicate what CPUs are available on the system. + * to be set by a PSM to indicate what cpus + * are sitting around on the system. */ -cpuset_t mp_cpus = 1; +cpuset_t mp_cpus; /* * This variable is used by the hat layer to decide whether or not @@ -87,11 +89,9 @@ cpuset_t mp_cpus = 1; * this variable is set once enough MP initialization has been done in * order to allow cross calls. */ -int flushes_require_xcalls = 0; -cpuset_t cpu_ready_set = 1; +int flushes_require_xcalls; +cpuset_t cpu_ready_set = 1; -extern void real_mode_start(void); -extern void real_mode_end(void); static void mp_startup(void); static void cpu_sep_enable(void); @@ -143,7 +143,7 @@ init_cpu_syscall(struct cpu *cp) kpreempt_disable(); #if defined(__amd64) - if (x86_feature & X86_ASYSC) { + if ((x86_feature & (X86_MSR | X86_ASYSC)) == (X86_MSR | X86_ASYSC)) { #if !defined(__lint) /* @@ -163,8 +163,8 @@ init_cpu_syscall(struct cpu *cp) /* * Program the magic registers .. */ - wrmsr(MSR_AMD_STAR, ((uint64_t)(U32CS_SEL << 16 | KCS_SEL)) << - 32); + wrmsr(MSR_AMD_STAR, + ((uint64_t)(U32CS_SEL << 16 | KCS_SEL)) << 32); wrmsr(MSR_AMD_LSTAR, (uint64_t)(uintptr_t)sys_syscall); wrmsr(MSR_AMD_CSTAR, (uint64_t)(uintptr_t)sys_syscall32); @@ -183,7 +183,7 @@ init_cpu_syscall(struct cpu *cp) * On 64-bit kernels on Nocona machines, the 32-bit syscall * variant isn't available to 32-bit applications, but sysenter is. */ - if (x86_feature & X86_SEP) { + if ((x86_feature & (X86_MSR | X86_SEP)) == (X86_MSR | X86_SEP)) { #if !defined(__lint) /* @@ -208,7 +208,7 @@ init_cpu_syscall(struct cpu *cp) * resume() sets this value to the base of the threads stack * via a context handler. */ - wrmsr(MSR_INTC_SEP_ESP, 0ULL); + wrmsr(MSR_INTC_SEP_ESP, 0); wrmsr(MSR_INTC_SEP_EIP, (uint64_t)(uintptr_t)sys_sysenter); } @@ -221,35 +221,22 @@ init_cpu_syscall(struct cpu *cp) * Allocate and initialize the cpu structure, TRAPTRACE buffer, and the * startup and idle threads for the specified CPU. */ -static void +struct cpu * mp_startup_init(int cpun) { -#if defined(__amd64) -extern void *long_mode_64(void); -#endif /* __amd64 */ - struct cpu *cp; - struct tss *ntss; kthread_id_t tp; caddr_t sp; - int size; proc_t *procp; extern void idle(); - struct cpu_tables *tablesp; - rm_platter_t *real_mode_platter = (rm_platter_t *)rm_platter_va; - #ifdef TRAPTRACE trap_trace_ctl_t *ttc = &trap_trace_ctl[cpun]; #endif ASSERT(cpun < NCPU && cpu[cpun] == NULL); - if ((cp = kmem_zalloc(sizeof (*cp), KM_NOSLEEP)) == NULL) { - panic("mp_startup_init: cpu%d: " - "no memory for cpu structure", cpun); - /*NOTREACHED*/ - } + cp = kmem_zalloc(sizeof (*cp), KM_SLEEP); procp = curthread->t_procp; mutex_enter(&cpu_lock); @@ -289,6 +276,9 @@ extern void *long_mode_64(void); sp = tp->t_stk; tp->t_pc = (uintptr_t)mp_startup; tp->t_sp = (uintptr_t)(sp - MINFRAME); +#if defined(__amd64) + tp->t_sp -= STACK_ENTRY_ALIGN; /* fake a call */ +#endif cp->cpu_id = cpun; cp->cpu_self = cp; @@ -327,7 +317,7 @@ extern void *long_mode_64(void); pg_cpu_bootstrap(cp); /* - * Perform CPC intialization on the new CPU. + * Perform CPC initialization on the new CPU. */ kcpc_hw_init(cp); @@ -335,77 +325,25 @@ extern void *long_mode_64(void); * Allocate virtual addresses for cpu_caddr1 and cpu_caddr2 * for each CPU. */ - setup_vaddr_for_ppcopy(cp); /* - * Allocate space for page directory, stack, tss, gdt and idt. - * This assumes that kmem_alloc will return memory which is aligned - * to the next higher power of 2 or a page(if size > MAXABIG) - * If this assumption goes wrong at any time due to change in - * kmem alloc, things may not work as the page directory has to be - * page aligned + * Allocate page for new GDT and initialize from current GDT. */ - if ((tablesp = kmem_zalloc(sizeof (*tablesp), KM_NOSLEEP)) == NULL) - panic("mp_startup_init: cpu%d cannot allocate tables", cpun); - - if ((uintptr_t)tablesp & ~MMU_STD_PAGEMASK) { - kmem_free(tablesp, sizeof (struct cpu_tables)); - size = sizeof (struct cpu_tables) + MMU_STD_PAGESIZE; - tablesp = kmem_zalloc(size, KM_NOSLEEP); - tablesp = (struct cpu_tables *) - (((uintptr_t)tablesp + MMU_STD_PAGESIZE) & - MMU_STD_PAGEMASK); - } - - ntss = cp->cpu_tss = &tablesp->ct_tss; - - if ((tablesp->ct_gdt = kmem_zalloc(PAGESIZE, KM_NOSLEEP)) == NULL) - panic("mp_startup_init: cpu%d cannot allocate GDT", cpun); - cp->cpu_gdt = tablesp->ct_gdt; - bcopy(CPU->cpu_gdt, cp->cpu_gdt, NGDT * (sizeof (user_desc_t))); - -#if defined(__amd64) - - /* - * #DF (double fault). - */ - ntss->tss_ist1 = - (uint64_t)&tablesp->ct_stack[sizeof (tablesp->ct_stack)]; - -#elif defined(__i386) - - ntss->tss_esp0 = ntss->tss_esp1 = ntss->tss_esp2 = ntss->tss_esp = - (uint32_t)&tablesp->ct_stack[sizeof (tablesp->ct_stack)]; - - ntss->tss_ss0 = ntss->tss_ss1 = ntss->tss_ss2 = ntss->tss_ss = KDS_SEL; - - ntss->tss_eip = (uint32_t)mp_startup; - - ntss->tss_cs = KCS_SEL; - ntss->tss_fs = KFS_SEL; - ntss->tss_gs = KGS_SEL; +#if !defined(__lint) + ASSERT((sizeof (*cp->cpu_gdt) * NGDT) <= PAGESIZE); +#endif + cp->cpu_m.mcpu_gdt = kmem_zalloc(PAGESIZE, KM_SLEEP); + bcopy(CPU->cpu_m.mcpu_gdt, cp->cpu_m.mcpu_gdt, + (sizeof (*cp->cpu_m.mcpu_gdt) * NGDT)); +#if defined(__i386) /* * setup kernel %gs. */ set_usegd(&cp->cpu_gdt[GDT_GS], cp, sizeof (struct cpu) -1, SDT_MEMRWA, SEL_KPL, 0, 1); - -#endif /* __i386 */ - - /* - * Set I/O bit map offset equal to size of TSS segment limit - * for no I/O permission map. This will cause all user I/O - * instructions to generate #gp fault. - */ - ntss->tss_bitmapbase = sizeof (*ntss); - - /* - * setup kernel tss. - */ - set_syssegd((system_desc_t *)&cp->cpu_gdt[GDT_KTSS], cp->cpu_tss, - sizeof (*cp->cpu_tss) -1, SDT_SYSTSS, SEL_KPL); +#endif /* * If we have more than one node, each cpu gets a copy of IDT @@ -413,83 +351,35 @@ extern void *long_mode_64(void); * IDT. cpu 0's IDT has been made read-only to workaround the * cmpxchgl register bug */ - cp->cpu_idt = CPU->cpu_idt; if (system_hardware.hd_nodes && x86_type != X86_TYPE_P5) { - cp->cpu_idt = kmem_alloc(sizeof (idt0), KM_SLEEP); - bcopy(idt0, cp->cpu_idt, sizeof (idt0)); + struct machcpu *mcpu = &cp->cpu_m; + + mcpu->mcpu_idt = kmem_alloc(sizeof (idt0), KM_SLEEP); + bcopy(idt0, mcpu->mcpu_idt, sizeof (idt0)); + } else { + cp->cpu_m.mcpu_idt = CPU->cpu_m.mcpu_idt; } /* - * Get interrupt priority data from cpu 0 + * Get interrupt priority data from cpu 0. */ cp->cpu_pri_data = CPU->cpu_pri_data; - hat_cpu_online(cp); - - /* Should remove all entries for the current process/thread here */ - /* - * Fill up the real mode platter to make it easy for real mode code to - * kick it off. This area should really be one passed by boot to kernel - * and guaranteed to be below 1MB and aligned to 16 bytes. Should also - * have identical physical and virtual address in paged mode. + * alloc space for cpuid info */ - real_mode_platter->rm_idt_base = cp->cpu_idt; - real_mode_platter->rm_idt_lim = sizeof (idt0) - 1; - real_mode_platter->rm_gdt_base = cp->cpu_gdt; - real_mode_platter->rm_gdt_lim = sizeof (gdt0) -1; - real_mode_platter->rm_pdbr = getcr3(); - real_mode_platter->rm_cpu = cpun; - real_mode_platter->rm_x86feature = x86_feature; - real_mode_platter->rm_cr4 = cr4_value; - -#if defined(__amd64) - if (getcr3() > 0xffffffffUL) - panic("Cannot initialize CPUs; kernel's 64-bit page tables\n" - "located above 4G in physical memory (@ 0x%llx).", - (unsigned long long)getcr3()); + cpuid_alloc_space(cp); - /* - * Setup pseudo-descriptors for temporary GDT and IDT for use ONLY - * by code in real_mode_start(): - * - * GDT[0]: NULL selector - * GDT[1]: 64-bit CS: Long = 1, Present = 1, bits 12, 11 = 1 - * - * Clear the IDT as interrupts will be off and a limit of 0 will cause - * the CPU to triple fault and reset on an NMI, seemingly as reasonable - * a course of action as any other, though it may cause the entire - * platform to reset in some cases... - */ - real_mode_platter->rm_temp_gdt[0] = 0ULL; - real_mode_platter->rm_temp_gdt[TEMPGDT_KCODE64] = 0x20980000000000ULL; - - real_mode_platter->rm_temp_gdt_lim = (ushort_t) - (sizeof (real_mode_platter->rm_temp_gdt) - 1); - real_mode_platter->rm_temp_gdt_base = rm_platter_pa + - (uint32_t)(&((rm_platter_t *)0)->rm_temp_gdt); - - real_mode_platter->rm_temp_idt_lim = 0; - real_mode_platter->rm_temp_idt_base = 0; - - /* - * Since the CPU needs to jump to protected mode using an identity - * mapped address, we need to calculate it here. - */ - real_mode_platter->rm_longmode64_addr = rm_platter_pa + - ((uint32_t)long_mode_64 - (uint32_t)real_mode_start); -#endif /* __amd64 */ + hat_cpu_online(cp); #ifdef TRAPTRACE /* - * If this is a TRAPTRACE kernel, allocate TRAPTRACE buffers for this - * CPU. + * If this is a TRAPTRACE kernel, allocate TRAPTRACE buffers */ ttc->ttc_first = (uintptr_t)kmem_zalloc(trap_trace_bufsize, KM_SLEEP); ttc->ttc_next = ttc->ttc_first; ttc->ttc_limit = ttc->ttc_first + trap_trace_bufsize; #endif - /* * Record that we have another CPU. */ @@ -504,6 +394,92 @@ extern void *long_mode_64(void); */ cpu_add_unit(cp); mutex_exit(&cpu_lock); + + return (cp); +} + +/* + * Undo what was done in mp_startup_init + */ +static void +mp_startup_fini(struct cpu *cp, int error) +{ + mutex_enter(&cpu_lock); + + /* + * Remove the CPU from the list of available CPUs. + */ + cpu_del_unit(cp->cpu_id); + + if (error == ETIMEDOUT) { + /* + * The cpu was started, but never *seemed* to run any + * code in the kernel; it's probably off spinning in its + * own private world, though with potential references to + * our kmem-allocated IDTs and GDTs (for example). + * + * Worse still, it may actually wake up some time later, + * so rather than guess what it might or might not do, we + * leave the fundamental data structures intact. + */ + cp->cpu_flags = 0; + mutex_exit(&cpu_lock); + return; + } + + /* + * At this point, the only threads bound to this CPU should + * special per-cpu threads: it's idle thread, it's pause threads, + * and it's interrupt threads. Clean these up. + */ + cpu_destroy_bound_threads(cp); + cp->cpu_idle_thread = NULL; + + /* + * Free the interrupt stack. + */ + segkp_release(segkp, + cp->cpu_intr_stack - (INTR_STACK_SIZE - SA(MINFRAME))); + + mutex_exit(&cpu_lock); + +#ifdef TRAPTRACE + /* + * Discard the trap trace buffer + */ + { + trap_trace_ctl_t *ttc = &trap_trace_ctl[cp->cpu_id]; + + kmem_free((void *)ttc->ttc_first, trap_trace_bufsize); + ttc->ttc_first = NULL; + } +#endif + + hat_cpu_offline(cp); + + cpuid_free_space(cp); + + if (cp->cpu_m.mcpu_idt != CPU->cpu_m.mcpu_idt) + kmem_free(cp->cpu_m.mcpu_idt, sizeof (idt0)); + cp->cpu_m.mcpu_idt = NULL; + + kmem_free(cp->cpu_m.mcpu_gdt, PAGESIZE); + cp->cpu_m.mcpu_gdt = NULL; + + teardown_vaddr_for_ppcopy(cp); + + kcpc_hw_fini(cp); + + cp->cpu_dispthread = NULL; + cp->cpu_thread = NULL; /* discarded by cpu_destroy_bound_threads() */ + + cpu_vm_data_destroy(cp); + + mutex_enter(&cpu_lock); + disp_cpu_fini(cp); + mutex_exit(&cpu_lock); + + kmem_free(cp, sizeof (*cp)); } /* @@ -528,6 +504,10 @@ extern void *long_mode_64(void); * AMD Athlon(tm) 64 and AMD Opteron(tm) Processors, August 2005. */ +#if defined(OPTERON_ERRATUM_88) +int opteron_erratum_88; /* if non-zero -> at least one cpu has it */ +#endif + #if defined(OPTERON_ERRATUM_91) int opteron_erratum_91; /* if non-zero -> at least one cpu has it */ #endif @@ -536,10 +516,18 @@ int opteron_erratum_91; /* if non-zero -> at least one cpu has it */ int opteron_erratum_93; /* if non-zero -> at least one cpu has it */ #endif +#if defined(OPTERON_ERRATUM_95) +int opteron_erratum_95; /* if non-zero -> at least one cpu has it */ +#endif + #if defined(OPTERON_ERRATUM_100) int opteron_erratum_100; /* if non-zero -> at least one cpu has it */ #endif +#if defined(OPTERON_ERRATUM_108) +int opteron_erratum_108; /* if non-zero -> at least one cpu has it */ +#endif + #if defined(OPTERON_ERRATUM_109) int opteron_erratum_109; /* if non-zero -> at least one cpu has it */ #endif @@ -569,9 +557,30 @@ int opteron_workaround_6336786_UP = 0; /* Not needed for UP */ int opteron_workaround_6323525; /* if non-zero -> at least one cpu has it */ #endif -#define WARNING(cpu, n) \ - cmn_err(CE_WARN, "cpu%d: no workaround for erratum %d", \ - (cpu)->cpu_id, (n)) +static void +workaround_warning(cpu_t *cp, uint_t erratum) +{ + cmn_err(CE_WARN, "cpu%d: no workaround for erratum %u", + cp->cpu_id, erratum); +} + +static void +workaround_applied(uint_t erratum) +{ + if (erratum > 1000000) + cmn_err(CE_CONT, "?workaround applied for cpu issue #%d\n", + erratum); + else + cmn_err(CE_CONT, "?workaround applied for cpu erratum #%d\n", + erratum); +} + +static void +msr_warning(cpu_t *cp, const char *rw, uint_t msr, int error) +{ + cmn_err(CE_WARN, "cpu%d: couldn't %smsr 0x%x, error %d", + cp->cpu_id, rw, msr, error); +} uint_t workaround_errata(struct cpu *cpu) @@ -589,8 +598,9 @@ workaround_errata(struct cpu *cpu) /* * The workaround is an mfence in the relevant assembler code */ + opteron_erratum_88++; #else - WARNING(cpu, 88); + workaround_warning(cpu, 88); missing++; #endif } @@ -605,7 +615,7 @@ workaround_errata(struct cpu *cpu) */ opteron_erratum_91++; #else - WARNING(cpu, 91); + workaround_warning(cpu, 91); missing++; #endif } @@ -620,7 +630,7 @@ workaround_errata(struct cpu *cpu) */ opteron_erratum_93++; #else - WARNING(cpu, 93); + workaround_warning(cpu, 93); missing++; #endif } @@ -642,11 +652,12 @@ workaround_errata(struct cpu *cpu) /*LINTED*/ ASSERT((uint32_t)COREHEAP_BASE == 0xc0000000u); + opteron_erratum_95++; #endif /* _LP64 */ #else - WARNING(cpu, 95); + workaround_warning(cpu, 95); missing++; -#endif /* OPTERON_ERRATUM_95 */ +#endif } if (cpuid_opteron_erratum(cpu, 100) > 0) { @@ -659,7 +670,7 @@ workaround_errata(struct cpu *cpu) */ opteron_erratum_100++; #else - WARNING(cpu, 100); + workaround_warning(cpu, 100); missing++; #endif } @@ -676,26 +687,38 @@ workaround_errata(struct cpu *cpu) * those processors) */ #else - WARNING(cpu, 108); + workaround_warning(cpu, 108); missing++; #endif } /*LINTED*/ - if (cpuid_opteron_erratum(cpu, 109) > 0) { + if (cpuid_opteron_erratum(cpu, 109) > 0) do { /* * Certain Reverse REP MOVS May Produce Unpredictable Behaviour */ #if defined(OPTERON_ERRATUM_109) - - /* workaround is to print a warning to upgrade BIOS */ - if (rdmsr(MSR_AMD_PATCHLEVEL) == 0) + /* + * The "workaround" is to print a warning to upgrade the BIOS + */ + uint64_t value; + const uint_t msr = MSR_AMD_PATCHLEVEL; + int err; + + if ((err = checked_rdmsr(msr, &value)) != 0) { + msr_warning(cpu, "rd", msr, err); + workaround_warning(cpu, 109); + missing++; + } + if (value == 0) opteron_erratum_109++; #else - WARNING(cpu, 109); + workaround_warning(cpu, 109); missing++; #endif - } + /*CONSTANTCONDITION*/ + } while (0); + /*LINTED*/ if (cpuid_opteron_erratum(cpu, 121) > 0) { /* @@ -703,132 +726,160 @@ workaround_errata(struct cpu *cpu) * Processor Hang */ #if defined(OPTERON_ERRATUM_121) - static int lma; - - if (opteron_erratum_121) - opteron_erratum_121++; - +#if defined(_LP64) /* * Erratum 121 is only present in long (64 bit) mode. * Workaround is to include the page immediately before the * va hole to eliminate the possibility of system hangs due to * sequential execution across the va hole boundary. */ - if (lma == 0) { - /* - * check LMA once: assume all cpus are in long mode - * or not. - */ - lma = 1; - - if (rdmsr(MSR_AMD_EFER) & AMD_EFER_LMA) { - if (hole_start) { - hole_start -= PAGESIZE; - } else { - /* - * hole_start not yet initialized by - * mmu_init. Initialize hole_start - * with value to be subtracted. - */ - hole_start = PAGESIZE; - } - opteron_erratum_121++; + if (opteron_erratum_121) + opteron_erratum_121++; + else { + if (hole_start) { + hole_start -= PAGESIZE; + } else { + /* + * hole_start not yet initialized by + * mmu_init. Initialize hole_start + * with value to be subtracted. + */ + hole_start = PAGESIZE; } + opteron_erratum_121++; } +#endif /* _LP64 */ #else - WARNING(cpu, 121); + workaround_warning(cpu, 121); missing++; #endif } /*LINTED*/ - if (cpuid_opteron_erratum(cpu, 122) > 0) { + if (cpuid_opteron_erratum(cpu, 122) > 0) do { /* - * TLB Flush Filter May Cause Cohenrency Problem in + * TLB Flush Filter May Cause Coherency Problem in * Multiprocessor Systems */ #if defined(OPTERON_ERRATUM_122) + uint64_t value; + const uint_t msr = MSR_AMD_HWCR; + int error; + /* * Erratum 122 is only present in MP configurations (multi-core * or multi-processor). */ - - if (opteron_erratum_122 || lgrp_plat_node_cnt > 1 || - cpuid_get_ncpu_per_chip(cpu) > 1) { - /* disable TLB Flush Filter */ - wrmsr(MSR_AMD_HWCR, rdmsr(MSR_AMD_HWCR) | - (uint64_t)(uintptr_t)AMD_HWCR_FFDIS); - opteron_erratum_122++; + if (!opteron_erratum_122 && lgrp_plat_node_cnt == 1 && + cpuid_get_ncpu_per_chip(cpu) == 1) + break; + + /* disable TLB Flush Filter */ + + if ((error = checked_rdmsr(msr, &value)) != 0) { + msr_warning(cpu, "rd", msr, error); + workaround_warning(cpu, 122); + missing++; + } else { + value |= (uint64_t)AMD_HWCR_FFDIS; + if ((error = checked_wrmsr(msr, value)) != 0) { + msr_warning(cpu, "wr", msr, error); + workaround_warning(cpu, 122); + missing++; + } } - + opteron_erratum_122++; #else - WARNING(cpu, 122); + workaround_warning(cpu, 122); missing++; #endif - } + /*CONSTANTCONDITION*/ + } while (0); -#if defined(OPTERON_ERRATUM_123) /*LINTED*/ - if (cpuid_opteron_erratum(cpu, 123) > 0) { + if (cpuid_opteron_erratum(cpu, 123) > 0) do { /* * Bypassed Reads May Cause Data Corruption of System Hang in * Dual Core Processors */ +#if defined(OPTERON_ERRATUM_123) + uint64_t value; + const uint_t msr = MSR_AMD_PATCHLEVEL; + int err; + /* * Erratum 123 applies only to multi-core cpus. */ + if (cpuid_get_ncpu_per_chip(cpu) < 2) + break; - if (cpuid_get_ncpu_per_chip(cpu) > 1) { - /* workaround is to print a warning to upgrade BIOS */ - if (rdmsr(MSR_AMD_PATCHLEVEL) == 0) - opteron_erratum_123++; + /* + * The "workaround" is to print a warning to upgrade the BIOS + */ + if ((err = checked_rdmsr(msr, &value)) != 0) { + msr_warning(cpu, "rd", msr, err); + workaround_warning(cpu, 123); + missing++; } - } + if (value == 0) + opteron_erratum_123++; +#else + workaround_warning(cpu, 123); + missing++; + #endif + /*CONSTANTCONDITION*/ + } while (0); -#if defined(OPTERON_ERRATUM_131) /*LINTED*/ - if (cpuid_opteron_erratum(cpu, 131) > 0) { + if (cpuid_opteron_erratum(cpu, 131) > 0) do { /* * Multiprocessor Systems with Four or More Cores May Deadlock * Waiting for a Probe Response */ +#if defined(OPTERON_ERRATUM_131) + uint64_t nbcfg; + const uint_t msr = MSR_AMD_NB_CFG; + const uint64_t wabits = + AMD_NB_CFG_SRQ_HEARTBEAT | AMD_NB_CFG_SRQ_SPR; + int error; + /* * Erratum 131 applies to any system with four or more cores. */ - if ((opteron_erratum_131 == 0) && ((lgrp_plat_node_cnt * - cpuid_get_ncpu_per_chip(cpu)) >= 4)) { - uint64_t nbcfg; - uint64_t wabits; + if (opteron_erratum_131) + break; - /* - * Print a warning if neither of the workarounds - * for Erratum 131 is present. - */ + if (lgrp_plat_node_cnt * cpuid_get_ncpu_per_chip(cpu) < 4) + break; - wabits = AMD_NB_CFG_SRQ_HEARTBEAT | - AMD_NB_CFG_SRQ_SPR; - - nbcfg = rdmsr(MSR_AMD_NB_CFG); - if ((nbcfg & wabits) == 0) { - opteron_erratum_131++; - } else { - /* cannot have both workarounds set */ - ASSERT((nbcfg & wabits) != wabits); - } + /* + * Print a warning if neither of the workarounds for + * erratum 131 is present. + */ + if ((error = checked_rdmsr(msr, &nbcfg)) != 0) { + msr_warning(cpu, "rd", msr, error); + workaround_warning(cpu, 131); + missing++; + } else if ((nbcfg & wabits) == 0) { + opteron_erratum_131++; + } else { + /* cannot have both workarounds set */ + ASSERT((nbcfg & wabits) != wabits); } - } +#else + workaround_warning(cpu, 131); + missing++; #endif + /*CONSTANTCONDITION*/ + } while (0); -#if defined(OPTERON_WORKAROUND_6336786) /* - * This isn't really erratum, but for convenience the + * This isn't really an erratum, but for convenience the * detection/workaround code lives here and in cpuid_opteron_erratum. */ if (cpuid_opteron_erratum(cpu, 6336786) > 0) { - int node; - uint8_t data; - +#if defined(OPTERON_WORKAROUND_6336786) /* * Disable C1-Clock ramping on multi-core/multi-processor * K8 platforms to guard against TSC drift. @@ -836,8 +887,11 @@ workaround_errata(struct cpu *cpu) if (opteron_workaround_6336786) { opteron_workaround_6336786++; } else if ((lgrp_plat_node_cnt * - cpuid_get_ncpu_per_chip(cpu) >= 2) || + cpuid_get_ncpu_per_chip(cpu) > 1) || opteron_workaround_6336786_UP) { + int node; + uint8_t data; + for (node = 0; node < lgrp_plat_node_cnt; node++) { /* * Clear PMM7[1:0] (function 3, offset 0x87) @@ -849,18 +903,20 @@ workaround_errata(struct cpu *cpu) } opteron_workaround_6336786++; } - } +#else + workaround_warning(cpu, 6336786); + missing++; #endif + } -#if defined(OPTERON_WORKAROUND_6323525) /*LINTED*/ /* * Mutex primitives don't work as expected. */ if (cpuid_opteron_erratum(cpu, 6323525) > 0) { - +#if defined(OPTERON_WORKAROUND_6323525) /* - * problem only occurs with 2 or more cores. If bit in + * This problem only occurs with 2 or more cores. If bit in * MSR_BU_CFG set, then not applicable. The workaround * is to patch the semaphone routines with the lfence * instruction to provide necessary load memory barrier with @@ -872,18 +928,46 @@ workaround_errata(struct cpu *cpu) if (opteron_workaround_6323525) { opteron_workaround_6323525++; } else if ((x86_feature & X86_SSE2) && ((lgrp_plat_node_cnt * - cpuid_get_ncpu_per_chip(cpu)) >= 2)) { + cpuid_get_ncpu_per_chip(cpu)) > 1)) { if ((xrdmsr(MSR_BU_CFG) & 0x02) == 0) opteron_workaround_6323525++; } - } +#else + workaround_warning(cpu, 6323525); + missing++; #endif + } + return (missing); } void workaround_errata_end() { +#if defined(OPTERON_ERRATUM_88) + if (opteron_erratum_88) + workaround_applied(88); +#endif +#if defined(OPTERON_ERRATUM_91) + if (opteron_erratum_91) + workaround_applied(91); +#endif +#if defined(OPTERON_ERRATUM_93) + if (opteron_erratum_93) + workaround_applied(93); +#endif +#if defined(OPTERON_ERRATUM_95) + if (opteron_erratum_95) + workaround_applied(95); +#endif +#if defined(OPTERON_ERRATUM_100) + if (opteron_erratum_100) + workaround_applied(100); +#endif +#if defined(OPTERON_ERRATUM_108) + if (opteron_erratum_108) + workaround_applied(108); +#endif #if defined(OPTERON_ERRATUM_109) if (opteron_erratum_109) { cmn_err(CE_WARN, @@ -893,7 +977,15 @@ workaround_errata_end() " microcode patch is HIGHLY recommended or erroneous" " system\noperation may occur.\n"); } -#endif /* OPTERON_ERRATUM_109 */ +#endif +#if defined(OPTERON_ERRATUM_121) + if (opteron_erratum_121) + workaround_applied(121); +#endif +#if defined(OPTERON_ERRATUM_122) + if (opteron_erratum_122) + workaround_applied(122); +#endif #if defined(OPTERON_ERRATUM_123) if (opteron_erratum_123) { cmn_err(CE_WARN, @@ -903,7 +995,7 @@ workaround_errata_end() " microcode patch is HIGHLY recommended or erroneous" " system\noperation may occur.\n"); } -#endif /* OPTERON_ERRATUM_123 */ +#endif #if defined(OPTERON_ERRATUM_131) if (opteron_erratum_131) { cmn_err(CE_WARN, @@ -913,24 +1005,125 @@ workaround_errata_end() " microcode patch is HIGHLY recommended or erroneous" " system\noperation may occur.\n"); } -#endif /* OPTERON_ERRATUM_131 */ +#endif +#if defined(OPTERON_WORKAROUND_6336786) + if (opteron_workaround_6336786) + workaround_applied(6336786); +#endif +#if defined(OPTERON_WORKAROUND_6323525) + if (opteron_workaround_6323525) + workaround_applied(6323525); +#endif } -static ushort_t *mp_map_warm_reset_vector(); -static void mp_unmap_warm_reset_vector(ushort_t *warm_reset_vector); +static cpuset_t procset; + +/* + * Start a single cpu, assuming that the kernel context is available + * to successfully start another cpu. + * + * (For example, real mode code is mapped into the right place + * in memory and is ready to be run.) + */ +int +start_cpu(processorid_t who) +{ + void *ctx; + cpu_t *cp; + int delays; + int error = 0; + + ASSERT(who != 0); + + /* + * Check if there's at least a Mbyte of kmem available + * before attempting to start the cpu. + */ + if (kmem_avail() < 1024 * 1024) { + /* + * Kick off a reap in case that helps us with + * later attempts .. + */ + kmem_reap(); + return (ENOMEM); + } + + cp = mp_startup_init(who); + if ((ctx = mach_cpucontext_alloc(cp)) == NULL || + (error = mach_cpu_start(cp, ctx)) != 0) { + + /* + * Something went wrong before we even started it + */ + if (ctx) + cmn_err(CE_WARN, + "cpu%d: failed to start error %d", + cp->cpu_id, error); + else + cmn_err(CE_WARN, + "cpu%d: failed to allocate context", cp->cpu_id); + + if (ctx) + mach_cpucontext_free(cp, ctx, error); + else + error = EAGAIN; /* hmm. */ + mp_startup_fini(cp, error); + return (error); + } + + for (delays = 0; !CPU_IN_SET(procset, who); delays++) { + if (delays == 500) { + /* + * After five seconds, things are probably looking + * a bit bleak - explain the hang. + */ + cmn_err(CE_NOTE, "cpu%d: started, " + "but not running in the kernel yet", who); + } else if (delays > 2000) { + /* + * We waited at least 20 seconds, bail .. + */ + error = ETIMEDOUT; + cmn_err(CE_WARN, "cpu%d: timed out", who); + mach_cpucontext_free(cp, ctx, error); + mp_startup_fini(cp, error); + return (error); + } + + /* + * wait at least 10ms, then check again.. + */ + delay(USEC_TO_TICK_ROUNDUP(10000)); + } + + mach_cpucontext_free(cp, ctx, 0); + + if (tsc_gethrtime_enable) + tsc_sync_master(who); + + if (dtrace_cpu_init != NULL) { + /* + * DTrace CPU initialization expects cpu_lock to be held. + */ + mutex_enter(&cpu_lock); + (*dtrace_cpu_init)(who); + mutex_exit(&cpu_lock); + } + + while (!CPU_IN_SET(cpu_ready_set, who)) + delay(1); + + return (0); +} -static cpuset_t procset = 1; /*ARGSUSED*/ void start_other_cpus(int cprboot) { - unsigned int who; - int skipped = 0; - int cpuid = 0; - int delays = 0; - int started_cpu; - ushort_t *warm_reset_vector = NULL; + uint_t who; + uint_t skipped = 0; + uint_t bootcpuid = 0; /* * Initialize our own cpu_info. @@ -943,9 +1136,17 @@ start_other_cpus(int cprboot) init_cpu_syscall(CPU); /* + * Take the boot cpu out of the mp_cpus set because we know + * it's already running. Add it to the cpu_ready_set for + * precisely the same reason. + */ + CPUSET_DEL(mp_cpus, bootcpuid); + CPUSET_ADD(cpu_ready_set, bootcpuid); + + /* * if only 1 cpu or not using MP, skip the rest of this */ - if (CPUSET_ISEQUAL(mp_cpus, cpu_ready_set) || use_mp == 0) { + if (CPUSET_ISNULL(mp_cpus) || use_mp == 0) { if (use_mp == 0) cmn_err(CE_CONT, "?***** Not in MP mode\n"); goto done; @@ -959,23 +1160,11 @@ start_other_cpus(int cprboot) xc_init(); /* initialize processor crosscalls */ - /* - * Copy the real mode code at "real_mode_start" to the - * page at rm_platter_va. - */ - warm_reset_vector = mp_map_warm_reset_vector(); - if (warm_reset_vector == NULL) + if (mach_cpucontext_init() != 0) goto done; - bcopy((caddr_t)real_mode_start, - (caddr_t)((rm_platter_t *)rm_platter_va)->rm_code, - (size_t)real_mode_end - (size_t)real_mode_start); - flushes_require_xcalls = 1; - ASSERT(CPU_IN_SET(procset, cpuid)); - ASSERT(CPU_IN_SET(cpu_ready_set, cpuid)); - /* * We lock our affinity to the master CPU to ensure that all slave CPUs * do their TSC syncs with the same CPU. @@ -983,67 +1172,24 @@ start_other_cpus(int cprboot) affinity_set(CPU_CURRENT); for (who = 0; who < NCPU; who++) { - if (who == cpuid) - continue; - - delays = 0; if (!CPU_IN_SET(mp_cpus, who)) continue; - + ASSERT(who != bootcpuid); if (ncpus >= max_ncpus) { skipped = who; continue; } - - mp_startup_init(who); - started_cpu = 1; - (*cpu_startf)(who, rm_platter_pa); - - while (!CPU_IN_SET(procset, who)) { - delay(1); - if (++delays > (20 * hz)) { - - cmn_err(CE_WARN, - "cpu%d failed to start", who); - - mutex_enter(&cpu_lock); - cpu[who]->cpu_flags = 0; - cpu_vm_data_destroy(cpu[who]); - cpu_del_unit(who); - mutex_exit(&cpu_lock); - - started_cpu = 0; - break; - } - } - if (!started_cpu) - continue; - if (tsc_gethrtime_enable) - tsc_sync_master(who); - + if (start_cpu(who) != 0) + CPUSET_DEL(mp_cpus, who); } affinity_clear(); - /* - * Wait for all CPUs that booted (have presence in procset) - * to come online (have presence in cpu_ready_set). Note - * that the start CPU already satisfies both of these, so no - * special case is needed. - */ - for (who = 0; who < NCPU; who++) { - if (!CPU_IN_SET(procset, who)) - continue; - - while (!CPU_IN_SET(cpu_ready_set, who)) - delay(1); - } - if (skipped) { cmn_err(CE_NOTE, - "System detected %d CPU(s), but " - "only %d CPU(s) were enabled during boot.", + "System detected %d cpus, but " + "only %d cpu(s) were enabled during boot.", skipped + 1, ncpus); cmn_err(CE_NOTE, "Use \"boot-ncpus\" parameter to enable more CPU(s). " @@ -1052,11 +1198,7 @@ start_other_cpus(int cprboot) done: workaround_errata_end(); - - if (warm_reset_vector != NULL) - mp_unmap_warm_reset_vector(warm_reset_vector); - hat_unload(kas.a_hat, (caddr_t)(uintptr_t)rm_platter_pa, MMU_PAGESIZE, - HAT_UNLOAD); + mach_cpucontext_fini(); cmi_post_mpstartup(); } @@ -1124,6 +1266,13 @@ mp_startup(void) mtrr_sync(); /* + * Set up TSC_AUX to contain the cpuid for this processor + * for the rdtscp instruction. + */ + if (x86_feature & X86_TSCP) + (void) wrmsr(MSR_AMD_TSCAUX, cp->cpu_id); + + /* * Initialize this CPU's syscall handlers */ init_cpu_syscall(cp); @@ -1136,7 +1285,8 @@ mp_startup(void) * device interrupts that may end up in the hat layer issuing cross * calls before CPU_READY is set. */ - (void) splx(ipltospl(LOCK_LEVEL)); + splx(ipltospl(LOCK_LEVEL)); + sti(); /* * Do a sanity check to make sure this new CPU is a sane thing @@ -1218,7 +1368,7 @@ mp_startup(void) cmi_mca_init(); if (boothowto & RB_DEBUG) - kdi_dvec_cpu_init(cp); + kdi_cpu_init(); /* * Setting the bit in cpu_ready_set must be the last operation in @@ -1277,29 +1427,6 @@ mp_cpu_stop(struct cpu *cp) } /* - * Power on CPU. - */ -/* ARGSUSED */ -int -mp_cpu_poweron(struct cpu *cp) -{ - ASSERT(MUTEX_HELD(&cpu_lock)); - return (ENOTSUP); /* not supported */ -} - -/* - * Power off CPU. - */ -/* ARGSUSED */ -int -mp_cpu_poweroff(struct cpu *cp) -{ - ASSERT(MUTEX_HELD(&cpu_lock)); - return (ENOTSUP); /* not supported */ -} - - -/* * Take the specified CPU out of participation in interrupts. */ int @@ -1325,34 +1452,6 @@ cpu_enable_intr(struct cpu *cp) -static ushort_t * -mp_map_warm_reset_vector() -{ - ushort_t *warm_reset_vector; - - if (!(warm_reset_vector = (ushort_t *)psm_map_phys(WARM_RESET_VECTOR, - sizeof (ushort_t *), PROT_READ|PROT_WRITE))) - return (NULL); - - /* - * setup secondary cpu bios boot up vector - */ - *warm_reset_vector = (ushort_t)((caddr_t) - ((struct rm_platter *)rm_platter_va)->rm_code - rm_platter_va - + ((ulong_t)rm_platter_va & 0xf)); - warm_reset_vector++; - *warm_reset_vector = (ushort_t)(rm_platter_pa >> 4); - - --warm_reset_vector; - return (warm_reset_vector); -} - -static void -mp_unmap_warm_reset_vector(ushort_t *warm_reset_vector) -{ - psm_unmap_phys((caddr_t)warm_reset_vector, sizeof (ushort_t *)); -} - void mp_cpu_faulted_enter(struct cpu *cp) { @@ -1379,9 +1478,9 @@ mp_cpu_faulted_exit(struct cpu *cp) void cpu_fast_syscall_disable(void *arg) { - if (x86_feature & X86_SEP) + if ((x86_feature & (X86_MSR | X86_SEP)) == (X86_MSR | X86_SEP)) cpu_sep_disable(); - if (x86_feature & X86_ASYSC) + if ((x86_feature & (X86_MSR | X86_ASYSC)) == (X86_MSR | X86_ASYSC)) cpu_asysc_disable(); } @@ -1389,9 +1488,9 @@ cpu_fast_syscall_disable(void *arg) void cpu_fast_syscall_enable(void *arg) { - if (x86_feature & X86_SEP) + if ((x86_feature & (X86_MSR | X86_SEP)) == (X86_MSR | X86_SEP)) cpu_sep_enable(); - if (x86_feature & X86_ASYSC) + if ((x86_feature & (X86_MSR | X86_ASYSC)) == (X86_MSR | X86_ASYSC)) cpu_asysc_enable(); } @@ -1414,7 +1513,7 @@ cpu_sep_disable(void) * Setting the SYSENTER_CS_MSR register to 0 causes software executing * the sysenter or sysexit instruction to trigger a #gp fault. */ - wrmsr(MSR_INTC_SEP_CS, 0ULL); + wrmsr(MSR_INTC_SEP_CS, 0); } static void diff --git a/usr/src/uts/i86pc/os/startup.c b/usr/src/uts/i86pc/os/startup.c index 6d7954db30..d082635a8d 100644 --- a/usr/src/uts/i86pc/os/startup.c +++ b/usr/src/uts/i86pc/os/startup.c @@ -46,6 +46,7 @@ #include <sys/proc.h> #include <sys/buf.h> #include <sys/kmem.h> +#include <sys/mem.h> #include <sys/kstat.h> #include <sys/reboot.h> @@ -111,6 +112,11 @@ #include <sys/x86_archext.h> #include <sys/cpu_module.h> #include <sys/smbios.h> +#include <sys/debug_info.h> + + +#include <sys/bootinfo.h> +#include <vm/kboot_mmu.h> extern void progressbar_init(void); extern void progressbar_start(void); @@ -130,8 +136,8 @@ extern int segkp_fromheap; static void kvm_init(void); static void startup_init(void); static void startup_memlist(void); +static void startup_kmem(void); static void startup_modules(void); -static void startup_bop_gone(void); static void startup_vm(void); static void startup_end(void); @@ -187,14 +193,6 @@ size_t kpm_size; static int kpm_desired = 0; /* Do we want to try to use segkpm? */ /* - * VA range that must be preserved for boot until we release all of its - * mappings. - */ -#if defined(__amd64) -static void *kmem_setaside; -#endif - -/* * Configuration parameters set at boot time. */ @@ -241,6 +239,8 @@ struct seg kmapseg; /* Segment used for generic kernel mappings */ struct seg kdebugseg; /* Segment used for the kernel debugger */ struct seg *segkmap = &kmapseg; /* Kernel generic mapping segment */ +static struct seg *segmap = &kmapseg; /* easier to use name for in here */ + struct seg *segkp = &kpseg; /* Pageable kernel virtual memory segment */ #if defined(__amd64) @@ -260,6 +260,12 @@ pgcnt_t segkpsize = 0; #endif pgcnt_t segziosize = 0; /* size of zio segment in pages */ +/* + * VA range available to the debugger + */ +const caddr_t kdi_segdebugbase = (const caddr_t)SEGDEBUGBASE; +const size_t kdi_segdebugsize = SEGDEBUGSIZE; + struct memseg *memseg_base; struct vnode unused_pages_vp; @@ -279,13 +285,10 @@ caddr_t e_moddata; /* end of loadable module data reserved */ struct memlist *phys_install; /* Total installed physical memory */ struct memlist *phys_avail; /* Total available physical memory */ -static void memlist_add(uint64_t, uint64_t, struct memlist *, - struct memlist **); - /* * kphysm_init returns the number of pages that were processed */ -static pgcnt_t kphysm_init(page_t *, struct memseg *, pgcnt_t, pgcnt_t); +static pgcnt_t kphysm_init(page_t *, pgcnt_t); #define IO_PROP_SIZE 64 /* device property size */ @@ -297,15 +300,14 @@ static pgcnt_t kphysm_init(page_t *, struct memseg *, pgcnt_t, pgcnt_t); #define ROUND_UP_LPAGE(x) \ ((uintptr_t)P2ROUNDUP((uintptr_t)(x), mmu.level_size[1])) #define ROUND_UP_4MEG(x) \ - ((uintptr_t)P2ROUNDUP((uintptr_t)(x), (uintptr_t)FOURMB_PAGESIZE)) + ((uintptr_t)P2ROUNDUP((uintptr_t)(x), (uintptr_t)FOUR_MEG)) #define ROUND_UP_TOPLEVEL(x) \ ((uintptr_t)P2ROUNDUP((uintptr_t)(x), mmu.level_size[mmu.max_level])) /* * 32-bit Kernel's Virtual memory layout. * +-----------------------+ - * | psm 1-1 map | - * | exec args area | + * | | * 0xFFC00000 -|-----------------------|- ARGSBASE * | debugger | * 0xFF800000 -|-----------------------|- SEGDEBUGBASE @@ -313,23 +315,21 @@ static pgcnt_t kphysm_init(page_t *, struct memseg *, pgcnt_t, pgcnt_t); * 0xFEC00000 -|-----------------------| * | Kernel Text | * 0xFE800000 -|-----------------------|- KERNEL_TEXT - * | LUFS sinkhole | - * 0xFE000000 -|-----------------------|- lufs_addr - * --- -|-----------------------|- valloc_base + valloc_sz - * | early pp structures | + * |--- GDT ---|- GDT page (GDT_VA) + * |--- debug info ---|- debug info (DEBUG_INFO_VA) + * | | + * | page_t structures | * | memsegs, memlists, | * | page hash, etc. | - * --- -|-----------------------|- valloc_base (floating) - * | ptable_va | - * 0xFDFFE000 -|-----------------------|- ekernelheap, ptable_va - * | | (segkp is an arena under the heap) + * --- -|-----------------------|- ekernelheap, valloc_base (floating) + * | | (segkp is just an arena in the heap) * | | * | kvseg | * | | * | | * --- -|-----------------------|- kernelheap (floating) * | Segkmap | - * 0xC3002000 -|-----------------------|- segkmap_start (floating) + * 0xC3002000 -|-----------------------|- segmap_start (floating) * | Red Zone | * 0xC3000000 -|-----------------------|- kernelbase / userlimit (floating) * | | || @@ -348,8 +348,7 @@ static pgcnt_t kphysm_init(page_t *, struct memseg *, pgcnt_t, pgcnt_t); * * 64-bit Kernel's Virtual memory layout. (assuming 64 bit app) * +-----------------------+ - * | psm 1-1 map | - * | exec args area | + * | | * 0xFFFFFFFF.FFC00000 |-----------------------|- ARGSBASE * | debugger (?) | * 0xFFFFFFFF.FF800000 |-----------------------|- SEGDEBUGBASE @@ -359,28 +358,26 @@ static pgcnt_t kphysm_init(page_t *, struct memseg *, pgcnt_t, pgcnt_t); * 0xFFFFFFFF.FBC00000 |-----------------------| * | Kernel Text | * 0xFFFFFFFF.FB800000 |-----------------------|- KERNEL_TEXT - * | LUFS sinkhole | - * 0xFFFFFFFF.FB000000 -|-----------------------|- lufs_addr - * --- |-----------------------|- valloc_base + valloc_sz - * | early pp structures | - * | memsegs, memlists, | - * | page hash, etc. | - * --- |-----------------------|- valloc_base - * | ptable_va | - * --- |-----------------------|- ptable_va + * |--- GDT ---|- GDT page (GDT_VA) + * |--- debug info ---|- debug info (DEBUG_INFO_VA) + * | | * | Core heap | (used for loadable modules) * 0xFFFFFFFF.C0000000 |-----------------------|- core_base / ekernelheap * | Kernel | * | heap | * 0xFFFFFXXX.XXX00000 |-----------------------|- kernelheap (floating) - * | segkmap | - * 0xFFFFFXXX.XXX00000 |-----------------------|- segkmap_start (floating) + * | segmap | + * 0xFFFFFXXX.XXX00000 |-----------------------|- segmap_start (floating) * | device mappings | * 0xFFFFFXXX.XXX00000 |-----------------------|- toxic_addr (floating) * | segzio | * 0xFFFFFXXX.XXX00000 |-----------------------|- segzio_base (floating) * | segkp | - * --- |-----------------------|- segkp_base + * --- |-----------------------|- segkp_base (floating) + * | page_t structures | valloc_base + valloc_sz + * | memsegs, memlists, | + * | page hash, etc. | + * 0xFFFFFF00.00000000 |-----------------------|- valloc_base * | segkpm | * 0xFFFFFE00.00000000 |-----------------------| * | Red Zone | @@ -413,8 +410,8 @@ static pgcnt_t kphysm_init(page_t *, struct memseg *, pgcnt_t, pgcnt_t); * Floating values: * * valloc_base: start of the kernel's memory management/tracking data - * structures. This region contains page_t structures for the lowest 4GB - * of physical memory, memsegs, memlists, and the page hash. + * structures. This region contains page_t structures for + * physical memory, memsegs, memlists, and the page hash. * * core_base: start of the kernel's "core" heap area on 64-bit systems. * This area is intended to be used for global data as well as for module @@ -428,7 +425,7 @@ static pgcnt_t kphysm_init(page_t *, struct memseg *, pgcnt_t, pgcnt_t); * above a red zone that separates the user's address space from the * kernel's. On 64-bit systems, it sits above segkp and segkpm. * - * segkmap_start: start of segmap. The length of segmap can be modified + * segmap_start: start of segmap. The length of segmap can be modified * by changing segmapsize in /etc/system (preferred) or eeprom (deprecated). * The default length is 16MB on 32-bit systems and 64MB on 64-bit systems. * @@ -459,19 +456,19 @@ static pgcnt_t kphysm_init(page_t *, struct memseg *, pgcnt_t, pgcnt_t); */ /* real-time-clock initialization parameters */ -long gmt_lag; /* offset in seconds of gmt to local time */ -extern long process_rtc_config_file(void); +extern time_t process_rtc_config_file(void); char *final_kernelheap; char *boot_kernelheap; uintptr_t kernelbase; +uintptr_t postbootkernelbase; /* not set till boot loader is gone */ uintptr_t eprom_kernelbase; size_t segmapsize; static uintptr_t segmap_reserved; -uintptr_t segkmap_start; +uintptr_t segmap_start; int segmapfreelists; -pgcnt_t boot_npages; pgcnt_t npages; +pgcnt_t orig_npages; size_t core_size; /* size of "core" heap */ uintptr_t core_base; /* base address of "core" heap */ @@ -480,30 +477,20 @@ uintptr_t core_base; /* base address of "core" heap */ * release_bootstrap() will free them when we're completely done with * the bootstrap. */ -static page_t *bootpages, *rd_pages; +static page_t *bootpages; + +/* + * boot time pages that have a vnode from the ramdisk will keep that forever. + */ +static page_t *rd_pages; struct system_hardware system_hardware; /* * Enable some debugging messages concerning memory usage... - * - * XX64 There should only be one print routine once memlist usage between - * vmx and the kernel is cleaned up and there is a single memlist structure - * shared between kernel and boot. */ static void -print_boot_memlist(char *title, struct memlist *mp) -{ - prom_printf("MEMLIST: %s:\n", title); - while (mp != NULL) { - prom_printf("\tAddress 0x%" PRIx64 ", size 0x%" PRIx64 "\n", - mp->address, mp->size); - mp = mp->next; - } -} - -static void -print_kernel_memlist(char *title, struct memlist *mp) +print_memlist(char *title, struct memlist *mp) { prom_printf("MEMLIST: %s:\n", title); while (mp != NULL) { @@ -529,7 +516,7 @@ int l2cache_assoc = 1; vmem_t *device_arena; uintptr_t toxic_addr = (uintptr_t)NULL; -size_t toxic_size = 1 * 1024 * 1024 * 1024; /* Sparc uses 1 gig too */ +size_t toxic_size = 1024 * 1024 * 1024; /* Sparc uses 1 gig too */ #else /* __i386 */ @@ -566,8 +553,6 @@ struct { } allocations[NUM_ALLOCATIONS]; size_t valloc_sz = 0; uintptr_t valloc_base; -extern uintptr_t ptable_va; -extern size_t ptable_sz; #define ADD_TO_ALLOCATIONS(ptr, size) { \ size = ROUND_UP_PAGE(size); \ @@ -579,13 +564,20 @@ extern size_t ptable_sz; ++num_allocations; \ } +/* + * Allocate all the initial memory needed by the page allocator. + */ static void perform_allocations(void) { caddr_t mem; int i; + int valloc_align; - mem = BOP_ALLOC(bootops, (caddr_t)valloc_base, valloc_sz, BO_NO_ALIGN); + PRM_DEBUG(valloc_base); + PRM_DEBUG(valloc_sz); + valloc_align = mmu.level_size[mmu.max_page_level > 0]; + mem = BOP_ALLOC(bootops, (caddr_t)valloc_base, valloc_sz, valloc_align); if (mem != (caddr_t)valloc_base) panic("BOP_ALLOC() failed"); bzero(mem, valloc_sz); @@ -607,9 +599,8 @@ perform_allocations(void) * unix/genunix/krtld/module text loads. * * On the data page: - * unix/genunix/krtld/module data loads and space for page_t's. - */ -/* + * unix/genunix/krtld/module data loads. + * * Machine-dependent startup code */ void @@ -629,10 +620,10 @@ startup(void) progressbar_init(); startup_init(); startup_memlist(); + startup_kmem(); startup_pci_bios(); startup_modules(); startup_bios_disk(); - startup_bop_gone(); startup_vm(); startup_end(); progressbar_start(); @@ -707,7 +698,7 @@ avail_filter(uint64_t *addr, uint64_t *size) } /* - * First we trim from the front of the range. Since hat_boot_probe() + * First we trim from the front of the range. Since kbm_probe() * walks ranges in virtual order, but addr/size are physical, we need * to the list until no changes are seen. This deals with the case * where page "p" is mapped at v, page "p + PAGESIZE" is mapped at w @@ -716,11 +707,11 @@ avail_filter(uint64_t *addr, uint64_t *size) do { change = 0; for (va = KERNEL_TEXT; - *size > 0 && hat_boot_probe(&va, &len, &pfn, &prot) != 0; + *size > 0 && kbm_probe(&va, &len, &pfn, &prot) != 0; va = next_va) { next_va = va + len; - pfn_addr = ptob((uint64_t)pfn); + pfn_addr = pfn_to_pa(pfn); pfn_eaddr = pfn_addr + len; if (pfn_addr <= *addr && pfn_eaddr > *addr) { @@ -741,11 +732,11 @@ avail_filter(uint64_t *addr, uint64_t *size) * Trim pages from the end of the range. */ for (va = KERNEL_TEXT; - *size > 0 && hat_boot_probe(&va, &len, &pfn, &prot) != 0; + *size > 0 && kbm_probe(&va, &len, &pfn, &prot) != 0; va = next_va) { next_va = va + len; - pfn_addr = ptob((uint64_t)pfn); + pfn_addr = pfn_to_pa(pfn); if (pfn_addr >= *addr && pfn_addr < *addr + *size) *size = pfn_addr - *addr; @@ -760,8 +751,6 @@ static void kpm_init() { struct segkpm_crargs b; - uintptr_t start, end; - struct memlist *pmem; /* * These variables were all designed for sfmmu in which segkpm is @@ -792,53 +781,39 @@ kpm_init() panic("segkpm_create segkpm"); rw_exit(&kas.a_lock); +} - /* - * Map each of the memsegs into the kpm segment, coalesing adjacent - * memsegs to allow mapping with the largest possible pages. - */ - pmem = phys_install; - start = pmem->address; - end = start + pmem->size; - for (;;) { - if (pmem == NULL || pmem->address > end) { - hat_devload(kas.a_hat, kpm_vbase + start, - end - start, mmu_btop(start), - PROT_READ | PROT_WRITE, - HAT_LOAD | HAT_LOAD_LOCK | HAT_LOAD_NOCONSIST); - if (pmem == NULL) - break; - start = pmem->address; - } - end = pmem->address + pmem->size; - pmem = pmem->next; - } +/* + * The debug info page provides enough information to allow external + * inspectors (e.g. when running under a hypervisor) to bootstrap + * themselves into allowing full-blown kernel debugging. + */ +static void +init_debug_info(void) +{ + caddr_t mem; + debug_info_t *di; + +#ifndef __lint + ASSERT(sizeof (debug_info_t) < MMU_PAGESIZE); +#endif + + mem = BOP_ALLOC(bootops, (caddr_t)DEBUG_INFO_VA, MMU_PAGESIZE, + MMU_PAGESIZE); + + if (mem != (caddr_t)DEBUG_INFO_VA) + panic("BOP_ALLOC() failed"); + bzero(mem, MMU_PAGESIZE); + + di = (debug_info_t *)mem; + + di->di_magic = DEBUG_INFO_MAGIC; + di->di_version = DEBUG_INFO_VERSION; } /* - * The purpose of startup memlist is to get the system to the - * point where it can use kmem_alloc()'s that operate correctly - * relying on BOP_ALLOC(). This includes allocating page_ts, - * page hash table, vmem initialized, etc. - * - * Boot's versions of physinstalled and physavail are insufficient for - * the kernel's purposes. Specifically we don't know which pages that - * are not in physavail can be reclaimed after boot is gone. - * - * This code solves the problem by dividing the address space - * into 3 regions as it takes over the MMU from the booter. - * - * 1) Any (non-nucleus) pages that are mapped at addresses above KERNEL_TEXT - * can not be used by the kernel. - * - * 2) Any free page that happens to be mapped below kernelbase - * is protected until the boot loader is released, but will then be reclaimed. - * - * 3) Boot shouldn't use any address in the remaining area between kernelbase - * and KERNEL_TEXT. - * - * In the case of multiple mappings to the same page, region 1 has precedence - * over region 2. + * Build the memlists and other kernel essential memory system data structures. + * This is everything at valloc_base. */ static void startup_memlist(void) @@ -857,55 +832,31 @@ startup_memlist(void) caddr_t page_ctrs_mem; size_t page_ctrs_size; struct memlist *current; - pgcnt_t orig_npages = 0; extern void startup_build_mem_nodes(struct memlist *); /* XX64 fix these - they should be in include files */ - extern ulong_t cr4_value; extern size_t page_coloring_init(uint_t, int, int); extern void page_coloring_setup(caddr_t); PRM_POINT("startup_memlist() starting..."); /* - * Take the most current snapshot we can by calling mem-update. - * For this to work properly, we first have to ask boot for its - * end address. - */ - if (BOP_GETPROPLEN(bootops, "memory-update") == 0) - (void) BOP_GETPROP(bootops, "memory-update", NULL); - - /* - * find if the kernel is mapped on a large page - */ - va = KERNEL_TEXT; - if (hat_boot_probe(&va, &len, &pfn, &prot) == 0) - panic("Couldn't find kernel text boot mapping"); - - /* * Use leftover large page nucleus text/data space for loadable modules. * Use at most MODTEXT/MODDATA. */ - if (len > MMU_PAGESIZE) { - - moddata = (caddr_t)ROUND_UP_PAGE(e_data); - e_moddata = (caddr_t)ROUND_UP_4MEG(e_data); - if (e_moddata - moddata > MODDATA) - e_moddata = moddata + MODDATA; + len = kbm_nucleus_size; + ASSERT(len > MMU_PAGESIZE); - modtext = (caddr_t)ROUND_UP_PAGE(e_text); - e_modtext = (caddr_t)ROUND_UP_4MEG(e_text); - if (e_modtext - modtext > MODTEXT) - e_modtext = modtext + MODTEXT; + moddata = (caddr_t)ROUND_UP_PAGE(e_data); + e_moddata = (caddr_t)P2ROUNDUP((uintptr_t)e_data, (uintptr_t)len); + if (e_moddata - moddata > MODDATA) + e_moddata = moddata + MODDATA; + modtext = (caddr_t)ROUND_UP_PAGE(e_text); + e_modtext = (caddr_t)P2ROUNDUP((uintptr_t)e_text, (uintptr_t)len); + if (e_modtext - modtext > MODTEXT) + e_modtext = modtext + MODTEXT; - } else { - - PRM_POINT("Kernel NOT loaded on Large Page!"); - e_moddata = moddata = (caddr_t)ROUND_UP_PAGE(e_data); - e_modtext = modtext = (caddr_t)ROUND_UP_PAGE(e_text); - - } econtig = e_moddata; PRM_DEBUG(modtext); @@ -915,21 +866,13 @@ startup_memlist(void) PRM_DEBUG(econtig); /* - * For MP machines cr4_value must be set or the non-boot - * CPUs will not be able to start. - */ - if (x86_feature & X86_LARGEPAGE) - cr4_value = getcr4(); - PRM_DEBUG(cr4_value); - - /* - * Examine the boot loaders physical memory map to find out: + * Examine the boot loader physical memory map to find out: * - total memory in system - physinstalled * - the max physical address - physmax - * - the number of segments the intsalled memory comes in + * - the number of discontiguous segments of memory. */ if (prom_debug) - print_boot_memlist("boot physinstalled", + print_memlist("boot physinstalled", bootops->boot_mem->physinstalled); installed_top_size(bootops->boot_mem->physinstalled, &physmax, &physinstalled, &memblocks); @@ -937,10 +880,6 @@ startup_memlist(void) PRM_DEBUG(physinstalled); PRM_DEBUG(memblocks); - if (prom_debug) - print_boot_memlist("boot physavail", - bootops->boot_mem->physavail); - /* * Initialize hat's mmu parameters. * Check for enforce-prot-exec in boot environment. It's used to @@ -992,7 +931,7 @@ startup_memlist(void) npages = physinstalled - 1; /* avail_filter() skips page 0, so "- 1" */ obp_pages = 0; va = KERNEL_TEXT; - while (hat_boot_probe(&va, &len, &pfn, &prot) != 0) { + while (kbm_probe(&va, &len, &pfn, &prot) != 0) { npages -= len >> MMU_PAGESHIFT; if (va >= (uintptr_t)e_moddata) obp_pages += len >> MMU_PAGESHIFT; @@ -1029,9 +968,8 @@ startup_memlist(void) PRM_DEBUG(memseg_sz); /* - * Reserve space for phys_avail/phys_install memlists. - * There's no real good way to know exactly how much room we'll need, - * but this should be a good upper bound. + * Reserve space for memlists. There's no real good way to know exactly + * how much room we'll need, but this should be a good upper bound. */ memlist_sz = ROUND_UP_PAGE(2 * sizeof (struct memlist) * (memblocks + POSS_NEW_FRAGMENTS)); @@ -1049,23 +987,10 @@ startup_memlist(void) PRM_DEBUG(pagehash_sz); /* - * Set aside room for the page structures themselves. Note: on - * 64-bit systems we don't allocate page_t's for every page here. - * We just allocate enough to map the lowest 4GB of physical - * memory, minus those pages that are used for the "nucleus" kernel - * text and data. The remaining pages are allocated once we can - * map around boot. - * - * boot_npages is used to allocate an area big enough for our - * initial page_t's. kphym_init may use less than that. + * Set aside room for the page structures themselves. */ - boot_npages = npages; -#if defined(__amd64) - if (npages > mmu_btop(FOURGB - (econtig - s_text))) - boot_npages = mmu_btop(FOURGB - (econtig - s_text)); -#endif - PRM_DEBUG(boot_npages); - pp_sz = sizeof (struct page) * boot_npages; + PRM_DEBUG(npages); + pp_sz = sizeof (struct page) * npages; ADD_TO_ALLOCATIONS(pp_base, pp_sz); PRM_DEBUG(pp_sz); @@ -1083,14 +1008,83 @@ startup_memlist(void) ADD_TO_ALLOCATIONS(page_ctrs_mem, page_ctrs_size); PRM_DEBUG(page_ctrs_size); - /* - * valloc_base will be below kernel text - * The extra pages are for the HAT and kmdb to map page tables. - */ +#if defined(__amd64) valloc_sz = ROUND_UP_LPAGE(valloc_sz); - valloc_base = KERNEL_TEXT - valloc_sz; + valloc_base = VALLOC_BASE; +#else /* __i386 */ + valloc_base = (uintptr_t)(MISC_VA_BASE - valloc_sz); + valloc_base = P2ALIGN(valloc_base, mmu.level_size[1]); +#endif /* __i386 */ PRM_DEBUG(valloc_base); - ptable_va = valloc_base - ptable_sz; + + /* + * do all the initial allocations + */ + perform_allocations(); + + /* + * Build phys_install and phys_avail in kernel memspace. + * - phys_install should be all memory in the system. + * - phys_avail is phys_install minus any memory mapped before this + * point above KERNEL_TEXT. + */ + current = phys_install = memlist; + copy_memlist_filter(bootops->boot_mem->physinstalled, ¤t, NULL); + if ((caddr_t)current > (caddr_t)memlist + memlist_sz) + panic("physinstalled was too big!"); + if (prom_debug) + print_memlist("phys_install", phys_install); + + phys_avail = current; + PRM_POINT("Building phys_avail:\n"); + copy_memlist_filter(bootops->boot_mem->physinstalled, ¤t, + avail_filter); + if ((caddr_t)current > (caddr_t)memlist + memlist_sz) + panic("physavail was too big!"); + if (prom_debug) + print_memlist("phys_avail", phys_avail); + + /* + * setup page coloring + */ + page_coloring_setup(pagecolor_mem); + page_lock_init(); /* currently a no-op */ + + /* + * free page list counters + */ + (void) page_ctrs_alloc(page_ctrs_mem); + + /* + * Initialize the page structures from the memory lists. + */ + availrmem_initial = availrmem = freemem = 0; + PRM_POINT("Calling kphysm_init()..."); + npages = kphysm_init(pp_base, npages); + PRM_POINT("kphysm_init() done"); + PRM_DEBUG(npages); + + init_debug_info(); + + /* + * Now that page_t's have been initialized, remove all the + * initial allocation pages from the kernel free page lists. + */ + boot_mapin((caddr_t)valloc_base, valloc_sz); + boot_mapin((caddr_t)GDT_VA, MMU_PAGESIZE); + boot_mapin((caddr_t)DEBUG_INFO_VA, MMU_PAGESIZE); + PRM_POINT("startup_memlist() done"); + + PRM_DEBUG(valloc_sz); +} + +/* + * Layout the kernel's part of address space and initialize kmem allocator. + */ +static void +startup_kmem(void) +{ + PRM_POINT("startup_kmem() starting..."); #if defined(__amd64) if (eprom_kernelbase && eprom_kernelbase != KERNELBASE) @@ -1098,7 +1092,7 @@ startup_memlist(void) "systems."); kernelbase = (uintptr_t)KERNELBASE; core_base = (uintptr_t)COREHEAP_BASE; - core_size = ptable_va - core_base; + core_size = (size_t)MISC_VA_BASE - COREHEAP_BASE; #else /* __i386 */ /* * We configure kernelbase based on: @@ -1121,48 +1115,43 @@ startup_memlist(void) kernelbase -= ROUND_UP_4MEG(2 * valloc_sz); } ASSERT((kernelbase & mmu.level_offset[1]) == 0); - core_base = ptable_va; + core_base = valloc_base; core_size = 0; -#endif +#endif /* __i386 */ - PRM_DEBUG(kernelbase); PRM_DEBUG(core_base); PRM_DEBUG(core_size); + PRM_DEBUG(kernelbase); /* * At this point, we can only use a portion of the kernelheap that - * will be available after we boot. Both 32-bit and 64-bit systems - * have this limitation, although the reasons are completely - * different. - * - * On 64-bit systems, the booter only supports allocations in the - * upper 4GB of memory, so we have to work with a reduced kernel - * heap until we take over all allocations. The booter also sits - * in the lower portion of that 4GB range, so we have to raise the - * bottom of the heap even further. + * will be available after we boot. 32-bit systems have this + * limitation. * * On 32-bit systems we have to leave room to place segmap below * the heap. We don't yet know how large segmap will be, so we * have to be very conservative. + * + * On 64 bit systems there should be LOTS of room so just use + * the next 4Gig below core_base. */ #if defined(__amd64) - /* - * XX64: For now, we let boot have the lower 2GB of the top 4GB - * address range. In the long run, that should be fixed. It's - * insane for a booter to need 2 2GB address ranges. - */ - boot_kernelheap = (caddr_t)(BOOT_DOUBLEMAP_BASE + BOOT_DOUBLEMAP_SIZE); + + boot_kernelheap = (caddr_t)core_base - FOURGB; segmap_reserved = 0; #else /* __i386 */ + segkp_fromheap = 1; segmap_reserved = ROUND_UP_LPAGE(MAX(segmapsize, SEGMAPMAX)); - boot_kernelheap = (caddr_t)(ROUND_UP_LPAGE(kernelbase) + - segmap_reserved); -#endif + boot_kernelheap = + (caddr_t)ROUND_UP_LPAGE(kernelbase) + segmap_reserved; + +#endif /* __i386 */ PRM_DEBUG(boot_kernelheap); - kernelheap = boot_kernelheap; ekernelheap = (char *)core_base; + PRM_DEBUG(ekernelheap); + kernelheap = boot_kernelheap; /* * If segmap is too large we can push the bottom of the kernel heap @@ -1187,11 +1176,6 @@ startup_memlist(void) #if defined(__amd64) ASSERT(_kernelbase == KERNELBASE); ASSERT(_userlimit == USERLIMIT); - /* - * As one final sanity check, verify that the "red zone" between - * kernel and userspace is exactly the size we expected. - */ - ASSERT(_kernelbase == (_userlimit + (2 * 1024 * 1024))); #else *(uintptr_t *)&_kernelbase = kernelbase; *(uintptr_t *)&_userlimit = kernelbase; @@ -1202,63 +1186,11 @@ startup_memlist(void) PRM_DEBUG(_userlimit32); /* - * do all the initial allocations - */ - perform_allocations(); - - /* * Initialize the kernel heap. Note 3rd argument must be > 1st. */ - kernelheap_init(kernelheap, ekernelheap, kernelheap + MMU_PAGESIZE, - (void *)core_base, (void *)ptable_va); - - /* - * Build phys_install and phys_avail in kernel memspace. - * - phys_install should be all memory in the system. - * - phys_avail is phys_install minus any memory mapped before this - * point above KERNEL_TEXT. - */ - current = phys_install = memlist; - copy_memlist_filter(bootops->boot_mem->physinstalled, ¤t, NULL); - if ((caddr_t)current > (caddr_t)memlist + memlist_sz) - panic("physinstalled was too big!"); - if (prom_debug) - print_kernel_memlist("phys_install", phys_install); - - phys_avail = current; - PRM_POINT("Building phys_avail:\n"); - copy_memlist_filter(bootops->boot_mem->physinstalled, ¤t, - avail_filter); - if ((caddr_t)current > (caddr_t)memlist + memlist_sz) - panic("physavail was too big!"); - if (prom_debug) - print_kernel_memlist("phys_avail", phys_avail); - - /* - * setup page coloring - */ - page_coloring_setup(pagecolor_mem); - page_lock_init(); /* currently a no-op */ - - /* - * free page list counters - */ - (void) page_ctrs_alloc(page_ctrs_mem); - - /* - * Initialize the page structures from the memory lists. - */ - availrmem_initial = availrmem = freemem = 0; - PRM_POINT("Calling kphysm_init()..."); - boot_npages = kphysm_init(pp_base, memseg_base, 0, boot_npages); - PRM_POINT("kphysm_init() done"); - PRM_DEBUG(boot_npages); - - /* - * Now that page_t's have been initialized, remove all the - * initial allocation pages from the kernel free page lists. - */ - boot_mapin((caddr_t)valloc_base, valloc_sz); + kernelheap_init(boot_kernelheap, ekernelheap, + boot_kernelheap + MMU_PAGESIZE, + (void *)core_base, (void *)(core_base + core_size)); /* * Initialize kernel memory allocator. @@ -1286,7 +1218,7 @@ startup_memlist(void) * modified via /etc/system in kmem_init/mod_read_system_file. */ if (npages == PHYSMEM32) { - cmn_err(CE_WARN, "!Due to 32 bit virtual" + cmn_err(CE_WARN, "!Due to 32-bit virtual" " address space limitations, limiting" " physmem to 0x%lx of 0x%lx available pages", npages, orig_npages); @@ -1313,7 +1245,7 @@ startup_memlist(void) } #endif - PRM_POINT("startup_memlist() done"); + PRM_POINT("startup_kmem() done"); } static void @@ -1334,7 +1266,7 @@ startup_modules(void) /* * Read the GMT lag from /etc/rtc_config. */ - gmt_lag = process_rtc_config_file(); + sgmtl(process_rtc_config_file()); /* * Calculate default settings of system parameters based upon @@ -1414,34 +1346,46 @@ startup_modules(void) /* * Fake a prom tree such that /dev/openprom continues to work */ + PRM_POINT("startup_modules: calling prom_setup..."); prom_setup(); + PRM_POINT("startup_modules: done"); /* * Load all platform specific modules */ + PRM_POINT("startup_modules: calling psm_modload..."); psm_modload(); PRM_POINT("startup_modules() done"); } -static void -startup_bop_gone(void) +/* + * claim a "setaside" boot page for use in the kernel + */ +page_t * +boot_claim_page(pfn_t pfn) { - PRM_POINT("startup_bop_gone() starting..."); + page_t *pp; - /* - * Do final allocations of HAT data structures that need to - * be allocated before quiescing the boot loader. - */ - PRM_POINT("Calling hat_kern_alloc()..."); - hat_kern_alloc(); - PRM_POINT("hat_kern_alloc() done"); + pp = page_numtopp_nolock(pfn); + ASSERT(pp != NULL); - /* - * Setup MTRR (Memory type range registers) - */ - setup_mtrr(); - PRM_POINT("startup_bop_gone() done"); + if (PP_ISBOOTPAGES(pp)) { + if (pp->p_next != NULL) + pp->p_next->p_prev = pp->p_prev; + if (pp->p_prev == NULL) + bootpages = pp->p_next; + else + pp->p_prev->p_next = pp->p_next; + } else { + /* + * htable_attach() expects a base pagesize page + */ + if (pp->p_szc != 0) + page_boot_demote(pp); + pp = page_numtopp(pfn, SE_EXCL); + } + return (pp); } /* @@ -1459,7 +1403,7 @@ protect_boot_range(uintptr_t low, uintptr_t high, int setaside) page_t *pp; pgcnt_t boot_protect_cnt = 0; - while (hat_boot_probe(&va, &len, &pfn, &prot) != 0 && va < high) { + while (kbm_probe(&va, &len, &pfn, &prot) != 0 && va < high) { if (va + len >= high) panic("0x%lx byte mapping at 0x%p exceeds boot's " "legal range.", len, (void *)va); @@ -1473,6 +1417,11 @@ protect_boot_range(uintptr_t low, uintptr_t high, int setaside) (void *)va, pfn); pp->p_next = bootpages; + pp->p_prev = NULL; + PP_SETBOOTPAGES(pp); + if (bootpages != NULL) { + bootpages->p_prev = pp; + } bootpages = pp; ++boot_protect_cnt; } @@ -1485,87 +1434,53 @@ protect_boot_range(uintptr_t low, uintptr_t high, int setaside) PRM_DEBUG(boot_protect_cnt); } +/* + * Finish initializing the VM system, now that we are no longer + * relying on the boot time memory allocators. + */ static void startup_vm(void) { struct segmap_crargs a; - extern void hat_kern_setup(void); - pgcnt_t pages_left; extern int use_brk_lpg, use_stk_lpg; PRM_POINT("startup_vm() starting..."); /* - * The next two loops are done in distinct steps in order - * to be sure that any page that is doubly mapped (both above - * KERNEL_TEXT and below kernelbase) is dealt with correctly. - * Note this may never happen, but it might someday. - */ - - bootpages = NULL; - PRM_POINT("Protecting boot pages"); - /* - * Protect any pages mapped above KERNEL_TEXT that somehow have - * page_t's. This can only happen if something weird allocated - * in this range (like kadb/kmdb). + * Establish the final size of the kernel's heap, size of segmap, + * segkp, etc. */ - protect_boot_range(KERNEL_TEXT, (uintptr_t)-1, 0); - /* - * Before we can take over memory allocation/mapping from the boot - * loader we must remove from our free page lists any boot pages that - * will stay mapped until release_bootstrap(). - */ - protect_boot_range(0, kernelbase, 1); #if defined(__amd64) - protect_boot_range(BOOT_DOUBLEMAP_BASE, - BOOT_DOUBLEMAP_BASE + BOOT_DOUBLEMAP_SIZE, 0); -#endif - - /* - * Copy in boot's page tables, set up extra page tables for the kernel, - * and switch to the kernel's context. - */ - PRM_POINT("Calling hat_kern_setup()..."); - hat_kern_setup(); /* - * It is no longer safe to call BOP_ALLOC(), so make sure we don't. + * Check if there is enough virtual address space in KPM region to + * map physmax. */ - bootops->bsys_alloc = NULL; - PRM_POINT("hat_kern_setup() done"); + kpm_vbase = (caddr_t)(uintptr_t)SEGKPM_BASE; + kpm_size = 0; + if (kpm_desired) { + kpm_size = ROUND_UP_LPAGE(mmu_ptob(physmax + 1)); + if ((uintptr_t)kpm_vbase + kpm_size > (uintptr_t)VALLOC_BASE) { + kpm_size = 0; + kpm_desired = 0; + } + } - hat_cpu_online(CPU); + PRM_DEBUG(kpm_size); + PRM_DEBUG(kpm_vbase); /* - * Before we call kvm_init(), we need to establish the final size - * of the kernel's heap. So, we need to figure out how much space - * to set aside for segkp, segkpm, and segmap. + * By default we create a seg_kp in 64 bit kernels, it's a little + * faster to access than embedding it in the heap. */ - final_kernelheap = (caddr_t)ROUND_UP_LPAGE(kernelbase); -#if defined(__amd64) - if (kpm_desired) { - /* - * Segkpm appears at the bottom of the kernel's address - * range. To detect accidental overruns of the user - * address space, we leave a "red zone" of unmapped memory - * between kernelbase and the beginning of segkpm. - */ - kpm_vbase = final_kernelheap + KERNEL_REDZONE_SIZE; - kpm_size = mmu_ptob(physmax + 1); - PRM_DEBUG(kpm_vbase); - PRM_DEBUG(kpm_size); - final_kernelheap = - (caddr_t)ROUND_UP_TOPLEVEL(kpm_vbase + kpm_size); - } - + segkp_base = (caddr_t)valloc_base + valloc_sz; if (!segkp_fromheap) { size_t sz = mmu_ptob(segkpsize); /* - * determine size of segkp and adjust the bottom of the - * kernel's heap. + * determine size of segkp */ if (sz < SEGKPMINSIZE || sz > SEGKPMAXSIZE) { sz = SEGKPDEFSIZE; @@ -1576,14 +1491,14 @@ startup_vm(void) sz = MIN(sz, MAX(SEGKPMINSIZE, mmu_ptob(physmem))); segkpsize = mmu_btop(ROUND_UP_LPAGE(sz)); - segkp_base = final_kernelheap; - PRM_DEBUG(segkpsize); - PRM_DEBUG(segkp_base); - final_kernelheap = segkp_base + mmu_ptob(segkpsize); - PRM_DEBUG(final_kernelheap); } + PRM_DEBUG(segkp_base); + PRM_DEBUG(segkpsize); - if (!segzio_fromheap) { + segzio_base = segkp_base + mmu_ptob(segkpsize); + if (segzio_fromheap) { + segziosize = 0; + } else { size_t size; size_t maxsize; @@ -1603,22 +1518,23 @@ startup_vm(void) size = maxsize; } segziosize = mmu_btop(ROUND_UP_LPAGE(size)); - segzio_base = final_kernelheap; - PRM_DEBUG(segziosize); - PRM_DEBUG(segzio_base); - final_kernelheap = segzio_base + mmu_ptob(segziosize); - PRM_DEBUG(final_kernelheap); } + PRM_DEBUG(segziosize); + PRM_DEBUG(segzio_base); /* - * put the range of VA for device mappings next + * Put the range of VA for device mappings next, kmdb knows to not + * grep in this range of addresses. */ - toxic_addr = (uintptr_t)final_kernelheap; + toxic_addr = + ROUND_UP_LPAGE((uintptr_t)segzio_base + mmu_ptob(segziosize)); PRM_DEBUG(toxic_addr); - final_kernelheap = (char *)toxic_addr + toxic_size; -#endif - PRM_DEBUG(final_kernelheap); - ASSERT(final_kernelheap < boot_kernelheap); + segmap_start = ROUND_UP_LPAGE(toxic_addr + toxic_size); +#else /* __i386 */ + segmap_start = ROUND_UP_LPAGE(kernelbase); +#endif /* __i386 */ + PRM_DEBUG(segmap_start); + ASSERT((caddr_t)segmap_start < boot_kernelheap); /* * Users can change segmapsize through eeprom or /etc/system. @@ -1628,7 +1544,6 @@ startup_vm(void) * planned for in startup_memlist(). */ segmapsize = MAX(ROUND_UP_LPAGE(segmapsize), SEGMAPDEFAULT); - segkmap_start = ROUND_UP_LPAGE((uintptr_t)final_kernelheap); #if defined(__i386) if (segmapsize > segmap_reserved) { @@ -1639,18 +1554,69 @@ startup_vm(void) /* * 32-bit systems don't have segkpm or segkp, so segmap appears at * the bottom of the kernel's address range. Set aside space for a - * red zone just below the start of segmap. + * small red zone just below the start of segmap. */ - segkmap_start += KERNEL_REDZONE_SIZE; + segmap_start += KERNEL_REDZONE_SIZE; segmapsize -= KERNEL_REDZONE_SIZE; #endif - final_kernelheap = (char *)(segkmap_start + segmapsize); - PRM_DEBUG(segkmap_start); + PRM_DEBUG(segmap_start); PRM_DEBUG(segmapsize); + final_kernelheap = (caddr_t)ROUND_UP_LPAGE(segmap_start + segmapsize); PRM_DEBUG(final_kernelheap); /* + * Do final allocations of HAT data structures that need to + * be allocated before quiescing the boot loader. + */ + PRM_POINT("Calling hat_kern_alloc()..."); + hat_kern_alloc((caddr_t)segmap_start, segmapsize, ekernelheap); + PRM_POINT("hat_kern_alloc() done"); + + /* + * Setup MTRR (Memory type range registers) + */ + setup_mtrr(); + + /* + * The next two loops are done in distinct steps in order + * to be sure that any page that is doubly mapped (both above + * KERNEL_TEXT and below kernelbase) is dealt with correctly. + * Note this may never happen, but it might someday. + */ + bootpages = NULL; + PRM_POINT("Protecting boot pages"); + + /* + * Protect any pages mapped above KERNEL_TEXT that somehow have + * page_t's. This can only happen if something weird allocated + * in this range (like kadb/kmdb). + */ + protect_boot_range(KERNEL_TEXT, (uintptr_t)-1, 0); + + /* + * Before we can take over memory allocation/mapping from the boot + * loader we must remove from our free page lists any boot allocated + * pages that stay mapped until release_bootstrap(). + */ + protect_boot_range(0, kernelbase, 1); + + /* + * Switch to running on regular HAT (not boot_mmu) + */ + PRM_POINT("Calling hat_kern_setup()..."); + hat_kern_setup(); + + /* + * It is no longer safe to call BOP_ALLOC(), so make sure we don't. + */ + bop_no_more_mem(); + + PRM_POINT("hat_kern_setup() done"); + + hat_cpu_online(CPU); + + /* * Initialize VM system */ PRM_POINT("Calling kvm_init()..."); @@ -1668,37 +1634,16 @@ startup_vm(void) */ cpuid_pass3(CPU); - PRM_DEBUG(final_kernelheap); - /* * Now that we can use memory outside the top 4GB (on 64-bit * systems) and we know the size of segmap, we can set the final - * size of the kernel's heap. Note: on 64-bit systems we still - * can't touch anything in the bottom half of the top 4GB range - * because boot still has pages mapped there. + * size of the kernel's heap. */ if (final_kernelheap < boot_kernelheap) { + PRM_POINT("kernelheap_extend()"); + PRM_DEBUG(boot_kernelheap); + PRM_DEBUG(final_kernelheap); kernelheap_extend(final_kernelheap, boot_kernelheap); -#if defined(__amd64) - kmem_setaside = vmem_xalloc(heap_arena, BOOT_DOUBLEMAP_SIZE, - MMU_PAGESIZE, 0, 0, (void *)(BOOT_DOUBLEMAP_BASE), - (void *)(BOOT_DOUBLEMAP_BASE + BOOT_DOUBLEMAP_SIZE), - VM_NOSLEEP | VM_BESTFIT | VM_PANIC); - PRM_DEBUG(kmem_setaside); - if (kmem_setaside == NULL) - panic("Could not protect boot's memory"); -#endif - } - /* - * Now that the kernel heap may have grown significantly, we need - * to make all the remaining page_t's available to back that memory. - * - * XX64 this should probably wait till after release boot-strap too. - */ - pages_left = npages - boot_npages; - if (pages_left > 0) { - PRM_DEBUG(pages_left); - (void) kphysm_init(NULL, memseg_base, boot_npages, pages_left); } #if defined(__amd64) @@ -1714,7 +1659,7 @@ startup_vm(void) /* * allocate the bit map that tracks toxic pages */ - toxic_bit_map_len = btop((ulong_t)(ptable_va - kernelbase)); + toxic_bit_map_len = btop((ulong_t)(valloc_base - kernelbase)); PRM_DEBUG(toxic_bit_map_len); toxic_bit_map = kmem_zalloc(BT_SIZEOFMAP(toxic_bit_map_len), KM_NOSLEEP); @@ -1737,23 +1682,24 @@ startup_vm(void) */ #if !defined(__amd64) if (x86_type == X86_TYPE_P5) { + desctbr_t idtr; gate_desc_t *newidt; - desctbr_t newidt_r; + struct machcpu *mcpu = &CPU->cpu_m; if ((newidt = kmem_zalloc(MMU_PAGESIZE, KM_NOSLEEP)) == NULL) panic("failed to install pentium_pftrap"); bcopy(idt0, newidt, sizeof (idt0)); set_gatesegd(&newidt[T_PGFLT], &pentium_pftrap, - KCS_SEL, 0, SDT_SYSIGT, SEL_KPL); + KCS_SEL, SDT_SYSIGT, SEL_KPL); (void) as_setprot(&kas, (caddr_t)newidt, MMU_PAGESIZE, PROT_READ|PROT_EXEC); - newidt_r.dtr_limit = sizeof (idt0) - 1; - newidt_r.dtr_base = (uintptr_t)newidt; - CPU->cpu_idt = newidt; - wr_idtr(&newidt_r); + mcpu->mcpu_idt = newidt; + idtr.dtr_base = (uintptr_t)mcpu->mcpu_idt; + idtr.dtr_limit = sizeof (idt0) - 1; + wr_idtr(&idtr); } #endif /* !__amd64 */ @@ -1797,20 +1743,15 @@ startup_vm(void) * Initialize the segkp segment type. */ rw_enter(&kas.a_lock, RW_WRITER); - if (!segkp_fromheap) { - if (seg_attach(&kas, (caddr_t)segkp_base, mmu_ptob(segkpsize), - segkp) < 0) { - panic("startup: cannot attach segkp"); - /*NOTREACHED*/ - } - } else { - /* - * For 32 bit x86 systems, we will have segkp under the heap. - * There will not be a segkp segment. We do, however, need - * to fill in the seg structure. - */ + PRM_POINT("Attaching segkp"); + if (segkp_fromheap) { segkp->s_as = &kas; + } else if (seg_attach(&kas, (caddr_t)segkp_base, mmu_ptob(segkpsize), + segkp) < 0) { + panic("startup: cannot attach segkp"); + /*NOTREACHED*/ } + PRM_POINT("Doing segkp_create()"); if (segkp_create(segkp) != 0) { panic("startup: segkp_create failed"); /*NOTREACHED*/ @@ -1832,38 +1773,38 @@ startup_vm(void) * Now create segmap segment. */ rw_enter(&kas.a_lock, RW_WRITER); - if (seg_attach(&kas, (caddr_t)segkmap_start, segmapsize, segkmap) < 0) { - panic("cannot attach segkmap"); + if (seg_attach(&kas, (caddr_t)segmap_start, segmapsize, segmap) < 0) { + panic("cannot attach segmap"); /*NOTREACHED*/ } - PRM_DEBUG(segkmap); - - /* - * The 64 bit HAT permanently maps only segmap's page tables. - * The 32 bit HAT maps the heap's page tables too. - */ -#if defined(__amd64) - hat_kmap_init(segkmap_start, segmapsize); -#else /* __i386 */ - ASSERT(segkmap_start + segmapsize == (uintptr_t)final_kernelheap); - hat_kmap_init(segkmap_start, (uintptr_t)ekernelheap - segkmap_start); -#endif /* __i386 */ + PRM_DEBUG(segmap); a.prot = PROT_READ | PROT_WRITE; a.shmsize = 0; a.nfreelist = segmapfreelists; - if (segmap_create(segkmap, (caddr_t)&a) != 0) - panic("segmap_create segkmap"); + if (segmap_create(segmap, (caddr_t)&a) != 0) + panic("segmap_create segmap"); rw_exit(&kas.a_lock); setup_vaddr_for_ppcopy(CPU); segdev_init(); pmem_init(); + PRM_POINT("startup_vm() done"); } +/* + * Load a tod module for the non-standard tod part found on this system. + */ +static void +load_tod_module(char *todmod) +{ + if (modload("tod", todmod) == -1) + halt("Can't load TOD module"); +} + static void startup_end(void) { @@ -1883,22 +1824,20 @@ startup_end(void) */ kcpc_hw_init(CPU); -#if defined(__amd64) - /* - * Validate support for syscall/sysret - * XX64 -- include SSE, SSE2, etc. here too? - */ - if ((x86_feature & X86_ASYSC) == 0) { - cmn_err(CE_WARN, - "cpu%d does not support syscall/sysret", CPU->cpu_id); - } -#endif - #if defined(OPTERON_WORKAROUND_6323525) if (opteron_workaround_6323525) patch_workaround_6323525(); #endif /* + * If needed, load TOD module now so that ddi_get_time(9F) etc. work + * (For now, "needed" is defined as set tod_module_name in /etc/system) + */ + if (tod_module_name != NULL) { + PRM_POINT("load_tod_module()"); + load_tod_module(tod_module_name); + } + + /* * Configure the system. */ PRM_POINT("Calling configure()..."); @@ -1917,8 +1856,8 @@ startup_end(void) * We're done with bootops. We don't unmap the bootstrap yet because * we're still using bootsvcs. */ - PRM_POINT("zeroing out bootops"); - *bootopsp = (struct bootops *)0; + PRM_POINT("NULLing out bootops"); + *bootopsp = (struct bootops *)NULL; bootops = (struct bootops *)NULL; PRM_POINT("Enabling interrupts"); @@ -1946,13 +1885,13 @@ post_startup(void) bind_hwcap(); /* - * Load the System Management BIOS into the global ksmbios handle, - * if an SMBIOS is present on this system. + * Load the System Management BIOS into the global ksmbios + * handle, if an SMBIOS is present on this system. */ ksmbios = smbios_open(NULL, SMB_VERSION, ksmbios_flags, NULL); /* - * Startup memory scrubber. + * Startup the memory scrubber. */ memscrub_init(); @@ -1999,7 +1938,6 @@ void release_bootstrap(void) { int root_is_ramdisk; - pfn_t pfn; page_t *pp; extern void kobj_boot_unmountroot(void); extern dev_t rootdev; @@ -2011,12 +1949,8 @@ release_bootstrap(void) * We're finished using the boot loader so free its pages. */ PRM_POINT("Unmapping lower boot pages"); - clear_boot_mappings(0, kernelbase); -#if defined(__amd64) - PRM_POINT("Unmapping upper boot pages"); - clear_boot_mappings(BOOT_DOUBLEMAP_BASE, - BOOT_DOUBLEMAP_BASE + BOOT_DOUBLEMAP_SIZE); -#endif + clear_boot_mappings(0, _userlimit); + postbootkernelbase = kernelbase; /* * If root isn't on ramdisk, destroy the hardcoded @@ -2041,8 +1975,11 @@ release_bootstrap(void) continue; } pp->p_next = (struct page *)0; + pp->p_prev = (struct page *)0; + PP_CLRBOOTPAGES(pp); page_free(pp, 1); } + PRM_POINT("Boot pages released"); /* * Find 1 page below 1 MB so that other processors can boot up. @@ -2050,6 +1987,8 @@ release_bootstrap(void) * We should have just free'd one up. */ if (use_mp) { + pfn_t pfn; + for (pfn = 1; pfn < btop(1*1024*1024); pfn++) { if (page_numtopp_alloc(pfn) == NULL) continue; @@ -2067,11 +2006,6 @@ release_bootstrap(void) "other processors"); } -#if defined(__amd64) - PRM_POINT("Returning boot's VA space to kernel heap"); - if (kmem_setaside != NULL) - vmem_free(heap_arena, kmem_setaside, BOOT_DOUBLEMAP_SIZE); -#endif } /* @@ -2092,31 +2026,21 @@ add_physmem_cb(page_t *pp, pfn_t pnum) */ static pgcnt_t kphysm_init( - page_t *inpp, - struct memseg *memsegp, - pgcnt_t start, + page_t *pp, pgcnt_t npages) { struct memlist *pmem; struct memseg *cur_memseg; - struct memseg **memsegpp; pfn_t base_pfn; pgcnt_t num; - pgcnt_t total_skipped = 0; - pgcnt_t skipping = 0; pgcnt_t pages_done = 0; - pgcnt_t largepgcnt; uint64_t addr; uint64_t size; - page_t *pp = inpp; - int dobreak = 0; extern pfn_t ddiphysmin; ASSERT(page_hash != NULL && page_hashsz != 0); - for (cur_memseg = memsegp; cur_memseg->pages != NULL; cur_memseg++); - ASSERT(cur_memseg == memsegp || start > 0); - + cur_memseg = memseg_base; for (pmem = phys_avail; pmem && npages; pmem = pmem->next) { /* * In a 32 bit kernel can't use higher memory if we're @@ -2144,19 +2068,6 @@ kphysm_init( if (num == 0) continue; - if (total_skipped < start) { - if (start - total_skipped > num) { - total_skipped += num; - continue; - } - skipping = start - total_skipped; - num -= skipping; - addr += (MMU_PAGESIZE * skipping); - total_skipped = start; - } - if (num == 0) - continue; - if (num > npages) num = npages; @@ -2164,62 +2075,23 @@ kphysm_init( pages_done += num; base_pfn = btop(addr); - /* - * If the caller didn't provide space for the page - * structures, carve them out of the memseg they will - * represent. - */ - if (pp == NULL) { - pgcnt_t pp_pgs; - - if (num <= 1) - continue; - - /* - * Compute how many of the pages we need to use for - * page_ts - */ - pp_pgs = (num * sizeof (page_t)) / MMU_PAGESIZE + 1; - while (mmu_ptob(pp_pgs - 1) / sizeof (page_t) >= - num - pp_pgs + 1) - --pp_pgs; - PRM_DEBUG(pp_pgs); - - pp = vmem_alloc(heap_arena, mmu_ptob(pp_pgs), - VM_NOSLEEP); - if (pp == NULL) { - cmn_err(CE_WARN, "Unable to add %ld pages to " - "the system.", num); - continue; - } - - hat_devload(kas.a_hat, (void *)pp, mmu_ptob(pp_pgs), - base_pfn, PROT_READ | PROT_WRITE | HAT_UNORDERED_OK, - HAT_LOAD | HAT_LOAD_LOCK | HAT_LOAD_NOCONSIST); - bzero(pp, mmu_ptob(pp_pgs)); - num -= pp_pgs; - base_pfn += pp_pgs; - } - if (prom_debug) prom_printf("MEMSEG addr=0x%" PRIx64 " pgs=0x%lx pfn 0x%lx-0x%lx\n", addr, num, base_pfn, base_pfn + num); /* - * drop pages below ddiphysmin to simplify ddi memory + * Ignore pages below ddiphysmin to simplify ddi memory * allocation with non-zero addr_lo requests. */ if (base_pfn < ddiphysmin) { - if (base_pfn + num <= ddiphysmin) { - /* drop entire range below ddiphysmin */ + if (base_pfn + num <= ddiphysmin) continue; - } - /* adjust range to ddiphysmin */ pp += (ddiphysmin - base_pfn); num -= (ddiphysmin - base_pfn); base_pfn = ddiphysmin; } + /* * Build the memsegs entry */ @@ -2229,121 +2101,18 @@ kphysm_init( cur_memseg->pages_end = base_pfn + num; /* - * insert in memseg list in decreasing pfn range order. + * Insert into memseg list in decreasing pfn range order. * Low memory is typically more fragmented such that this * ordering keeps the larger ranges at the front of the list * for code that searches memseg. + * This ASSERTS that the memsegs coming in from boot are in + * increasing physical address order and not contiguous. */ - memsegpp = &memsegs; - for (;;) { - if (*memsegpp == NULL) { - /* empty memsegs */ - memsegs = cur_memseg; - break; - } - /* check for continuity with start of memsegpp */ - if (cur_memseg->pages_end == (*memsegpp)->pages_base) { - if (cur_memseg->epages == (*memsegpp)->pages) { - /* - * contiguous pfn and page_t's. Merge - * cur_memseg into *memsegpp. Drop - * cur_memseg - */ - (*memsegpp)->pages_base = - cur_memseg->pages_base; - (*memsegpp)->pages = - cur_memseg->pages; - /* - * check if contiguous with the end of - * the next memseg. - */ - if ((*memsegpp)->next && - ((*memsegpp)->pages_base == - (*memsegpp)->next->pages_end)) { - cur_memseg = *memsegpp; - memsegpp = &((*memsegpp)->next); - dobreak = 1; - } else { - break; - } - } else { - /* - * contiguous pfn but not page_t's. - * drop last pfn/page_t in cur_memseg - * to prevent creation of large pages - * with noncontiguous page_t's if not - * aligned to largest page boundary. - */ - largepgcnt = page_get_pagecnt( - page_num_pagesizes() - 1); - - if (cur_memseg->pages_end & - (largepgcnt - 1)) { - num--; - cur_memseg->epages--; - cur_memseg->pages_end--; - } - } - } - - /* check for continuity with end of memsegpp */ - if (cur_memseg->pages_base == (*memsegpp)->pages_end) { - if (cur_memseg->pages == (*memsegpp)->epages) { - /* - * contiguous pfn and page_t's. Merge - * cur_memseg into *memsegpp. Drop - * cur_memseg. - */ - if (dobreak) { - /* merge previously done */ - cur_memseg->pages = - (*memsegpp)->pages; - cur_memseg->pages_base = - (*memsegpp)->pages_base; - cur_memseg->next = - (*memsegpp)->next; - } else { - (*memsegpp)->pages_end = - cur_memseg->pages_end; - (*memsegpp)->epages = - cur_memseg->epages; - } - break; - } - /* - * contiguous pfn but not page_t's. - * drop first pfn/page_t in cur_memseg - * to prevent creation of large pages - * with noncontiguous page_t's if not - * aligned to largest page boundary. - */ - largepgcnt = page_get_pagecnt( - page_num_pagesizes() - 1); - if (base_pfn & (largepgcnt - 1)) { - num--; - base_pfn++; - cur_memseg->pages++; - cur_memseg->pages_base++; - pp = cur_memseg->pages; - } - if (dobreak) - break; - } - - if (cur_memseg->pages_base >= - (*memsegpp)->pages_end) { - cur_memseg->next = *memsegpp; - *memsegpp = cur_memseg; - break; - } - if ((*memsegpp)->next == NULL) { - cur_memseg->next = NULL; - (*memsegpp)->next = cur_memseg; - break; - } - memsegpp = &((*memsegpp)->next); - ASSERT(*memsegpp != NULL); + if (memsegs != NULL) { + ASSERT(cur_memseg->pages_base >= memsegs->pages_end); + cur_memseg->next = memsegs; } + memsegs = cur_memseg; /* * add_physmem() initializes the PSM part of the page @@ -2356,12 +2125,7 @@ kphysm_init( availrmem_initial += num; availrmem += num; - /* - * If the caller provided the page frames to us, then - * advance in that list. Otherwise, prepare to allocate - * our own page frames for the next memseg. - */ - pp = (inpp == NULL) ? NULL : pp + num; + pp += num; } PRM_DEBUG(availrmem_initial); @@ -2377,11 +2141,6 @@ kphysm_init( static void kvm_init(void) { -#ifdef DEBUG - extern void _start(); - - ASSERT((caddr_t)_start == s_text); -#endif ASSERT((((uintptr_t)s_text) & MMU_PAGEOFFSET) == 0); /* @@ -2400,20 +2159,20 @@ kvm_init(void) * We're about to map out /boot. This is the beginning of the * system resource management transition. We can no longer * call into /boot for I/O or memory allocations. - * - * XX64 - Is this still correct with kernelheap_extend() being called - * later than this???? */ (void) seg_attach(&kas, final_kernelheap, ekernelheap - final_kernelheap, &kvseg); (void) segkmem_create(&kvseg); -#if defined(__amd64) - (void) seg_attach(&kas, (caddr_t)core_base, core_size, &kvseg_core); - (void) segkmem_create(&kvseg_core); + if (core_size > 0) { + PRM_POINT("attaching kvseg_core"); + (void) seg_attach(&kas, (caddr_t)core_base, core_size, + &kvseg_core); + (void) segkmem_create(&kvseg_core); + } - /* segzio optimization is only valid for 64-bit kernels */ - if (!segzio_fromheap) { + if (segziosize > 0) { + PRM_POINT("attaching segzio"); (void) seg_attach(&kas, segzio_base, mmu_ptob(segziosize), &kzioseg); (void) segkmem_zio_create(&kzioseg); @@ -2421,10 +2180,8 @@ kvm_init(void) /* create zio area covering new segment */ segkmem_zio_init(segzio_base, mmu_ptob(segziosize)); } -#endif - (void) seg_attach(&kas, (caddr_t)SEGDEBUGBASE, (size_t)SEGDEBUGSIZE, - &kdebugseg); + (void) seg_attach(&kas, kdi_segdebugbase, kdi_segdebugsize, &kdebugseg); (void) segkmem_create(&kdebugseg); rw_exit(&kas.a_lock); @@ -2432,6 +2189,7 @@ kvm_init(void) /* * Ensure that the red zone at kernelbase is never accessible. */ + PRM_POINT("protecting redzone"); (void) as_setprot(&kas, (caddr_t)kernelbase, KERNEL_REDZONE_SIZE, 0); /* @@ -2526,8 +2284,8 @@ mtrr_sync(void) crvalue &= ~CR0_NW; setcr0(crvalue); invalidate_cache(); - setcr3(getcr3()); + reload_cr3(); if (x86_feature & X86_PAT) wrmsr(REG_MTRRPAT, pat_attr_reg); @@ -2555,7 +2313,8 @@ mtrr_sync(void) wrmsr(ecx + 1, mtrrphys->mtrrphys_mask); } wrmsr(REG_MTRRDEF, mtrrdef); - setcr3(getcr3()); + + reload_cr3(); invalidate_cache(); setcr0(cr0_orig); } @@ -2633,7 +2392,7 @@ get_system_configuration(void) * new = pointer to a new struct memlist * memlistp = memory list to which to add segment. */ -static void +void memlist_add( uint64_t start, uint64_t len, @@ -2782,7 +2541,7 @@ device_arena_free(void *vaddr, size_t size) vmem_free(device_arena, vaddr, size); } -#else +#else /* __i386 */ void * device_arena_alloc(size_t size, int vm_flag) @@ -2798,7 +2557,7 @@ device_arena_alloc(size_t size, int vm_flag) v = (uintptr_t)vaddr; ASSERT(v >= kernelbase); - ASSERT(v + size <= ptable_va); + ASSERT(v + size <= valloc_base); start = btop(v - kernelbase); end = btop(v + size - 1 - kernelbase); @@ -2820,7 +2579,7 @@ device_arena_free(void *vaddr, size_t size) size_t end; ASSERT(v >= kernelbase); - ASSERT(v + size <= ptable_va); + ASSERT(v + size <= valloc_base); start = btop(v - kernelbase); end = btop(v + size - 1 - kernelbase); @@ -2856,7 +2615,7 @@ device_arena_contains(void *vaddr, size_t size, size_t *len) /* * First check if we're completely outside the bitmap range. */ - if (v >= ptable_va || eaddr < kernelbase) + if (v >= valloc_base || eaddr < kernelbase) return (NULL); /* @@ -2878,4 +2637,4 @@ device_arena_contains(void *vaddr, size_t size, size_t *len) return ((void *)v); } -#endif +#endif /* __i386 */ diff --git a/usr/src/uts/i86pc/os/timestamp.c b/usr/src/uts/i86pc/os/timestamp.c index b0d422b867..ad7db8a28e 100644 --- a/usr/src/uts/i86pc/os/timestamp.c +++ b/usr/src/uts/i86pc/os/timestamp.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -135,19 +134,20 @@ static volatile int tsc_sync_go; /* * XX64 Is the faster way to do this with a 64-bit ABI? */ -#define TSC_CONVERT_AND_ADD(tsc, hrt, scale) { \ - unsigned int *_l = (unsigned int *)&(tsc); \ - (hrt) += mul32(_l[1], scale) << NSEC_SHIFT; \ + +#define TSC_CONVERT_AND_ADD(tsc, hrt, scale) { \ + unsigned int *_l = (unsigned int *)&(tsc); \ + (hrt) += mul32(_l[1], scale) << NSEC_SHIFT; \ (hrt) += mul32(_l[0], scale) >> (32 - NSEC_SHIFT); \ } -#define TSC_CONVERT(tsc, hrt, scale) { \ - unsigned int *_l = (unsigned int *)&(tsc); \ - (hrt) = mul32(_l[1], scale) << NSEC_SHIFT; \ +#define TSC_CONVERT(tsc, hrt, scale) { \ + unsigned int *_l = (unsigned int *)&(tsc); \ + (hrt) = mul32(_l[1], scale) << NSEC_SHIFT; \ (hrt) += mul32(_l[0], scale) >> (32 - NSEC_SHIFT); \ } - +int tsc_master_slave_sync_needed = 1; static int tsc_max_delta; static hrtime_t tsc_sync_snaps[2]; @@ -211,9 +211,12 @@ tsc_digest(processorid_t target) void tsc_sync_master(processorid_t slave) { - int flags; + ulong_t flags; hrtime_t hrt; + if (!tsc_master_slave_sync_needed) + return; + ASSERT(tsc_sync_go != TSC_SYNC_GO); flags = clear_int_flag(); @@ -264,9 +267,12 @@ tsc_sync_master(processorid_t slave) void tsc_sync_slave(void) { - int flags; + ulong_t flags; hrtime_t hrt; + if (!tsc_master_slave_sync_needed) + return; + ASSERT(tsc_sync_go != TSC_SYNC_GO); flags = clear_int_flag(); @@ -311,7 +317,7 @@ void tsc_hrtimeinit(uint64_t cpu_freq_hz) { longlong_t tsc; - int flags; + ulong_t flags; /* * cpu_freq_hz is the measured cpu frequency in hertz @@ -333,8 +339,8 @@ tsc_hrtimeinit(uint64_t cpu_freq_hz) } /* - * Called once per second on some CPU from the cyclic subsystem's - * CY_HIGH_LEVEL interrupt. (no longer CPU0-only) + * Called once per second on a CPU from the cyclic subsystem's + * CY_HIGH_LEVEL interrupt. (No longer just cpu0-only) */ void tsc_tick(void) @@ -418,7 +424,6 @@ tsc_gethrtime(void) */ tsc = 0; } - hrt = tsc_hrtime_base; TSC_CONVERT_AND_ADD(tsc, hrt, nsec_scale); @@ -581,13 +586,8 @@ tsc_gethrtimeunscaled(void) do { old_hres_lock = hres_lock; - if ((tsc = tsc_read()) < tsc_last) { - /* - * see comments in tsc_gethrtime - */ - tsc += tsc_last_jumped; - } - + /* See tsc_tick(). */ + tsc = tsc_read() + tsc_last_jumped; } while ((old_hres_lock & ~1) != hres_lock); return (tsc); diff --git a/usr/src/uts/i86pc/os/trap.c b/usr/src/uts/i86pc/os/trap.c index 8bae150533..bce1c7ad24 100644 --- a/usr/src/uts/i86pc/os/trap.c +++ b/usr/src/uts/i86pc/os/trap.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -50,7 +50,6 @@ #include <sys/sysinfo.h> #include <sys/fault.h> #include <sys/stack.h> -#include <sys/mmu.h> #include <sys/psw.h> #include <sys/regset.h> #include <sys/fp.h> @@ -72,6 +71,7 @@ #include <vm/as.h> #include <vm/seg.h> #include <vm/hat_pte.h> +#include <vm/hat_i86.h> #include <sys/procfs.h> @@ -92,6 +92,10 @@ #include <sys/traptrace.h> #include <sys/ontrap.h> #include <sys/cpc_impl.h> +#include <sys/bootconf.h> +#include <sys/bootinfo.h> +#include <sys/promif.h> +#include <sys/mach_mmu.h> #define USER 0x10000 /* user-mode flag added to trap type */ @@ -276,11 +280,11 @@ instr_is_syscall(caddr_t pc) #ifdef __amd64 /* - * In the first revisions of AMD64 CPUs produced by AMD, the LAHF and - * SAHF instructions were not implemented in 64bit mode. Later revisions + * In the first revisions of amd64 CPUs produced by AMD, the LAHF and + * SAHF instructions were not implemented in 64-bit mode. Later revisions * did implement these instructions. An extension to the cpuid instruction * was added to check for the capability of executing these instructions - * in 64bit mode. + * in 64-bit mode. * * Intel originally did not implement these instructions in EM64T either, * but added them in later revisions. @@ -367,15 +371,18 @@ instr_is_prefetch(caddr_t pc) * * Note: All user-level traps that might call stop() must exit * trap() by 'goto out' or by falling through. + * Note Also: trap() is usually called with interrupts enabled, (PS_IE == 1) + * however, there are paths that arrive here with PS_IE == 0 so special care + * must be taken in those cases. */ void trap(struct regs *rp, caddr_t addr, processorid_t cpuid) { - kthread_t *cur_thread = curthread; + kthread_t *ct = curthread; enum seg_rw rw; unsigned type; - proc_t *p = ttoproc(cur_thread); - klwp_t *lwp = ttolwp(cur_thread); + proc_t *p = ttoproc(ct); + klwp_t *lwp = ttolwp(ct); uintptr_t lofault; faultcode_t pagefault(), res, errcode; enum fault_type fault_type; @@ -397,8 +404,7 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) type = rp->r_trapno; CPU_STATS_ADDQ(CPU, sys, trap, 1); - - ASSERT(cur_thread->t_schedflag & TS_DONT_SWAP); + ASSERT(ct->t_schedflag & TS_DONT_SWAP); if (type == T_PGFLT) { @@ -435,7 +441,8 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) } #endif /* __i386 */ - } + } else if (type == T_SGLSTP && lwp != NULL) + lwp->lwp_pcb.pcb_drstat = (uintptr_t)addr; if (tdebug) showregs(type, rp, addr); @@ -448,14 +455,14 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) * the entire trap. If trapping from the kernel, this * should already be set up. */ - if (cur_thread->t_cred != p->p_cred) { - cred_t *oldcred = cur_thread->t_cred; + if (ct->t_cred != p->p_cred) { + cred_t *oldcred = ct->t_cred; /* * DTrace accesses t_cred in probe context. t_cred * must always be either NULL, or point to a valid, * allocated cred structure. */ - cur_thread->t_cred = crgetcred(); + ct->t_cred = crgetcred(); crfree(oldcred); } ASSERT(lwp != NULL); @@ -477,7 +484,7 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) /* Kernel probe */ TNF_PROBE_1(thread_state, "thread", /* CSTYLED */, tnf_microstate, state, mstate); - mstate = new_mstate(cur_thread, mstate); + mstate = new_mstate(ct, mstate); bzero(&siginfo, sizeof (siginfo)); } @@ -518,9 +525,9 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) * If we're under on_trap() protection (see <sys/ontrap.h>), * set ot_trap and longjmp back to the on_trap() call site. */ - if ((cur_thread->t_ontrap != NULL) && - (cur_thread->t_ontrap->ot_prot & OT_DATA_ACCESS)) { - curthread->t_ontrap->ot_trap |= OT_DATA_ACCESS; + if ((ct->t_ontrap != NULL) && + (ct->t_ontrap->ot_prot & OT_DATA_ACCESS)) { + ct->t_ontrap->ot_trap |= OT_DATA_ACCESS; longjmp(&curthread->t_ontrap->ot_jmpbuf); } @@ -533,10 +540,10 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) * starting and because we know that we always have * KERNELBASE mapped as invalid to serve as a "barrier". */ - lofault = cur_thread->t_lofault; - cur_thread->t_lofault = 0; + lofault = ct->t_lofault; + ct->t_lofault = 0; - mstate = new_mstate(cur_thread, LMS_KFAULT); + mstate = new_mstate(ct, LMS_KFAULT); if (addr < (caddr_t)kernelbase) { res = pagefault(addr, @@ -549,13 +556,13 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) res = pagefault(addr, (errcode & PF_ERR_PROT)? F_PROT: F_INVAL, rw, 1); } - (void) new_mstate(cur_thread, mstate); + (void) new_mstate(ct, mstate); /* * Restore lofault. If we resolved the fault, exit. * If we didn't and lofault wasn't set, die. */ - cur_thread->t_lofault = lofault; + ct->t_lofault = lofault; if (res == 0) goto cleanup; @@ -630,7 +637,7 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) else res = EFAULT; rp->r_r0 = res; - rp->r_pc = cur_thread->t_lofault; + rp->r_pc = ct->t_lofault; goto cleanup; case T_PGFLT + USER: /* user page fault */ @@ -1008,7 +1015,7 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) if (singlestep_twiddle) { rp->r_ps &= ~PS_T; /* turn off trace */ lwp->lwp_pcb.pcb_flags |= DEBUG_PENDING; - cur_thread->t_post_sys = 1; + ct->t_post_sys = 1; aston(curthread); goto cleanup; } @@ -1032,16 +1039,20 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) #if defined(__amd64) /* * On amd64, we can get a #gp from referencing addresses - * in the virtual address hole e.g. from a copyin. + * in the virtual address hole e.g. from a copyin + * or in update_sregs while updating user semgent registers. */ /* * If we're under on_trap() protection (see <sys/ontrap.h>), * set ot_trap and longjmp back to the on_trap() call site. */ - if ((cur_thread->t_ontrap != NULL) && - (cur_thread->t_ontrap->ot_prot & OT_DATA_ACCESS)) { - curthread->t_ontrap->ot_trap |= OT_DATA_ACCESS; + if (ct->t_ontrap != NULL) { + if (ct->t_ontrap->ot_prot & OT_DATA_ACCESS) + ct->t_ontrap->ot_trap |= OT_DATA_ACCESS; + + if (ct->t_ontrap->ot_prot & OT_SEGMENT_ACCESS) + ct->t_ontrap->ot_trap |= OT_SEGMENT_ACCESS; longjmp(&curthread->t_ontrap->ot_jmpbuf); } @@ -1049,7 +1060,7 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) * If we're under lofault protection (copyin etc.), * longjmp back to lofault with an EFAULT. */ - if (cur_thread->t_lofault) { + if (ct->t_lofault) { /* * Fault is not resolvable, so just return to lofault */ @@ -1058,14 +1069,28 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) traceregs(rp); } rp->r_r0 = EFAULT; - rp->r_pc = cur_thread->t_lofault; + rp->r_pc = ct->t_lofault; goto cleanup; } /*FALLTHROUGH*/ #endif + case T_SEGFLT: /* segment not present fault */ +#if defined(__amd64) + /* + * One example of this is #NP in update_sregs while + * attempting to update a user segment register + * that points to a descriptor that is marked not + * present. + */ + if (ct->t_ontrap != NULL && + ct->t_ontrap->ot_prot & OT_SEGMENT_ACCESS) { + ct->t_ontrap->ot_trap |= OT_SEGMENT_ACCESS; + longjmp(&curthread->t_ontrap->ot_jmpbuf); + } +#endif /* __amd64 */ + /*FALLTHROUGH*/ case T_STKFLT: /* stack fault */ case T_TSSFLT: /* invalid TSS fault */ - case T_SEGFLT: /* segment not present fault */ if (tudebug) showregs(type, rp, (caddr_t)0); if (kern_gpfault(rp)) @@ -1073,16 +1098,17 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) goto cleanup; /*FALLTHROUGH*/ -/* - * ONLY 32-bit PROCESSES can USE a PRIVATE LDT! 64-bit apps should have - * no legacy need for them, so we put a stop to it here. - * - * So: not-present fault is ONLY valid for 32-bit processes with a private LDT - * trying to do a system call. Emulate it. - * - * #gp fault is ONLY valid for 32-bit processes also, which DO NOT have private - * LDT, and are trying to do a system call. Emulate it. - */ + /* + * ONLY 32-bit PROCESSES can USE a PRIVATE LDT! 64-bit apps + * should have no need for them, so we put a stop to it here. + * + * So: not-present fault is ONLY valid for 32-bit processes with + * a private LDT trying to do a system call. Emulate it. + * + * #gp fault is ONLY valid for 32-bit processes also, which DO NOT + * have a private LDT, and are trying to do a system call. Emulate it. + */ + case T_SEGFLT + USER: /* segment not present fault */ case T_GPFLT + USER: /* general protection violation */ #ifdef _SYSCALL32_IMPL @@ -1278,14 +1304,14 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) if (lwp->lwp_oweupc) profil_tick(rp->r_pc); - if (cur_thread->t_astflag | cur_thread->t_sig_check) { + if (ct->t_astflag | ct->t_sig_check) { /* * Turn off the AST flag before checking all the conditions that * may have caused an AST. This flag is on whenever a signal or * unusual condition should be handled after the next trap or * syscall. */ - astoff(cur_thread); + astoff(ct); /* * If a single-step trap occurred on a syscall (see above) * recognize it now. Do this before checking for signals @@ -1295,7 +1321,7 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) if (lwp->lwp_pcb.pcb_flags & DEBUG_PENDING) deferred_singlestep_trap((caddr_t)rp->r_pc); - cur_thread->t_sig_check = 0; + ct->t_sig_check = 0; mutex_enter(&p->p_lock); if (curthread->t_proc_flag & TP_CHANGEBIND) { @@ -1329,15 +1355,15 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid) * All code that sets signals and makes ISSIG evaluate true must * set t_astflag afterwards. */ - if (ISSIG_PENDING(cur_thread, lwp, p)) { + if (ISSIG_PENDING(ct, lwp, p)) { if (issig(FORREAL)) psig(); - cur_thread->t_sig_check = 1; + ct->t_sig_check = 1; } - if (cur_thread->t_rprof != NULL) { + if (ct->t_rprof != NULL) { realsigprof(0, 0); - cur_thread->t_sig_check = 1; + ct->t_sig_check = 1; } /* @@ -1374,15 +1400,15 @@ out: /* We can't get here from a system trap */ */ lwp->lwp_state = LWP_USER; - if (cur_thread->t_trapret) { - cur_thread->t_trapret = 0; - thread_lock(cur_thread); - CL_TRAPRET(cur_thread); - thread_unlock(cur_thread); + if (ct->t_trapret) { + ct->t_trapret = 0; + thread_lock(ct); + CL_TRAPRET(ct); + thread_unlock(ct); } if (CPU->cpu_runrun) preempt(); - (void) new_mstate(cur_thread, mstate); + (void) new_mstate(ct, mstate); /* Kernel probe */ TNF_PROBE_1(thread_state, "thread", /* CSTYLED */, @@ -1419,7 +1445,7 @@ struct kpreempt_cnts { /* kernel preemption statistics */ void kpreempt(int asyncspl) { - kthread_t *cur_thread = curthread; + kthread_t *ct = curthread; if (IGNORE_KERNEL_PREEMPTION) { aston(CPU->cpu_dispthread); @@ -1430,24 +1456,24 @@ kpreempt(int asyncspl) * Check that conditions are right for kernel preemption */ do { - if (cur_thread->t_preempt) { + if (ct->t_preempt) { /* * either a privileged thread (idle, panic, interrupt) * or will check when t_preempt is lowered */ - if (cur_thread->t_pri < 0) + if (ct->t_pri < 0) kpreempt_cnts.kpc_idle++; - else if (cur_thread->t_flag & T_INTR_THREAD) { + else if (ct->t_flag & T_INTR_THREAD) { kpreempt_cnts.kpc_intr++; - if (cur_thread->t_pil == CLOCK_LEVEL) + if (ct->t_pil == CLOCK_LEVEL) kpreempt_cnts.kpc_clock++; } else kpreempt_cnts.kpc_blocked++; aston(CPU->cpu_dispthread); return; } - if (cur_thread->t_state != TS_ONPROC || - cur_thread->t_disp_queue != CPU->cpu_disp) { + if (ct->t_state != TS_ONPROC || + ct->t_disp_queue != CPU->cpu_disp) { /* this thread will be calling swtch() shortly */ kpreempt_cnts.kpc_notonproc++; if (CPU->cpu_thread != CPU->cpu_dispthread) { @@ -1467,15 +1493,21 @@ kpreempt(int asyncspl) kpreempt_cnts.kpc_prilevel++; return; } - + if (!interrupts_enabled()) { + /* + * Can't preempt while running with ints disabled + */ + kpreempt_cnts.kpc_prilevel++; + return; + } if (asyncspl != KPREEMPT_SYNC) kpreempt_cnts.kpc_apreempt++; else kpreempt_cnts.kpc_spreempt++; - cur_thread->t_preempt++; + ct->t_preempt++; preempt(); - cur_thread->t_preempt--; + ct->t_preempt--; } while (CPU->cpu_kprunrun); } @@ -1489,8 +1521,8 @@ showregs(uint_t type, struct regs *rp, caddr_t addr) s = spl7(); type &= ~USER; - if (u.u_comm[0]) - printf("%s: ", u.u_comm); + if (PTOU(curproc)->u_comm[0]) + printf("%s: ", PTOU(curproc)->u_comm); if (type < TRAP_TYPES) printf("#%s %s\n", trap_type_mnemonic[type], trap_type[type]); else @@ -1526,7 +1558,7 @@ showregs(uint_t type, struct regs *rp, caddr_t addr) #else printf("cr0: %b cr4: %b\n", (uint_t)getcr0(), FMT_CR0, (uint_t)getcr4(), FMT_CR4); -#endif +#endif /* __lint */ #if defined(__amd64) printf("cr2: %lx cr3: %lx cr8: %lx\n", getcr2(), getcr3(), getcr8()); @@ -1550,7 +1582,8 @@ dumpregs(struct regs *rp) printf(fmt, "r10", rp->r_r10, "r11", rp->r_r11, "r12", rp->r_r12); printf(fmt, "r13", rp->r_r13, "r14", rp->r_r14, "r15", rp->r_r15); - printf(fmt, "fsb", rp->r_fsbase, "gsb", rp->r_gsbase, " ds", rp->r_ds); + printf(fmt, "fsb", rdmsr(MSR_AMD_FSBASE), "gsb", rdmsr(MSR_AMD_GSBASE), + " ds", rp->r_ds); printf(fmt, " es", rp->r_es, " fs", rp->r_fs, " gs", rp->r_gs); printf(fmt, "trp", rp->r_trapno, "err", rp->r_err, "rip", rp->r_rip); @@ -1610,7 +1643,6 @@ kern_gpfault(struct regs *rp) extern void _sys_rtt(), sr_sup(); #if defined(__amd64) - extern void _update_sregs(), _update_sregs_done(); static const uint8_t iretq_insn[2] = { 0x48, 0xcf }; #elif defined(__i386) @@ -1678,23 +1710,6 @@ kern_gpfault(struct regs *rp) ASSERT(trp->r_pc == lwptoregs(lwp)->r_pc); ASSERT(trp->r_err == rp->r_err); - } else if ((lwp->lwp_pcb.pcb_flags & RUPDATE_PENDING) != 0 && - pc >= (caddr_t)_update_sregs && - pc < (caddr_t)_update_sregs_done) { - /* - * This is the common case -- we're trying to load - * a bad segment register value in the only section - * of kernel code that ever loads segment registers. - * - * We don't need to do anything at this point because - * the pcb contains all the pending segment register - * state, and the regs are still intact because we - * didn't adjust the stack pointer yet. Given the fidelity - * of all this, we could conceivably send a signal - * to the lwp, rather than core-ing. - */ - trp = lwptoregs(lwp); - ASSERT((caddr_t)trp == (caddr_t)rp->r_sp); } #elif defined(__i386) @@ -1870,7 +1885,7 @@ dump_ttrace(void) const char fmt1[] = "%3d %016lx %12llx "; #elif defined(__i386) const char banner[] = - "\ncpu address timestamp type vc handler pc\n"; + "\ncpu address timestamp type vc handler pc\n"; const char fmt1[] = "%3d %08lx %12llx "; #endif const char fmt2[] = "%4s %3x "; @@ -1943,11 +1958,11 @@ dump_ttrace(void) (uintptr_t)sys->sy_callc, &off); if (sym != NULL) - printf("%s ", sym); + printf(fmt3, sym); else printf("%p ", sys->sy_callc); } else { - printf("unknown "); + printf(fmt3, "unknown"); } break; @@ -1958,19 +1973,36 @@ dump_ttrace(void) sym = kobj_getsymname( (uintptr_t)vec->av_vector, &off); if (sym != NULL) - printf("%s ", sym); + printf(fmt3, sym); else printf("%p ", vec->av_vector); } else { - printf("unknown "); + printf(fmt3, "unknown "); } break; case TT_TRAP: + case TT_EVENT: type = rec->ttr_regs.r_trapno; printf(fmt2, "trap", type); - printf("#%s ", type < TRAP_TYPES ? - trap_type_mnemonic[type] : "trap"); + if (type < TRAP_TYPES) + printf(" #%s ", + trap_type_mnemonic[type]); + else + switch (type) { + case T_AST: + printf(fmt3, "ast"); + break; + default: + printf(fmt3, ""); + break; + } + break; + + case TT_XCALL: + printf(fmt2, "xcal", + rec->ttr_info.xc_entry.xce_marker); + printf(fmt3, ""); break; default: @@ -2026,6 +2058,36 @@ dump_ttrace(void) } } +/* + * Help with constructing traptrace records in C + */ +trap_trace_rec_t * +trap_trace_get_traceptr(uint8_t marker, ulong_t pc, ulong_t sp) +{ + trap_trace_rec_t *ttr; + + if (trap_trace_freeze) + ttr = &trap_trace_postmort; + else { + trap_trace_ctl_t *ttc = &trap_trace_ctl[CPU->cpu_id]; + + ttr = (void *)ttc->ttc_next; + + if (ttc->ttc_next >= ttc->ttc_limit) + ttc->ttc_next = ttc->ttc_first; + else + ttc->ttc_next += sizeof (trap_trace_rec_t); + } + + ttr->ttr_regs.r_sp = sp; + ttr->ttr_regs.r_pc = pc; + ttr->ttr_cr2 = getcr2(); + ttr->ttr_curthread = (uintptr_t)curthread; + ttr->ttr_stamp = tsc_read(); + ttr->ttr_marker = marker; + return (ttr); +} + #endif /* TRAPTRACE */ void diff --git a/usr/src/uts/i86pc/os/x_call.c b/usr/src/uts/i86pc/os/x_call.c index f29cf1a94c..2520cb95dc 100644 --- a/usr/src/uts/i86pc/os/x_call.c +++ b/usr/src/uts/i86pc/os/x_call.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,7 +31,6 @@ */ #include <sys/types.h> - #include <sys/param.h> #include <sys/t_lock.h> #include <sys/thread.h> @@ -40,11 +39,13 @@ #include <sys/cpu.h> #include <sys/psw.h> #include <sys/sunddi.h> -#include <sys/mmu.h> #include <sys/debug.h> #include <sys/systm.h> +#include <sys/archsystm.h> #include <sys/machsystm.h> #include <sys/mutex_impl.h> +#include <sys/traptrace.h> + static struct xc_mbox xc_mboxes[X_CALL_LEVELS]; static kmutex_t xc_mbox_lock[X_CALL_LEVELS]; @@ -58,7 +59,6 @@ static void xc_common(xc_func_t, xc_arg_t, xc_arg_t, xc_arg_t, int, cpuset_t, int); static int xc_initialized = 0; -extern cpuset_t cpu_ready_set; void xc_init() @@ -78,15 +78,41 @@ xc_init() xc_initialized = 1; } +#if defined(TRAPTRACE) + /* - * Used by the debugger to determine whether or not cross calls have been - * initialized and are safe to use. + * When xc_traptrace is on, put x-call records into the trap trace buffer. */ -int -kdi_xc_initialized(void) +int xc_traptrace; + +void +xc_make_trap_trace_entry(uint8_t marker, int pri, ulong_t arg) { - return (xc_initialized); + trap_trace_rec_t *ttr; + struct _xc_entry *xce; + + if (xc_traptrace == 0) + return; + + ttr = trap_trace_get_traceptr(TT_XCALL, + (ulong_t)caller(), (ulong_t)getfp()); + xce = &(ttr->ttr_info.xc_entry); + + xce->xce_marker = marker; + xce->xce_pri = pri; + xce->xce_arg = arg; + + if ((uint_t)pri < X_CALL_LEVELS) { + struct machcpu *mcpu = &CPU->cpu_m; + + xce->xce_pend = mcpu->xc_pend[pri]; + xce->xce_ack = mcpu->xc_ack[pri]; + xce->xce_state = mcpu->xc_state[pri]; + xce->xce_retval = mcpu->xc_retval[pri]; + xce->xce_func = (uintptr_t)xc_mboxes[pri].func; + } } +#endif #define CAPTURE_CPU_ARG ~0UL @@ -101,58 +127,53 @@ kdi_xc_initialized(void) uint_t xc_serv(caddr_t arg1, caddr_t arg2) { - int op; - int pri = (int)(uintptr_t)arg1; + int op; + int pri = (int)(uintptr_t)arg1; struct cpu *cpup = CPU; - xc_arg_t *argp; xc_arg_t arg2val; - uint_t tlbflush; + + XC_TRACE(TT_XC_SVC_BEGIN, pri, (ulong_t)arg2); if (pri == X_CALL_MEDPRI) { - argp = &xc_mboxes[X_CALL_MEDPRI].arg2; - arg2val = *argp; + arg2val = xc_mboxes[X_CALL_MEDPRI].arg2; + if (arg2val != CAPTURE_CPU_ARG && !CPU_IN_SET((cpuset_t)arg2val, cpup->cpu_id)) - return (DDI_INTR_UNCLAIMED); + goto unclaimed; + ASSERT(arg2val == CAPTURE_CPU_ARG); + if (cpup->cpu_m.xc_pend[pri] == 0) - return (DDI_INTR_UNCLAIMED); + goto unclaimed; cpup->cpu_m.xc_pend[X_CALL_MEDPRI] = 0; cpup->cpu_m.xc_ack[X_CALL_MEDPRI] = 1; for (;;) { if ((cpup->cpu_m.xc_state[X_CALL_MEDPRI] == XC_DONE) || - (cpup->cpu_m.xc_pend[X_CALL_MEDPRI])) + (cpup->cpu_m.xc_pend[X_CALL_MEDPRI])) break; - ht_pause(); + SMT_PAUSE(); } + XC_TRACE(TT_XC_SVC_END, pri, DDI_INTR_CLAIMED); return (DDI_INTR_CLAIMED); } + if (cpup->cpu_m.xc_pend[pri] == 0) - return (DDI_INTR_UNCLAIMED); + goto unclaimed; cpup->cpu_m.xc_pend[pri] = 0; op = cpup->cpu_m.xc_state[pri]; /* - * When invalidating TLB entries, wait until the initiator changes the - * memory PTE before doing any INVLPG. Otherwise, if the PTE in memory - * hasn't been changed, the processor's TLB Flush filter may ignore - * the INVLPG instruction. - */ - tlbflush = (cpup->cpu_m.xc_wait[pri] == 2); - - /* * Don't invoke a null function. */ - if (xc_mboxes[pri].func != NULL) { - if (!tlbflush) - cpup->cpu_m.xc_retval[pri] = (*xc_mboxes[pri].func) - (xc_mboxes[pri].arg1, xc_mboxes[pri].arg2, - xc_mboxes[pri].arg3); - } else + if (xc_mboxes[pri].func != NULL) + cpup->cpu_m.xc_retval[pri] = (*xc_mboxes[pri].func) + (xc_mboxes[pri].arg1, xc_mboxes[pri].arg2, + xc_mboxes[pri].arg3); + else cpup->cpu_m.xc_retval[pri] = 0; /* @@ -160,36 +181,31 @@ xc_serv(caddr_t arg1, caddr_t arg2) */ cpup->cpu_m.xc_ack[pri] = 1; - if (op == XC_CALL_OP) - return (DDI_INTR_CLAIMED); - - /* - * for (op == XC_SYNC_OP) - * Wait for the initiator of the x-call to indicate - * that all CPUs involved can proceed. - */ - while (cpup->cpu_m.xc_wait[pri]) - ht_pause(); - - while (cpup->cpu_m.xc_state[pri] != XC_DONE) - ht_pause(); - - /* - * Flush the TLB, if that's what is requested. - */ - if (xc_mboxes[pri].func != NULL && tlbflush) { - cpup->cpu_m.xc_retval[pri] = (*xc_mboxes[pri].func) - (xc_mboxes[pri].arg1, xc_mboxes[pri].arg2, - xc_mboxes[pri].arg3); + if (op != XC_CALL_OP) { + /* + * for (op == XC_SYNC_OP) + * Wait for the initiator of the x-call to indicate + * that all CPUs involved can proceed. + */ + while (cpup->cpu_m.xc_wait[pri]) + SMT_PAUSE(); + + while (cpup->cpu_m.xc_state[pri] != XC_DONE) + SMT_PAUSE(); + + /* + * Acknowledge that we have received the directive to continue. + */ + ASSERT(cpup->cpu_m.xc_ack[pri] == 0); + cpup->cpu_m.xc_ack[pri] = 1; } - /* - * Acknowledge that we have received the directive to continue. - */ - ASSERT(cpup->cpu_m.xc_ack[pri] == 0); - cpup->cpu_m.xc_ack[pri] = 1; - + XC_TRACE(TT_XC_SVC_END, pri, DDI_INTR_CLAIMED); return (DDI_INTR_CLAIMED); + +unclaimed: + XC_TRACE(TT_XC_SVC_END, pri, DDI_INTR_UNCLAIMED); + return (DDI_INTR_UNCLAIMED); } @@ -261,23 +277,6 @@ xc_sync( xc_do_call(arg1, arg2, arg3, pri, set, func, 1); } -/* - * xc_sync_wait: similar to xc_sync(), except that the starting - * cpu waits for all other cpus to check in before running its - * service locally. - */ -void -xc_wait_sync( - xc_arg_t arg1, - xc_arg_t arg2, - xc_arg_t arg3, - int pri, - cpuset_t set, - xc_func_t func) -{ - xc_do_call(arg1, arg2, arg3, pri, set, func, 2); -} - /* * The routines xc_capture_cpus and xc_release_cpus @@ -329,7 +328,7 @@ xc_capture_cpus(cpuset_t set) CPUSET_AND(c, cpu_ready_set); if (CPUSET_ISNULL(c)) break; - ht_pause(); + SMT_PAUSE(); } /* @@ -358,6 +357,7 @@ xc_capture_cpus(cpuset_t set) cpup->cpu_m.xc_ack[X_CALL_MEDPRI] = 0; cpup->cpu_m.xc_state[X_CALL_MEDPRI] = XC_HOLD; cpup->cpu_m.xc_pend[X_CALL_MEDPRI] = 1; + XC_TRACE(TT_XC_CAPTURE, X_CALL_MEDPRI, cix); send_dirint(cix, XC_MED_PIL); } i++; @@ -366,14 +366,14 @@ xc_capture_cpus(cpuset_t set) } /* - * Wait here until all remote calls to complete. + * Wait here until all remote calls to acknowledge. */ i = 0; for (cix = 0; cix < NCPU; cix++) { if (lcx != cix && CPU_IN_SET(set, cix)) { cpup = cpu[cix]; while (cpup->cpu_m.xc_ack[X_CALL_MEDPRI] == 0) - ht_pause(); + SMT_PAUSE(); cpup->cpu_m.xc_ack[X_CALL_MEDPRI] = 0; } i++; @@ -411,6 +411,7 @@ xc_release_cpus(void) * Clear xc_ack since we will be waiting for it * to be set again after we set XC_DONE. */ + XC_TRACE(TT_XC_RELEASE, X_CALL_MEDPRI, cix); cpup->cpu_m.xc_state[X_CALL_MEDPRI] = XC_DONE; } i++; @@ -428,7 +429,6 @@ xc_release_cpus(void) * -1 - no waiting, don't release remotes * 0 - no waiting, release remotes immediately * 1 - run service locally w/o waiting for remotes. - * 2 - wait for remotes before running locally */ static void xc_common( @@ -480,37 +480,35 @@ xc_common( else cpup->cpu_m.xc_state[pri] = XC_CALL_OP; cpup->cpu_m.xc_pend[pri] = 1; + XC_TRACE(TT_XC_START, pri, cix); send_dirint(cix, xc_xlat_xcptoipl[pri]); } } /* - * Run service locally if not waiting for remotes. + * Run service locally. */ - if (sync != 2 && CPU_IN_SET(set, lcx) && func != NULL) + if (CPU_IN_SET(set, lcx) && func != NULL) { + XC_TRACE(TT_XC_START, pri, CPU->cpu_id); CPU->cpu_m.xc_retval[pri] = (*func)(arg1, arg2, arg3); + } if (sync == -1) return; /* - * Wait here until all remote calls complete. + * Wait here until all remote calls acknowledge. */ for (cix = 0; cix < NCPU; cix++) { if (lcx != cix && CPU_IN_SET(set, cix)) { cpup = cpu[cix]; while (cpup->cpu_m.xc_ack[pri] == 0) - ht_pause(); + SMT_PAUSE(); + XC_TRACE(TT_XC_WAIT, pri, cix); cpup->cpu_m.xc_ack[pri] = 0; } } - /* - * Run service locally if waiting for remotes. - */ - if (sync == 2 && CPU_IN_SET(set, lcx) && func != NULL) - CPU->cpu_m.xc_retval[pri] = (*func)(arg1, arg2, arg3); - if (sync == 0) return; @@ -540,7 +538,8 @@ xc_common( cpup = cpu[cix]; if (cpup != NULL && (cpup->cpu_flags & CPU_READY)) { while (cpup->cpu_m.xc_ack[pri] == 0) - ht_pause(); + SMT_PAUSE(); + XC_TRACE(TT_XC_ACK, pri, cix); cpup->cpu_m.xc_ack[pri] = 0; } } @@ -592,6 +591,9 @@ kdi_xc_others(int this_cpu, void (*func)(void)) cpuset_t set; int x; + if (!xc_initialized) + return; + CPUSET_ALL_BUT(set, this_cpu); save_kernel_preemption = IGNORE_KERNEL_PREEMPTION; diff --git a/usr/src/uts/i86pc/pcplusmp/Makefile b/usr/src/uts/i86pc/pcplusmp/Makefile index 18b7a414d2..f0e108904d 100644 --- a/usr/src/uts/i86pc/pcplusmp/Makefile +++ b/usr/src/uts/i86pc/pcplusmp/Makefile @@ -21,7 +21,7 @@ # # uts/i86pc/pcplusmp/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -43,7 +43,7 @@ UTSBASE = ../.. MODULE = pcplusmp OBJECTS = $(PCPLUSMP_OBJS:%=$(OBJS_DIR)/%) LINTS = $(PCPLUSMP_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_MACH_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_PSM_MACH_DIR)/$(MODULE) # # Include common rules. diff --git a/usr/src/uts/i86pc/sys/Makefile b/usr/src/uts/i86pc/sys/Makefile index d1ae51babe..c3afe499df 100644 --- a/usr/src/uts/i86pc/sys/Makefile +++ b/usr/src/uts/i86pc/sys/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,7 +21,7 @@ # #pragma ident "%Z%%M% %I% %E% SMI" # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # uts/i86pc/sys/Makefile @@ -46,12 +45,14 @@ HDRS= \ clock.h \ cram.h \ ddi_subrdefs.h \ + debug_info.h \ + mach_mmu.h \ machcpuvar.h \ machparam.h \ machsystm.h \ machthread.h \ memnode.h \ - pmem.h \ + pc_mmu.h \ psm.h \ psm_defs.h \ psm_modctl.h \ @@ -60,7 +61,8 @@ HDRS= \ smp_impldefs.h \ vm_machparam.h \ x_call.h \ - xc_levels.h + xc_levels.h \ + xsvc.h ROOTHDRS= $(HDRS:%=$(USR_PSM_ISYS_DIR)/%) diff --git a/usr/src/uts/i86pc/io/pcplusmp/apic.h b/usr/src/uts/i86pc/sys/apic.h index 56cef05819..ede1d1225e 100644 --- a/usr/src/uts/i86pc/io/pcplusmp/apic.h +++ b/usr/src/uts/i86pc/sys/apic.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -28,6 +28,8 @@ #pragma ident "%Z%%M% %I% %E% SMI" +#include <sys/psm_types.h> + #ifdef __cplusplus extern "C" { #endif @@ -230,7 +232,7 @@ struct apic_io_entry { #define IOAPIC_FLAGS_EN 0x01 /* this I/O apic is enable or not */ -#define MAX_IO_APIC 32 /* maximum # of I/O apic supported */ +#define MAX_IO_APIC 32 /* maximum # of IOAPICs supported */ struct apic_io_intr { uint_t intr_entry: 8, @@ -333,8 +335,8 @@ struct apic_io_intr { /* special or reserve vectors */ #define APIC_CHECK_RESERVE_VECTORS(v) \ - ((v == T_FASTTRAP) || (v == APIC_SPUR_INTR) || (v == T_SYSCALLINT) ||\ - (v == T_DTRACE_RET) || (v == T_INT80)) + ((v == T_FASTTRAP) || (v == APIC_SPUR_INTR) || (v == T_SYSCALLINT) || \ + (v == T_DTRACE_RET) || (v == T_INT80)) /* cmos shutdown code for BIOS */ #define BIOS_SHUTDOWN 0x0a @@ -421,7 +423,7 @@ typedef struct apic_irq { * to another CPU. */ major_t airq_major; /* major number corresponding to the device */ - ushort_t airq_rdt_entry; /* level, polarity & trig mode */ + ushort_t airq_rdt_entry; /* level, polarity & trig mode */ uchar_t airq_cpu; /* Which CPU are we bound to ? */ uchar_t airq_temp_cpu; /* Could be diff from cpu due to disable_intr */ uchar_t airq_vector; /* Vector chosen for this irq */ @@ -515,22 +517,21 @@ typedef struct apic_cpus_info { #define SMS_WRITE_STATE 0x80 #define SMS_ERROR_STATE 0xc0 +extern uint32_t ioapic_read(int ioapic_ix, uint32_t reg); +extern void ioapic_write(int ioapic_ix, uint32_t reg, uint32_t value); + /* Macros for reading/writing the IOAPIC RDT entries */ -#define READ_IOAPIC_RDT_ENTRY_LOW_DWORD(addr, ipin) \ - ((addr)[APIC_IO_REG] = APIC_RDT_CMD + (2 * (ipin)),\ - (addr)[APIC_IO_DATA]) +#define READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, ipin) \ + ioapic_read(ioapic_ix, APIC_RDT_CMD + (2 * (ipin))) -#define READ_IOAPIC_RDT_ENTRY_HIGH_DWORD(addr, ipin) \ - ((addr)[APIC_IO_REG] = APIC_RDT_CMD2 + (2 * (ipin)),\ - (addr)[APIC_IO_DATA]) +#define READ_IOAPIC_RDT_ENTRY_HIGH_DWORD(ioapic_ix, ipin) \ + ioapic_read(ioapic_ix, APIC_RDT_CMD2 + (2 * (ipin))) -#define WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(addr, ipin, value) \ - (addr)[APIC_IO_REG] = APIC_RDT_CMD + (2 * (ipin));\ - (addr)[APIC_IO_DATA] = (value) +#define WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, ipin, value) \ + ioapic_write(ioapic_ix, APIC_RDT_CMD + (2 * (ipin)), value) -#define WRITE_IOAPIC_RDT_ENTRY_HIGH_DWORD(addr, ipin, value) \ - (addr)[APIC_IO_REG] = APIC_RDT_CMD2 + (2 * (ipin));\ - (addr)[APIC_IO_DATA] = (value) +#define WRITE_IOAPIC_RDT_ENTRY_HIGH_DWORD(ioapic_ix, ipin, value) \ + ioapic_write(ioapic_ix, APIC_RDT_CMD2 + (2 * (ipin)), value) /* Used by PSM_INTR_OP_GET_INTR to return device information. */ typedef struct { @@ -567,11 +568,175 @@ typedef struct { #define APIC_NSECS_TO_TICKS(nsecs) (((int64_t)(nsecs) * \ apic_ticks_per_SFnsecs + (SF/2)) / SF) -extern uchar_t apic_bind_intr(dev_info_t *, int, uchar_t, uchar_t); -extern int apic_allocate_irq(int); -extern int apic_introp_xlate(dev_info_t *, struct intrspec *, int); -extern int apic_rebind_all(apic_irq_t *irq_ptr, int bind_cpu); +extern int apic_verbose; + +/* Flag definitions for apic_verbose */ +#define APIC_VERBOSE_IOAPIC_FLAG 0x00000001 +#define APIC_VERBOSE_IRQ_FLAG 0x00000002 +#define APIC_VERBOSE_POWEROFF_FLAG 0x00000004 +#define APIC_VERBOSE_POWEROFF_PAUSE_FLAG 0x00000008 + + +#define APIC_VERBOSE_IOAPIC(fmt) \ + if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) \ + cmn_err fmt; + +#define APIC_VERBOSE_IRQ(fmt) \ + if (apic_verbose & APIC_VERBOSE_IRQ_FLAG) \ + cmn_err fmt; + +#define APIC_VERBOSE_POWEROFF(fmt) \ + if (apic_verbose & APIC_VERBOSE_POWEROFF_FLAG) \ + prom_printf fmt; + +#ifdef DEBUG +#define DENT 0x0001 +extern int apic_debug; +/* + * set apic_restrict_vector to the # of vectors we want to allow per range + * useful in testing shared interrupt logic by setting it to 2 or 3 + */ +extern int apic_restrict_vector; + +#define APIC_DEBUG_MSGBUFSIZE 2048 +extern int apic_debug_msgbuf[]; +extern int apic_debug_msgbufindex; + +/* + * Put "int" info into debug buffer. No MP consistency, but light weight. + * Good enough for most debugging. + */ +#define APIC_DEBUG_BUF_PUT(x) \ + apic_debug_msgbuf[apic_debug_msgbufindex++] = x; \ + if (apic_debug_msgbufindex >= (APIC_DEBUG_MSGBUFSIZE - NCPU)) \ + apic_debug_msgbufindex = 0; + +#endif /* DEBUG */ + +extern int apic_error; +/* values which apic_error can take. Not catastrophic, but may help debug */ +#define APIC_ERR_BOOT_EOI 0x1 +#define APIC_ERR_GET_IPIVECT_FAIL 0x2 +#define APIC_ERR_INVALID_INDEX 0x4 +#define APIC_ERR_MARK_VECTOR_FAIL 0x8 +#define APIC_ERR_APIC_ERROR 0x40000000 +#define APIC_ERR_NMI 0x80000000 + +/* + * ACPI definitions + */ +/* _PIC method arguments */ +#define ACPI_PIC_MODE 0 +#define ACPI_APIC_MODE 1 + +/* APIC error flags we care about */ +#define APIC_SEND_CS_ERROR 0x01 +#define APIC_RECV_CS_ERROR 0x02 +#define APIC_CS_ERRORS (APIC_SEND_CS_ERROR|APIC_RECV_CS_ERROR) + +/* Maximum number of times to retry reprogramming at apic_intr_exit time */ +#define APIC_REPROGRAM_MAX_TRIES 10000 + +/* Parameter to ioapic_init_intr(): Should ioapic ints be masked? */ +#define IOAPIC_MASK 1 +#define IOAPIC_NOMASK 0 + +#define INTR_ROUND_ROBIN_WITH_AFFINITY 0 +#define INTR_ROUND_ROBIN 1 +#define INTR_LOWEST_PRIORITY 2 + + + +struct ioapic_reprogram_data { + boolean_t done; + apic_irq_t *irqp; + /* The CPU to which the int will be bound */ + int bindcpu; + /* # times the reprogram timeout was called */ + unsigned tries; +}; + +/* The irq # is implicit in the array index: */ +extern struct ioapic_reprogram_data apic_reprogram_info[]; + +extern void apic_intr_exit(int ipl, int irq); +extern int apic_probe_common(); +extern void apic_init_common(); +extern void ioapic_init_intr(); +extern void ioapic_disable_redirection(); +extern int apic_addspl_common(int irqno, int ipl, int min_ipl, int max_ipl); +extern int apic_delspl_common(int irqno, int ipl, int min_ipl, int max_ipl); +extern void apic_cleanup_busy(); +extern void apic_intr_redistribute(); +extern uchar_t apic_xlate_vector(uchar_t vector); +extern uchar_t apic_allocate_vector(int ipl, int irq, int pri); +extern void apic_free_vector(uchar_t vector); +extern int apic_allocate_irq(int irq); +extern uchar_t apic_bind_intr(dev_info_t *dip, int irq, uchar_t ioapicid, + uchar_t intin); +extern int apic_rebind(apic_irq_t *irq_ptr, int bind_cpu, + struct ioapic_reprogram_data *drep); +extern int apic_rebind_all(apic_irq_t *irq_ptr, int bind_cpu); +extern int apic_introp_xlate(dev_info_t *dip, struct intrspec *ispec, int type); +extern int apic_intr_ops(dev_info_t *dip, ddi_intr_handle_impl_t *hdlp, + psm_intr_op_t intr_op, int *result); extern boolean_t apic_cpu_in_range(int cpu); +extern int apic_check_msi_support(); +extern apic_irq_t *apic_find_irq(dev_info_t *dip, struct intrspec *ispec, + int type); +extern int apic_navail_vector(dev_info_t *dip, int pri); +extern int apic_alloc_vectors(dev_info_t *dip, int inum, int count, int pri, + int type, int behavior); +extern void apic_free_vectors(dev_info_t *dip, int inum, int count, int pri, + int type); +extern int apic_get_vector_intr_info(int vecirq, + apic_get_intr_t *intr_params_p); +extern uchar_t apic_find_multi_vectors(int pri, int count); +extern int apic_setup_io_intr(void *p, int irq, boolean_t deferred); +extern uint32_t *mapin_apic(uint32_t addr, size_t len, int flags); +extern uint32_t *mapin_ioapic(uint32_t addr, size_t len, int flags); +extern void mapout_apic(caddr_t addr, size_t len); +extern void mapout_ioapic(caddr_t addr, size_t len); +extern uchar_t apic_modify_vector(uchar_t vector, int irq); +extern int apic_pci_msi_unconfigure(dev_info_t *rdip, int type, int inum); +extern int apic_pci_msi_disable_mode(dev_info_t *rdip, int type, int inum); +extern int apic_pci_msi_enable_mode(dev_info_t *rdip, int type, int inum); + +extern volatile uint32_t *apicadr; /* virtual addr of local APIC */ +extern int apic_forceload; +extern apic_cpus_info_t *apic_cpus; +extern cpuset_t apic_cpumask; +extern uint_t apic_flag; +extern uchar_t apic_ipltopri[MAXIPL+1]; +extern uchar_t apic_vector_to_irq[APIC_MAX_VECTOR+1]; +extern int apic_max_device_irq; +extern int apic_min_device_irq; +extern apic_irq_t *apic_irq_table[APIC_MAX_VECTOR+1]; +extern volatile uint32_t *apicioadr[MAX_IO_APIC]; +extern uchar_t apic_io_id[MAX_IO_APIC]; +extern lock_t apic_ioapic_lock; +extern uint32_t apic_physaddr[MAX_IO_APIC]; +extern kmutex_t airq_mutex; +extern int apic_first_avail_irq; +extern uchar_t apic_vectortoipl[APIC_AVAIL_VECTOR / APIC_VECTOR_PER_IPL]; +extern int apic_imcrp; +extern int apic_revector_pending; +extern char apic_level_intr[APIC_MAX_VECTOR+1]; +extern uchar_t apic_resv_vector[MAXIPL+1]; +extern int apic_sample_factor_redistribution; +extern int apic_int_busy_mark; +extern int apic_int_free_mark; +extern int apic_diff_for_redistribution; +extern int apic_poweroff_method; +extern int apic_enable_acpi; +extern int apic_nproc; +extern int apic_next_bind_cpu; +extern int apic_redistribute_sample_interval; +extern int apic_multi_msi_enable; +extern int apic_multi_msi_max; +extern int apic_sci_vect; + + #ifdef __cplusplus } diff --git a/usr/src/uts/i86pc/sys/asm_misc.h b/usr/src/uts/i86pc/sys/asm_misc.h index 0003f220ab..be45a97886 100644 --- a/usr/src/uts/i86pc/sys/asm_misc.h +++ b/usr/src/uts/i86pc/sys/asm_misc.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -49,6 +48,42 @@ extern "C" { #define STI_INSTR 0xfb #define JMP_INSTR 0x00eb + +#if defined(__i386) + +#define _HOT_PATCH_PROLOG \ + push %ebp; \ + mov %esp, %ebp; \ + push %ebx; \ + push %esi; \ + push %edi + +#define _HOT_PATCH(srcaddr, dstaddr, size) \ + movl $srcaddr, %esi; \ + movl $dstaddr, %edi; \ + movl $size, %ebx; \ +0: pushl $1; \ + /*CSTYLED*/ \ + movzbl (%esi), %eax; \ + pushl %eax; \ + pushl %edi; \ + call hot_patch_kernel_text; \ + addl $12, %esp; \ + inc %edi; \ + inc %esi; \ + dec %ebx; \ + test %ebx, %ebx; \ + jne 0b + +#define _HOT_PATCH_EPILOG \ + pop %edi; \ + pop %esi; \ + pop %ebx; \ + mov %ebp, %esp; \ + pop %ebp + +#endif /* __i386 */ + #endif /* _ASM */ #ifdef __cplusplus diff --git a/usr/src/psm/stand/boot/i386/common/console.h b/usr/src/uts/i86pc/sys/boot_console.h index ca28b967f6..92fa9cebf5 100644 --- a/usr/src/psm/stand/boot/i386/common/console.h +++ b/usr/src/uts/i86pc/sys/boot_console.h @@ -19,12 +19,16 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#ifndef _CONSOLE_H -#define _CONSOLE_H +/* + * This file is shared between dboot and the kernel. + */ + +#ifndef _BOOT_CONSOLE_H +#define _BOOT_CONSOLE_H #pragma ident "%Z%%M% %I% %E% SMI" @@ -34,29 +38,27 @@ extern "C" { #define CONS_INVALID -1 #define CONS_SCREEN_TEXT 0 -#define CONS_SCREEN_GRAPHICS 1 -#define CONS_TTYA 2 -#define CONS_TTYB 3 -#define CONS_USBSER 4 +#define CONS_TTYA 1 +#define CONS_TTYB 2 +#define CONS_USBSER 3 #define CONS_COLOR 7 -#define VGA_GRAPHICS 0x12 - extern void kb_init(void); extern int kb_getchar(void); extern int kb_ischar(void); -extern char *console_init(char *); -extern void console_init2(char *, char *, char *); -extern void text_init(void); -extern void putchar(int); -extern int getchar(void); -extern int ischar(void); -extern int cons_gets(char *, int); +extern void bcons_init(char *); +extern void bcons_init2(char *, char *, char *); +extern void bcons_putchar(int); +extern int bcons_getchar(void); +extern int bcons_ischar(void); +extern int bcons_gets(char *, int); + +extern int console; #ifdef __cplusplus } #endif -#endif /* _CONSOLE_H */ +#endif /* _BOOT_CONSOLE_H */ diff --git a/usr/src/uts/i86pc/sys/clock.h b/usr/src/uts/i86pc/sys/clock.h index d058a8ae72..efabb1c84c 100644 --- a/usr/src/uts/i86pc/sys/clock.h +++ b/usr/src/uts/i86pc/sys/clock.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -43,10 +42,13 @@ extern "C" { #if defined(__GNUC__) && defined(_ASM_INLINES) #include <asm/clock.h> #endif +#include <sys/machclock.h> + +extern time_t ggmtl(void); +extern void sgmtl(time_t); +extern void rtcsync(void); extern void unlock_hres_lock(void); -extern timestruc_t pc_tod_get(void); -extern void pc_tod_set(timestruc_t); extern void hres_tick(void); extern void (*hrtime_tick)(void); @@ -60,7 +62,7 @@ extern void tsc_tick(void); extern void tsc_sync_master(processorid_t); extern void tsc_sync_slave(void); extern hrtime_t tsc_read(void); - +extern hrtime_t __rdtsc_insn(void); #define ADJ_SHIFT 4 /* used in get_hrestime */ diff --git a/usr/src/psm/stand/boot/amd64/amd64/msr.h b/usr/src/uts/i86pc/sys/debug_info.h index 4bbba75b9b..3c626fd360 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/msr.h +++ b/usr/src/uts/i86pc/sys/debug_info.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,27 +19,31 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#ifndef _AMD64_MSR_H -#define _AMD64_MSR_H +#ifndef _SYS_DEBUG_INFO_H +#define _SYS_DEBUG_INFO_H #pragma ident "%Z%%M% %I% %E% SMI" +#include <sys/machparam.h> + #ifdef __cplusplus extern "C" { #endif -#include <sys/types.h> -#include <sys/controlregs.h> +#define DEBUG_INFO_MAGIC 0xdeb116ed +#define DEBUG_INFO_VERSION 0x1 -extern void amd64_rdmsr(uint32_t, uint64_t *); -extern void amd64_wrmsr(uint32_t, const uint64_t *); +typedef struct debug_info { + uint32_t di_magic; + uint32_t di_version; +} debug_info_t; #ifdef __cplusplus } #endif -#endif /* _AMD64_MSR_H */ +#endif /* _SYS_DEBUG_INFO_H */ diff --git a/usr/src/uts/i86pc/sys/mach_mmu.h b/usr/src/uts/i86pc/sys/mach_mmu.h new file mode 100644 index 0000000000..431c6045e4 --- /dev/null +++ b/usr/src/uts/i86pc/sys/mach_mmu.h @@ -0,0 +1,165 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_MACH_MMU_H +#define _SYS_MACH_MMU_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ASM + +#include <sys/types.h> +#include <sys/systm.h> + +/* + * Platform-dependent MMU routines and types. + * + * WARNING: this header file is used by both dboot and i86pc, so don't go using + * normal kernel headers. + */ + +#define TWO_MEG (2 * 1024 * 1024) + +/* + * This is: + * The kernel nucleus pagesizes, ie: bi->bi_kseg_size + * The grub 64 bit file load address (see multiboot header in dboot_grub.s) + * The grub 32 bit and hypervisor physical load addresses of + * the kernel text/data (see Mapfile.unix) + */ +#define FOUR_MEG (4 * 1024 * 1024) + +#define ONE_GIG (1024 * 1024 * 1024) +#define FOUR_GIG ((uint64_t)4 * ONE_GIG) + +#define MMU_STD_PAGESIZE 4096 +#ifdef __amd64 +#define MMU_STD_PAGEMASK 0xFFFFFFFFFFFFF000ULL +#else +#define MMU_STD_PAGEMASK 0xFFFFF000UL +#endif + +/* + * Defines for the bits in X86 and AMD64 Page Tables + * + * Notes: + * + * Largepages and PAT bits: + * + * bit 7 at level 0 is the PAT bit + * bit 7 above level 0 is the Pagesize bit (set for large page) + * bit 12 (when a large page) is the PAT bit + * + * In Solaris the PAT/PWT/PCD values are set up so that: + * + * PAT & PWT -> Write Protected + * PAT & PCD -> Write Combining + * PAT by itself (PWT == 0 && PCD == 0) yields uncacheable (same as PCD == 1) + * + * + * Permission bits: + * + * - PT_USER must be set in all levels for user pages + * - PT_WRITE must be set in all levels for user writable pages + * - PT_NX applies if set at any level + * + * For these, we use the "allow" settings in all tables above level 0 and only + * ever disable things in PTEs. + * + * The use of PT_GLOBAL and PT_NX depend on being enabled in processor + * control registers. Hence, we use a variable to reference these bit + * masks. During hat_kern_setup() if the feature isn't enabled we + * clear out the variables. + */ +#define PT_VALID (0x001) /* a valid translation is present */ +#define PT_WRITABLE (0x002) /* the page is writable */ +#define PT_USER (0x004) /* the page is accessible by user mode */ +#define PT_WRITETHRU (0x008) /* write back caching is disabled (non-PAT) */ +#define PT_NOCACHE (0x010) /* page is not cacheable (non-PAT) */ +#define PT_REF (0x020) /* page was referenced */ +#define PT_MOD (0x040) /* page was modified */ +#define PT_PAGESIZE (0x080) /* above level 0, indicates a large page */ +#define PT_PAT_4K (0x080) /* at level 0, used for write combining */ +#define PT_GLOBAL (0x100) /* the mapping is global */ +#define PT_SOFTWARE (0xe00) /* software bits */ + +#define PT_PAT_LARGE (0x1000) /* PAT bit for large pages */ + +#define PT_PTPBITS (PT_VALID | PT_USER | PT_WRITABLE | PT_REF) +#define PT_FLAGBITS (0xfff) /* for masking off flag bits */ + +/* + * The software bits are used by the HAT to track attributes. + * Note that the attributes are inclusive as the values increase. + * + * PT_NOSYNC - The PT_REF/PT_MOD bits are not sync'd to page_t. + * The hat will install them as always set. + * + * PT_NOCONSIST - There is no hment entry for this mapping. + * + */ +#define PT_NOSYNC (0x200) /* PTE was created with HAT_NOSYNC */ +#define PT_NOCONSIST (0x400) /* PTE was created with HAT_LOAD_NOCONSIST */ + +#include <sys/pc_mmu.h> + +/* + * The software extraction for a single Page Table Entry will always + * be a 64 bit unsigned int. If running a non-PAE hat, the page table + * access routines know to extend/shorten it to 32 bits. + */ +typedef uint64_t x86pte_t; +typedef uint32_t x86pte32_t; + +x86pte_t get_pteval(paddr_t, uint_t); +void set_pteval(paddr_t, uint_t, uint_t, x86pte_t); +paddr_t make_ptable(x86pte_t *, uint_t); +x86pte_t *find_pte(uint64_t, paddr_t *, uint_t, uint_t); +x86pte_t *map_pte(paddr_t, uint_t); + +#ifndef _BOOT +ulong_t getcr3(); +#endif + +extern uint_t *shift_amt; +extern uint_t ptes_per_table; +extern paddr_t top_page_table; +extern uint_t top_level; +extern uint_t pte_size; +extern uint_t shift_amt_nopae[]; +extern uint_t shift_amt_pae[]; +extern uint32_t lpagesize; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASM */ + +#endif /* _SYS_MACH_MMU_H */ diff --git a/usr/src/psm/stand/boot/i386/common/bootprop.h b/usr/src/uts/i86pc/sys/machclock.h index 7c25e8e69d..6b3686b95c 100644 --- a/usr/src/psm/stand/boot/i386/common/bootprop.h +++ b/usr/src/uts/i86pc/sys/machclock.h @@ -18,53 +18,49 @@ * * CDDL HEADER END */ + /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#ifndef _BOOTPROP_H -#define _BOOTPROP_H +#ifndef _SYS_MACHCLOCK_H +#define _SYS_MACHCLOCK_H #pragma ident "%Z%%M% %I% %E% SMI" -/* - * Global variables which will be exported as boot properties in - * i386_bootprop.c. - */ - #ifdef __cplusplus extern "C" { #endif -#include <sys/bootconf.h> -#include <sys/obpdefs.h> -#include <sys/param.h> - -extern char *impl_arch_name; -extern char *module_path; - /* - * bootenv.rc properties + * tod module name and operations */ -extern char *bootfile_prop; -extern char *inputdevice_prop; -extern char *outputdevice_prop; -extern char *console_prop; -/* These are actually in intel/bootprop.c. */ -extern int bgetproplen(struct bootops *, char *); -extern int bgetprop(struct bootops *, char *, void *); -extern int bsetprop(struct bootops *, char *, void *, int); -extern char *bnextprop(struct bootops *, char *); +struct tod_ops; +typedef struct tod_ops tod_ops_t; -extern void setup_bootdev_props(void); -extern void setup_bootprop(void); -extern void get_grub_bootargs(char *); -extern void get_eeprom_bootargs(char *); +struct tod_ops { + int tod_version; + timestruc_t (*tod_get)(tod_ops_t *); + void (*tod_set)(tod_ops_t *, timestruc_t); + /* + * On SPARC, additional operations include setting + * and clearing a watchdog timer, as well as power alarms. + */ + struct tod_ops *tod_next; +}; -#ifdef __cplusplus +#define TOD_OPS_VERSION 1 + +extern tod_ops_t *tod_ops; +extern char *tod_module_name; + +#define TODOP_GET(top) ((top)->tod_get(top)) +#define TODOP_SET(top, ts) ((top)->tod_set(top, ts)) + +#ifdef __cplusplus } #endif -#endif /* _BOOTPROP_H */ +#endif /* _SYS_MACHCLOCK_H */ diff --git a/usr/src/uts/i86pc/sys/machcpuvar.h b/usr/src/uts/i86pc/sys/machcpuvar.h index 2cd92ac3b5..3217a674ab 100644 --- a/usr/src/uts/i86pc/sys/machcpuvar.h +++ b/usr/src/uts/i86pc/sys/machcpuvar.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,7 +38,6 @@ extern "C" { #include <sys/segments.h> #include <sys/rm_platter.h> #include <sys/avintr.h> -#include <sys/mmu.h> #include <sys/pte.h> #ifndef _ASM @@ -73,35 +72,43 @@ struct machcpu { struct hat_cpu_info *mcpu_hat_info; /* i86 hardware table addresses that cannot be shared */ + user_desc_t *mcpu_gdt; /* GDT */ - gate_desc_t *mcpu_idt; /* IDT */ + gate_desc_t *mcpu_idt; /* current IDT */ + struct tss *mcpu_tss; /* TSS */ - struct cpu_tables *mcpu_cp_tables; /* pointer to space acquired */ - /* while starting up */ - /* auxillary processors */ kmutex_t mcpu_ppaddr_mutex; - caddr_t mcpu_caddr1; /* per cpu CADDR1 */ caddr_t mcpu_caddr2; /* per cpu CADDR2 */ - void *mcpu_caddr1pte; - void *mcpu_caddr2pte; - struct softint mcpu_softinfo; + uint64_t mcpu_caddr1pte; + uint64_t mcpu_caddr2pte; + + struct softint mcpu_softinfo; uint64_t pil_high_start[HIGH_LEVELS]; uint64_t intrstat[PIL_MAX + 1][2]; + struct cpuid_info *mcpu_cpi; + struct cmi *mcpu_cmi; /* CPU module state */ void *mcpu_cmidata; #if defined(__amd64) greg_t mcpu_rtmp_rsp; /* syscall: temporary %rsp stash */ greg_t mcpu_rtmp_r15; /* syscall: temporary %r15 stash */ #endif + + struct vcpu_info *mcpu_vcpu_info; + uint64_t mcpu_gdtpa; /* xen: GDT in physical address */ + + uint16_t mcpu_intr_pending; /* xen: pending interrupt levels */ }; #define NINTR_THREADS (LOCK_LEVEL-1) /* number of interrupt threads */ #endif /* _ASM */ +/* Please DON'T add any more of this namespace-poisoning sewage here */ + #define cpu_nodeid cpu_m.mcpu_nodeid #define cpu_pri cpu_m.mcpu_pri #define cpu_pri_data cpu_m.mcpu_pri_data diff --git a/usr/src/uts/i86pc/sys/machparam.h b/usr/src/uts/i86pc/sys/machparam.h index e5e92f9412..4b764776c5 100644 --- a/usr/src/uts/i86pc/sys/machparam.h +++ b/usr/src/uts/i86pc/sys/machparam.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -49,12 +49,11 @@ extern "C" { /* * Machine dependent parameters and limits. */ + #if defined(__amd64) -#define NCPU 64 /* NBBY * sizeof (ulong_t) for simple cpuset_t */ +#define NCPU 64 /* NBBY * sizeof (ulong_t) for simple cpuset_t */ #elif defined(__i386) #define NCPU 32 -#else -#error "port me" #endif /* @@ -86,9 +85,9 @@ extern "C" { #if !defined(_ASM) #define MMU_PAGEOFFSET (MMU_PAGESIZE-1) /* Mask of address bits in page */ -#else /* !_ASM */ -#define MMU_PAGEOFFSET _CONST(MMU_PAGESIZE-1) /* assembler lameness */ -#endif /* !_ASM */ +#else /* _ASM */ +#define MMU_PAGEOFFSET _CONST(MMU_PAGESIZE-1) /* assembler lameness */ +#endif /* _ASM */ #define MMU_PAGEMASK (~MMU_PAGEOFFSET) @@ -133,6 +132,8 @@ extern "C" { * i86 and i86pc files use kernelbase instead of KERNELBASE, which is * initialized in i86pc/os/startup.c. */ +#define KERNEL_TEXT_amd64 UINT64_C(0xfffffffffb800000) +#define KERNEL_TEXT_i386 ADDRESS_C(0xfe800000) #if defined(__amd64) @@ -160,6 +161,11 @@ extern "C" { #define SEGKPM_BASE ADDRESS_C(0xfffffe0000000000) /* + * This is valloc_base, above seg_kpm, but below everything else + */ +#define VALLOC_BASE ADDRESS_C(0xffffff0000000000) + +/* * default and boundary sizes for segkp */ #define SEGKPDEFSIZE (2L * 1024L * 1024L * 1024L) /* 2G */ @@ -172,20 +178,22 @@ extern "C" { #define SEGZIOMINSIZE (400L * 1024 * 1024L) /* 400M */ /* - * Boot (or, more precisely, vmx) maps most pages twice - once in the - * bottom 2GB of memory and once in the bottom 2GB of the topmost 4GB. - * When boot is unmapped this range is available to the kernel, but until - * then we have to leave it untouched. + * During intial boot we limit heap to the top 4Gig. */ -#define BOOT_DOUBLEMAP_BASE ADDRESS_C(0xffffffff00000000) -#define BOOT_DOUBLEMAP_SIZE ADDRESS_C(0x80000000) +#define BOOT_KERNELHEAP_BASE ADDRESS_C(0xffffffff00000000) /* * VMWare works best if we don't use the top 64Meg of memory for amd64. * Set KERNEL_TEXT to top_o_memory - 64Meg - 8 Meg for 8Meg of nucleus pages. */ #define PROMSTART ADDRESS_C(0xffc00000) -#define KERNEL_TEXT ADDRESS_C(0xfffffffffb800000) +#define KERNEL_TEXT KERNEL_TEXT_amd64 + +/* + * Virtual address range available to the debugger + */ +#define SEGDEBUGBASE ADDRESS_C(0xffffffffff800000) +#define SEGDEBUGSIZE ADDRESS_C(0x400000) /* * Define upper limit on user address space @@ -233,7 +241,14 @@ extern "C" { * need this region of virtual address space mapped 1-1 */ #define PROMSTART ADDRESS_C(0xffc00000) -#define KERNEL_TEXT ADDRESS_C(0xfe800000) +#define KERNEL_TEXT KERNEL_TEXT_i386 + +/* + * Virtual address range available to the debugger + * We place it just above the kernel text (4M) and kernel data (4M). + */ +#define SEGDEBUGBASE (KERNEL_TEXT + ADDRESS_C(0x800000)) +#define SEGDEBUGSIZE ADDRESS_C(0x400000) /* * Define upper limit on user address space @@ -243,8 +258,17 @@ extern "C" { #endif /* __i386 */ -#if !defined(_ASM) && !defined(_KADB) -extern uintptr_t kernelbase, segkmap_start, segmapsize; +/* + * Reserve two pages just below KERNEL_TEXT for the GDT and debug info page. + */ +#if !defined(_ASM) +#define MISC_VA_BASE (KERNEL_TEXT - MMU_PAGESIZE * 2) +#define GDT_VA (MISC_VA_BASE) +#define DEBUG_INFO_VA (MISC_VA_BASE + MMU_PAGESIZE) +#endif /* !_ASM */ + +#if !defined(_ASM) && !defined(_KMDB) +extern uintptr_t kernelbase, segmap_start, segmapsize; #endif /* diff --git a/usr/src/uts/i86pc/sys/machprivregs.h b/usr/src/uts/i86pc/sys/machprivregs.h new file mode 100644 index 0000000000..1d4abe0b1c --- /dev/null +++ b/usr/src/uts/i86pc/sys/machprivregs.h @@ -0,0 +1,172 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_MACHPRIVREGS_H +#define _SYS_MACHPRIVREGS_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Platform dependent instruction sequences for manipulating + * privileged state + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ASSERT_UPCALL_MASK_IS_SET /* empty */ + +/* + * CLI and STI + */ + +#define CLI(r) \ + cli + +#define STI \ + sti + +/* + * Used to re-enable interrupts in the body of exception handlers + */ + +#if defined(__amd64) + +#define ENABLE_INTR_FLAGS \ + pushq $F_ON; \ + popfq + +#elif defined(__i386) + +#define ENABLE_INTR_FLAGS \ + pushl $F_ON; \ + popfl + +#endif /* __i386 */ + +/* + * IRET and SWAPGS + */ +#if defined(__amd64) + +#define IRET iretq +#define SWAPGS swapgs + +#elif defined(__i386) + +#define IRET iret + +#endif /* __i386 */ + +#define CLEAN_CS /* empty */ + +/* + * Macros for saving the original segment registers and restoring them + * for fast traps. + */ +#if defined(__amd64) + +/* + * Smaller versions of INTR_PUSH and INTR_POP for fast traps. + * The following registers have been pushed onto the stack by + * hardware at this point: + * + * greg_t r_rip; + * greg_t r_cs; + * greg_t r_rfl; + * greg_t r_rsp; + * greg_t r_ss; + * + * This handler is executed both by 32-bit and 64-bit applications. + * 64-bit applications allow us to treat the set (%rdi, %rsi, %rdx, + * %rcx, %r8, %r9, %r10, %r11, %rax) as volatile across function calls. + * However, 32-bit applications only expect (%eax, %edx, %ecx) to be volatile + * across a function call -- in particular, %esi and %edi MUST be saved! + * + * We could do this differently by making a FAST_INTR_PUSH32 for 32-bit + * programs, and FAST_INTR_PUSH for 64-bit programs, but it doesn't seem + * particularly worth it. + */ +#define FAST_INTR_PUSH \ + INTGATE_INIT_KERNEL_FLAGS; \ + subq $REGOFF_RIP, %rsp; \ + movq %rsi, REGOFF_RSI(%rsp); \ + movq %rdi, REGOFF_RDI(%rsp); \ + swapgs + +#define FAST_INTR_POP \ + swapgs; \ + movq REGOFF_RSI(%rsp), %rsi; \ + movq REGOFF_RDI(%rsp), %rdi; \ + addq $REGOFF_RIP, %rsp + +#define FAST_INTR_RETURN iretq + +#elif defined(__i386) + +#define FAST_INTR_PUSH \ + cld; \ + __SEGREGS_PUSH \ + __SEGREGS_LOAD_KERNEL + +#define FAST_INTR_POP \ + __SEGREGS_POP + +#define FAST_INTR_RETURN iret + +#endif /* __i386 */ + +/* + * Handling the CR0.TS bit for floating point handling. + * + * When the TS bit is *set*, attempts to touch the floating + * point hardware will result in a #nm trap. + */ +#if defined(__amd64) + +#define STTS(rtmp) \ + movq %cr0, rtmp; \ + orq $CR0_TS, rtmp; \ + movq rtmp, %cr0 + +#elif defined(__i386) + +#define STTS(rtmp) \ + movl %cr0, rtmp; \ + orl $CR0_TS, rtmp; \ + movl rtmp, %cr0 + +#endif /* __i386 */ + +#define CLTS \ + clts + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_MACHPRIVREGS_H */ diff --git a/usr/src/uts/i86pc/sys/machsystm.h b/usr/src/uts/i86pc/sys/machsystm.h index 43a3a94df1..caacf71e30 100644 --- a/usr/src/uts/i86pc/sys/machsystm.h +++ b/usr/src/uts/i86pc/sys/machsystm.h @@ -18,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,6 +42,9 @@ #include <sys/varargs.h> #include <sys/thread.h> #include <sys/cpuvar.h> +#include <sys/privregs.h> +#include <sys/systm.h> +#include <sys/traptrace.h> #include <vm/page.h> #ifdef __cplusplus @@ -49,7 +53,9 @@ extern "C" { #ifdef _KERNEL -extern void mp_halt(char *); +extern void mach_cpu_idle(void); +extern void mach_cpu_halt(char *); +extern int mach_cpu_start(cpu_t *, void *); extern int Cpudelay; extern void setcpudelay(void); @@ -61,10 +67,11 @@ extern void return_instr(void); extern int kcpc_hw_load_pcbe(void); extern void kcpc_hw_init(cpu_t *cp); +extern void kcpc_hw_fini(cpu_t *cp); extern int kcpc_hw_overflow_intr_installed; struct memconf { - pfn_t mcf_spfn; /* begin page fram number */ + pfn_t mcf_spfn; /* begin page frame number */ pfn_t mcf_epfn; /* end page frame number */ }; @@ -84,6 +91,9 @@ extern int cpuid2nodeid(int); extern void map_kaddr(caddr_t, pfn_t, int, int); extern void memscrub_init(void); +extern void trap(struct regs *, caddr_t, processorid_t); + +extern void do_interrupt(struct regs *, trap_trace_rec_t *); extern void memscrub_disable(void); extern unsigned int microdata; @@ -92,6 +102,11 @@ extern int use_mp; extern struct cpu cpus[]; /* pointer to other cpus */ extern struct cpu *cpu[]; /* pointer to all cpus */ +extern int mach_cpucontext_init(void); +extern void mach_cpucontext_fini(void); +extern void *mach_cpucontext_alloc(struct cpu *); +extern void mach_cpucontext_free(struct cpu *, void *, int); + extern uintptr_t hole_start, hole_end; #define INVALID_VADDR(a) \ @@ -102,6 +117,11 @@ extern size_t kpm_size; extern uchar_t kpm_size_shift; extern caddr_t kpm_vbase; +struct memlist; +extern void memlist_add(uint64_t, uint64_t, struct memlist *, + struct memlist **); +extern page_t *page_get_physical(uintptr_t); + #endif /* _KERNEL */ #ifdef __cplusplus diff --git a/usr/src/uts/i86pc/sys/pc_mmu.h b/usr/src/uts/i86pc/sys/pc_mmu.h new file mode 100644 index 0000000000..89661449a4 --- /dev/null +++ b/usr/src/uts/i86pc/sys/pc_mmu.h @@ -0,0 +1,66 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_PC_MMU_H +#define _SYS_PC_MMU_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Platform-dependent MMU routines and types for real x86 hardware. + * + * WARNING: this header file is used by both dboot and i86pc, so don't go using + * normal kernel headers. + */ + +#define IN_HYPERVISOR_VA(va) (__lintzero) + +void reload_cr3(void); + +#define pa_to_ma(pa) (pa) +#define ma_to_pa(ma) (ma) +#define pfn_to_mfn(pfn) (pfn) +#define mfn_to_pfn(mfn) (mfn) + +#ifndef _BOOT + +void mmu_tlbflush_entry(caddr_t); +void setcr3(ulong_t); + +#if defined(__GNUC__) +#include <asm/mmu.h> +#endif + +#endif /* !_BOOT */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_PC_MMU_H */ diff --git a/usr/src/uts/i86pc/sys/psm_types.h b/usr/src/uts/i86pc/sys/psm_types.h index 9af8bdde12..435d2da112 100644 --- a/usr/src/uts/i86pc/sys/psm_types.h +++ b/usr/src/uts/i86pc/sys/psm_types.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -61,7 +61,7 @@ typedef enum psm_intr_op_e { PSM_INTR_OP_GET_INTR /* 13. Get vector's info */ } psm_intr_op_t; -struct psm_ops { +struct psm_ops { int (*psm_probe)(void); void (*psm_softinit)(void); @@ -89,7 +89,11 @@ struct psm_ops { hrtime_t (*psm_gethrtime)(void); processorid_t (*psm_get_next_processorid)(processorid_t cpu_id); +#if defined(PSMI_1_5) + int (*psm_cpu_start)(processorid_t cpun, caddr_t ctxt); +#else void (*psm_cpu_start)(processorid_t cpun, caddr_t rm_code); +#endif int (*psm_post_cpu_start)(void); #if defined(PSMI_1_2) || defined(PSMI_1_3) || defined(PSMI_1_4) || \ defined(PSMI_1_5) @@ -102,9 +106,10 @@ struct psm_ops { int (*psm_translate_irq)(dev_info_t *dip, int irqno); +#if defined(PSMI_1_2) || defined(PSMI_1_3) || defined(PSMI_1_4) int (*psm_tod_get)(todinfo_t *tod); int (*psm_tod_set)(todinfo_t *tod); - +#endif void (*psm_notify_error)(int level, char *errmsg); #if defined(PSMI_1_2) || defined(PSMI_1_3) || defined(PSMI_1_4) || \ defined(PSMI_1_5) @@ -126,7 +131,7 @@ struct psm_ops { }; -struct psm_info { +struct psm_info { ushort_t p_version; ushort_t p_owner; struct psm_ops *p_ops; diff --git a/usr/src/uts/i86pc/sys/rm_platter.h b/usr/src/uts/i86pc/sys/rm_platter.h index 8f1bc977ba..b21c54dd63 100644 --- a/usr/src/uts/i86pc/sys/rm_platter.h +++ b/usr/src/uts/i86pc/sys/rm_platter.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -98,18 +98,14 @@ typedef struct rm_platter { } rm_platter_t; /* - * cpu tables put within a single structure all the tables which need to be - * allocated when a CPU starts up. Makes it more memory efficient and easier - * to allocate/release + * cpu tables put within a single structure two of the tables which need to be + * allocated when a CPU starts up. * - * Note: gdt and tss should be 16 byte aligned for best performance on - * amd64. Since DEFAULTSTKSIZE is a multiple of pagesize gdt will be aligned. - * We test below that the tss is properly aligned. + * Note: the tss should be 16 byte aligned for best performance on amd64 + * Since DEFAULTSTKSIZE is a multiple of PAGESIZE tss will be aligned. */ - struct cpu_tables { char ct_stack[DEFAULTSTKSZ]; - user_desc_t *ct_gdt; struct tss ct_tss; }; diff --git a/usr/src/uts/i86pc/sys/smp_impldefs.h b/usr/src/uts/i86pc/sys/smp_impldefs.h index e61c756381..27beafeac7 100644 --- a/usr/src/uts/i86pc/sys/smp_impldefs.h +++ b/usr/src/uts/i86pc/sys/smp_impldefs.h @@ -18,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -53,7 +54,6 @@ extern void (*picinitf)(); /* pic init entry point */ extern int (*clkinitf)(int, int *); /* clock init entry point */ extern int (*ap_mlsetup)(); /* completes init of starting cpu */ extern void (*send_dirintf)(); /* send interprocessor intr */ -extern void (*cpu_startf)(); /* start running a given processor */ extern hrtime_t (*gethrtimef)(); /* get high resolution timer value */ extern hrtime_t (*gethrtimeunscaledf)(); /* get high res timer unscaled value */ extern void (*psm_shutdownf)(int, int); /* machine dependent shutdown */ diff --git a/usr/src/uts/i86pc/sys/x_call.h b/usr/src/uts/i86pc/sys/x_call.h index daabe989b8..37cd7e39af 100644 --- a/usr/src/uts/i86pc/sys/x_call.h +++ b/usr/src/uts/i86pc/sys/x_call.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -29,7 +29,6 @@ #pragma ident "%Z%%M% %I% %E% SMI" - /* * For x86, we only have three cross call levels: * a low, med and high. (see xc_levels.h) @@ -66,6 +65,10 @@ struct xc_mbox { int saved_pri; }; +#if defined(_MACHDEP) +extern cpuset_t cpu_ready_set; +#endif + /* * Cross-call routines. */ @@ -76,11 +79,23 @@ extern uint_t xc_serv(caddr_t, caddr_t); extern void xc_call(xc_arg_t, xc_arg_t, xc_arg_t, int, cpuset_t, xc_func_t); extern void xc_trycall(xc_arg_t, xc_arg_t, xc_arg_t, cpuset_t, xc_func_t); extern void xc_sync(xc_arg_t, xc_arg_t, xc_arg_t, int, cpuset_t, xc_func_t); -extern void xc_wait_sync(xc_arg_t, xc_arg_t, xc_arg_t, int, cpuset_t, - xc_func_t); extern void xc_capture_cpus(cpuset_t); extern void xc_release_cpus(void); +#if defined(TRAPTRACE) + +/* + * X-call tracing can be interleaved with trap tracing + */ +extern void xc_make_trap_trace_entry(uint8_t, int, ulong_t); +#define XC_TRACE(m, pri, arg) xc_make_trap_trace_entry(m, pri, arg) + +#else /* TRAPTRACE */ + +#define XC_TRACE(m, pri, arg) /* nothing */ + +#endif /* TRAPTRACE */ + #endif /* _KERNEL */ #endif /* !_ASM */ diff --git a/usr/src/uts/i86pc/sys/xsvc.h b/usr/src/uts/i86pc/sys/xsvc.h new file mode 100644 index 0000000000..1bf541e98d --- /dev/null +++ b/usr/src/uts/i86pc/sys/xsvc.h @@ -0,0 +1,134 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_XSVC_H +#define _SYS_XSVC_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/avl.h> +#include <sys/types.h> + +/* xsvc ioctls */ +#define XSVCIOC ('Q'<< 8) +#define XSVC_ALLOC_MEM (XSVCIOC | 130) +#define XSVC_FREE_MEM (XSVCIOC | 131) +#define XSVC_FLUSH_MEM (XSVCIOC | 132) + +/* arg * struct for ioctls */ +typedef struct _xsvc_mem_req { + int xsvc_mem_reqid; /* request ID */ + uint64_t xsvc_mem_addr_lo; /* low DMA address range */ + uint64_t xsvc_mem_addr_hi; /* high DMA address range */ + uint64_t xsvc_mem_align; /* DMA address alignment */ + int xsvc_mem_sgllen; /* s/g length */ + size_t xsvc_mem_size; /* length of mem in bytes */ + void *xsvc_sg_list; /* returned scatter gather list */ +} xsvc_mem_req; + +/* xsvc_sg_list format */ +typedef struct _xsvc_mloc { + uint64_t mloc_addr; + size_t mloc_size; +} xsvc_mloc; + +#ifdef _KERNEL +/* *** Driver Private Below *** */ + +/* arg * struct for ioctls from 32-bit app in 64-bit kernel */ +#pragma pack(1) +typedef struct _xsvc_mem_req_32 { + int xsvc_mem_reqid; /* request ID */ + uint64_t xsvc_mem_addr_lo; /* low DMA address range */ + uint64_t xsvc_mem_addr_hi; /* high DMA address range */ + uint64_t xsvc_mem_align; /* DMA address alignment */ + int xsvc_mem_sgllen; /* s/g length */ + uint32_t xsvc_mem_size; /* length of mem in bytes */ + uint32_t xsvc_sg_list; /* returned scatter gather list */ +} xsvc_mem_req_32; +#pragma pack() + +/* xsvc_sg_list format */ +#pragma pack(1) +typedef struct _xsvc_mloc_32 { + uint64_t mloc_addr; + uint32_t mloc_size; +} xsvc_mloc_32; +#pragma pack() + +/* avl node */ +typedef struct xsvc_mnode_s { + avl_node_t mn_link; + uint64_t mn_key; + struct xsvc_mem_s *mn_home; +} xsvc_mnode_t; + +/* track memory allocs */ +typedef struct xsvc_mem_s { + xsvc_mnode_t xm_mnode; + size_t xm_size; + caddr_t xm_addr; + size_t xm_real_length; + ddi_dma_handle_t xm_dma_handle; + ddi_acc_handle_t xm_mem_handle; + ddi_dma_attr_t xm_dma_attr; + ddi_device_acc_attr_t xm_device_attr; + uint_t xm_cookie_count; + ddi_dma_cookie_t xm_cookie; +} xsvc_mem_t; + +/* list of memory allocs */ +typedef struct xsvc_mlist_s { + kmutex_t ml_mutex; + avl_tree_t ml_avl; +} xsvc_mlist_t; + +/* driver state */ +typedef struct xsvc_state_s { + dev_info_t *xs_dip; + int xs_instance; + + /* + * track total memory allocated, mutex only covers + * xs_currently_alloced + */ + kmutex_t xs_mutex; + uint64_t xs_currently_alloced; + + xsvc_mlist_t xs_mlist; +} xsvc_state_t; + +#endif /* _KERNEL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_XSVC_H */ diff --git a/usr/src/uts/i86pc/unix/Makefile b/usr/src/uts/i86pc/unix/Makefile index 778a495e50..8bef129839 100644 --- a/usr/src/uts/i86pc/unix/Makefile +++ b/usr/src/uts/i86pc/unix/Makefile @@ -18,13 +18,14 @@ # # CDDL HEADER END # + # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" # -# This makefile drives the production of /unix (and unix.o). +# This makefile drives the production of unix (and unix.o). # # i86pc implementation architecture dependent # @@ -38,25 +39,27 @@ UTSBASE = ../.. # Define the module and object file sets. # UNIX = unix +DBOOT = dboot +MULTIBOOT = multiboot OBJECTS = $(SPECIAL_OBJS:%=$(OBJS_DIR)/%) \ $(CORE_OBJS:%=$(OBJS_DIR)/%) \ + $(KRTLD_OBJS:%=$(OBJS_DIR)/%) \ $(MACH_NOT_YET_KMODS:%=$(OBJS_DIR)/%) LINTS = $(SPECIAL_OBJS:%.o=$(LINTS_DIR)/%.ln) \ $(CORE_OBJS:%.o=$(LINTS_DIR)/%.ln) \ + $(KRTLD_OBJS:%.o=$(LINTS_DIR)/%.ln) \ $(MACH_NOT_YET_KMODS:%.o=$(LINTS_DIR)/%.ln) \ $(LINTS_DIR)/vers.ln \ $(LINTS_DIR)/modstubs.ln ROOTMODULE = $(ROOT_PSM_KERN_DIR)/$(UNIX) +ROOT_MULTIBOOT = $(ROOT_PSM_DIR)/$(MULTIBOOT) +BOOT_KERNEL = $(ROOT_BOOT_PSM_KERN_DIR)/$(UNIX) UNIX_BIN = $(OBJS_DIR)/$(UNIX) -KRTLD_32 = misc/krtld -KRTLD_64 = misc/$(SUBDIR64)/krtld -KRTLD = $(KRTLD_$(CLASS)) - LIBS = $(GENLIB) GENUNIX = genunix @@ -66,6 +69,13 @@ LIBOPTS = -L $(GENUNIX_DIR)/$(OBJS_DIR) -l $(GENUNIX) CTFEXTRAOBJS = $(OBJS_DIR)/vers.o +DBOOT_OBJS_DIR = dboot/$(OBJS_DIR) +DBOOT_OBJECTS = $(DBOOT_OBJS:%=$(DBOOT_OBJS_DIR)/%) +DBOOT_O = $(OBJS_DIR)/$(DBOOT).o +DBOOT_S = $(DBOOT_O:%.o=%.s) +DBOOT_LINTS = $(DBOOT_OBJS:%.o=$(DBOOT_OBJS_DIR)/%.ln) +DBOOT_LINT = $(i386_LINT) + # # Include common rules. # @@ -74,9 +84,9 @@ include $(UTSBASE)/i86pc/Makefile.i86pc # # Define targets # -ALL_TARGET = $(UNIX_BIN) -LINT_TARGET = $(LINT_LIB) -INSTALL_TARGET = $(UNIX_BIN) $(ROOTMODULE) +ALL_TARGET = $(UNIX_BIN) $(MULTIBOOT) +LINT_TARGET = $(LINT_LIB) $(DBOOT_LINT_LIB) +INSTALL_TARGET = $(UNIX_BIN) $(MULTIBOOT) $(ROOTMODULE) $(ROOT_MULTIBOOT) $(BOOT_KERNEL) # # This is UNIX_DIR. Use a short path. @@ -86,12 +96,21 @@ UNIX_DIR = . # # Overrides # -CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(OBJS_DIR)/vers.c \ - $(OBJS_DIR)/vers.o \ - $(DTRACESTUBS_O) $(DTRACESTUBS) +CLEANFILES += \ + $(UNIX_O) $(MODSTUBS_O) \ + $(OBJS_DIR)/vers.c $(OBJS_DIR)/vers.o \ + $(DTRACESTUBS_O) $(DTRACESTUBS) + +CLEANFILES += \ + $(DBOOT_O) $(DBOOT_S) \ + $(DBOOT_OBJECTS) \ + $(OBJS_DIR)/bios_call_src.o \ + $(OBJS_DIR)/bios_call_src \ + $(OBJS_DIR)/bios_call.s \ + $(DBOOT_OBJS_DIR)/$(DBOOT) -CLOBBERFILES = $(CLEANFILES) $(UNIX_BIN) -CLEANLINTFILES += $(LINT_LIB) +CLOBBERFILES = $(CLEANFILES) $(UNIX_BIN) $(MULTIBOOT) +CLEANLINTFILES += $(LINT_LIB) $(DBOOT_LINT_LIB) $(DBOOT_LINTS) # instr_size needs a special header $(OBJS_DIR)/instr_size.o := EXTRA_OPTIONS = -I$(SRC)/common/dis/i386 @@ -136,19 +155,48 @@ MAPFILE_64 = $(MAPFILE).amd64 MAPFILE_NAME = $(MAPFILE_$(CLASS)) $(UNIX_BIN): $(UNIX_O) $(MODSTUBS_O) $(MAPFILE_NAME) \ - $(GENLIB) $(DTRACESTUBS) - $(LD) -dy -b -o $@ -e _start -I $(KRTLD) -M $(MAPFILE_NAME) \ - $(UNIX_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) + $(GENLIB) $(DTRACESTUBS) $(DBOOT_O) + $(LD) -dy -b -o $@ -e dboot_image -znointerp -M $(MAPFILE_NAME) \ + $(UNIX_O) $(DBOOT_O) $(MODSTUBS_O) $(LIBOPTS) \ + $(DTRACESTUBS) + $(MBH_PATCH) $(UNIX_BIN) $(CTFMERGE_UNIQUIFY_AGAINST_GENUNIX) $(POST_PROCESS) $(UNIX_O): $(OBJECTS) $(OBJS_DIR)/vers.o $(LD) -r -o $@ $(OBJECTS) $(OBJS_DIR)/vers.o +$(DBOOT_O): $(DBOOT_OBJS_DIR) $(DBOOT_OBJECTS) + $(LD) -dn -M dboot/Mapfile.dboot \ + -o $(DBOOT_OBJS_DIR)/$(DBOOT) $(DBOOT_OBJECTS) + @echo " .data" > $(DBOOT_S) + @echo " .globl dboot_image" >> $(DBOOT_S) + @echo "dboot_image:" >> $(DBOOT_S) + $(ELFEXTRACT) $(DBOOT_OBJS_DIR)/$(DBOOT) >> $(DBOOT_S) + $(COMPILE.s) -o $(DBOOT_O) $(DBOOT_S) + +$(DBOOT_OBJS_DIR): + -@mkdir -p $@ 2> /dev/null + +# +# dboot is built as an intermediate target in dboot.o, so just make +# dboot.o the dependency here. +# +$(MULTIBOOT): $(DBOOT_O) + $(CP) $(DBOOT_OBJS_DIR)/$(DBOOT) $(MULTIBOOT) + $(POST_PROCESS) + +# +# The boot kernel is a copy of the 32-bit kernel paired with the +# install/failsafe miniroot +$(BOOT_KERNEL): $(ROOTMODULE) $(ROOT_BOOT_PSM_KERN_DIR) + $(CP) $(ROOTMODULE) $(BOOT_KERNEL) + $(POST_PROCESS) + # # Special rules for generating assym.h for inclusion in assembly files. # -$(DSF_DIR)/$(OBJS_DIR)/assym.h: FRC +$(DSF_DIR)/$(OBJS_DIR)/assym.h $(DSF_DIR)/$(OBJS_DIR)/kdi_assym.h: FRC @cd $(DSF_DIR); $(MAKE) all.targ $(GENLIB): FRC @@ -170,6 +218,11 @@ $(LINT_LIB): $(LINT_LIB_DIR) $(LINTS) @$(LINT) -o$(UNIX) $(LINTFLAGS) $(LINTS) @$(MV) $(@F) $@ +$(DBOOT_LINT_LIB): $(LINT_LIB_DIR) $(DBOOT_LINTS) + @-$(ECHO) "\n$(DBOOT): (library construction):" + @$(LINT) -o$(DBOOT) $(DBOOT_LINTFLAGS) $(DBOOT_LINTS) + @$(MV) $(@F) $@ + lintlib: $(LINT_DEPS) # diff --git a/usr/src/psm/stand/boot/i386/common/biosint.map b/usr/src/uts/i86pc/unix/dboot/Mapfile.dboot index 8780bf99b3..a8c6856dfe 100644 --- a/usr/src/psm/stand/boot/i386/common/biosint.map +++ b/usr/src/uts/i86pc/unix/dboot/Mapfile.dboot @@ -1,13 +1,9 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,7 +18,15 @@ # # CDDL HEADER END # + +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# #ident "%Z%%M% %I% %E% SMI" +# -text = LOAD V0x2000; -data = A0x1; +dboot = LOAD ?RWX V0xC00000 P0xC00000 A0x1000; +dboot : ?A; diff --git a/usr/src/uts/i86pc/vm/Makefile b/usr/src/uts/i86pc/vm/Makefile index dab7916bfe..270efbe462 100644 --- a/usr/src/uts/i86pc/vm/Makefile +++ b/usr/src/uts/i86pc/vm/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -40,7 +39,7 @@ include ../Makefile.i86pc FILEMODE = 644 GROUP = bin -HDRS= hat_i86.h hat_pte.h hment.h htable.h +HDRS= hat_i86.h hat_pte.h hment.h htable.h kboot_mmu.h ROOTHDRS= $(HDRS:%=$(USR_PSM_IVM_DIR)/%) @@ -73,9 +72,6 @@ $(ROOTDIRS): $(ROOTLINK): $(ROOTDIRS) -$(RM) -r $@; $(SYMLINK) $(LINKDEST) $@ $(CHOWNLINK) $(CHGRPLINK) -#%.check: -# $(DOT_H_CHECK) - CLEANFILES= CLOBBERFILES= diff --git a/usr/src/uts/i86pc/vm/hat_i86.c b/usr/src/uts/i86pc/vm/hat_i86.c index bd95917765..05bdde381a 100644 --- a/usr/src/uts/i86pc/vm/hat_i86.c +++ b/usr/src/uts/i86pc/vm/hat_i86.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -58,6 +58,10 @@ #include <sys/x86_archext.h> #include <sys/atomic.h> #include <sys/bitmap.h> +#include <sys/controlregs.h> +#include <sys/bootconf.h> +#include <sys/bootsvcs.h> +#include <sys/bootinfo.h> #include <vm/seg_kmem.h> #include <vm/hat_i86.h> @@ -67,16 +71,14 @@ #include <vm/seg_kp.h> #include <vm/seg_kpm.h> #include <vm/vm_dep.h> +#include <vm/kboot_mmu.h> #include <sys/cmn_err.h> - /* * Basic parameters for hat operation. */ struct hat_mmu_info mmu; -uint_t force_pae_off = 0; /* for testing, change with kernel debugger */ -uint_t force_pae_on = 0; /* for testing, change with kernel debugger */ /* * The page that is the kernel's top level pagetable. @@ -168,21 +170,6 @@ kmem_cache_t *vlp_hash_cache; struct hatstats hatstat; /* - * macros to detect addresses in use by kernel only during boot - */ -#if defined(__amd64) - -#define BOOT_VA(va) ((va) < kernelbase || \ - ((va) >= BOOT_DOUBLEMAP_BASE && \ - (va) < BOOT_DOUBLEMAP_BASE + BOOT_DOUBLEMAP_SIZE)) - -#elif defined(__i386) - -#define BOOT_VA(va) ((va) < kernelbase) - -#endif /* __i386 */ - -/* * useful stuff for atomic access/clearing/setting REF/MOD/RO bits in page_t's. */ extern void atomic_orb(uchar_t *addr, uchar_t val); @@ -238,8 +225,6 @@ hati_constructor(void *buf, void *handle, int kmflags) sizeof (pgcnt_t) * (mmu.max_page_level + 1)); hat->hat_stats = 0; hat->hat_flags = 0; - mutex_init(&hat->hat_switch_mutex, NULL, MUTEX_DRIVER, - (void *)ipltospl(DISP_LEVEL)); CPUSET_ZERO(hat->hat_cpus); hat->hat_htable = NULL; hat->hat_ht_hash = NULL; @@ -305,6 +290,7 @@ hat_alloc(struct as *as) hat->hat_htable = NULL; hat->hat_ht_cached = NULL; ht = htable_create(hat, (uintptr_t)0, TOP_LEVEL(hat), NULL); + if (!(hat->hat_flags & HAT_VLP)) x86pte_copy(kas.a_hat->hat_htable, ht, khat_start, khat_entries); @@ -461,39 +447,20 @@ mmu_init(void) int i; /* - * if CPU enabled the page table global bit, use it for the kernel - * This is bit 7 in CR4 (PGE - Page Global Enable) + * If CPU enabled the page table global bit, use it for the kernel + * This is bit 7 in CR4 (PGE - Page Global Enable). */ - if ((x86_feature & X86_PGE) != 0 && (getcr4() & 0x80) != 0) + if ((x86_feature & X86_PGE) != 0 && (getcr4() & CR4_PGE) != 0) mmu.pt_global = PT_GLOBAL; /* - * We use PAE except when we aren't on an AMD64 and this is - * a 32 bit kernel with all physical addresses less than 4 Gig. + * Detect NX and PAE usage. */ - mmu.pae_hat = 1; - if (x86_feature & X86_NX) { + mmu.pae_hat = kbm_pae_support; + if (kbm_nx_support) mmu.pt_nx = PT_NX; - } else { - mmu.pt_nx = 0; -#if defined(__i386) - if (!PFN_ABOVE4G(physmax)) - mmu.pae_hat = 0; -#endif - } - -#if defined(__i386) - /* - * Setting one of these two lets you force testing of the different - * hat modes for 32 bit, regardless of the hardware setup. - */ - if (force_pae_on) { - mmu.pae_hat = 1; - } else if (force_pae_off) { - mmu.pae_hat = 0; + else mmu.pt_nx = 0; - } -#endif /* * Use CPU info to set various MMU parameters @@ -541,7 +508,7 @@ mmu_init(void) * Initialize parameters based on the 64 or 32 bit kernels and * for the 32 bit kernel decide if we should use PAE. */ - if (x86_feature & X86_LARGEPAGE) + if (kbm_largepage_support) mmu.max_page_level = 1; else mmu.max_page_level = 0; @@ -590,15 +557,18 @@ mmu_init(void) mmu.level_mask[i] = ~mmu.level_offset[i]; } - mmu.pte_bits[0] = PT_VALID; - for (i = 1; i <= mmu.max_page_level; ++i) - mmu.pte_bits[i] = PT_VALID | PT_PAGESIZE; + for (i = 0; i <= mmu.max_page_level; ++i) { + mmu.pte_bits[i] = PT_VALID; + if (i > 0) + mmu.pte_bits[i] |= PT_PAGESIZE; + } /* * NOTE Legacy 32 bit PAE mode only has the P_VALID bit at top level. */ for (i = 1; i < mmu.num_level; ++i) mmu.ptp_bits[i] = PT_PTPBITS; + #if defined(__i386) mmu.ptp_bits[2] = PT_VALID; #endif @@ -625,15 +595,6 @@ mmu_init(void) while (mmu.hash_cnt * HASH_MAX_LENGTH < max_htables) mmu.hash_cnt <<= 1; #endif - - /* - * This code knows that there are only 2 pagesizes. - * We ignore 4MB (non-PAE) for now. The value is only used - * for optimizing demaps across large ranges. - * These return zero if no information is known. - */ - mmu.tlb_entries[0] = cpuid_get_dtlb_nent(NULL, MMU_PAGESIZE); - mmu.tlb_entries[1] = cpuid_get_dtlb_nent(NULL, 2 * 1024 * 1024); } @@ -765,11 +726,29 @@ hat_vlp_setup(struct cpu *cpu) #endif /* __amd64 */ } +/*ARGSUSED*/ +static void +hat_vlp_teardown(cpu_t *cpu) +{ +#if defined(__amd64) + struct hat_cpu_info *hci; + + if ((hci = cpu->cpu_hat_info) == NULL) + return; + if (hci->hci_vlp_l2ptes) + kmem_free(hci->hci_vlp_l2ptes, MMU_PAGESIZE); + if (hci->hci_vlp_l3ptes) + kmem_free(hci->hci_vlp_l3ptes, MMU_PAGESIZE); +#endif /* __amd64 */ +} + /* * Finish filling in the kernel hat. * Pre fill in all top level kernel page table entries for the kernel's * part of the address range. From this point on we can't use any new * kernel large pages if they need PTE's at max_level + * + * create the kmap mappings. */ void hat_init_finish(void) @@ -779,6 +758,7 @@ hat_init_finish(void) uint_t e; x86pte_t pte; uintptr_t va = kernelbase; + size_t size; #if defined(__i386) @@ -826,6 +806,8 @@ hat_init_finish(void) khat_entries = mmu.top_level_count - khat_start; for (e = khat_start; e < mmu.top_level_count; ++e, va += LEVEL_SIZE(mmu.max_level)) { + if (IN_HYPERVISOR_VA(va)) + continue; pte = x86pte_get(top, e); if (PTE_ISVALID(pte)) continue; @@ -847,20 +829,30 @@ hat_init_finish(void) * pagetable. We'll use the remainder for the "per CPU" page tables * for VLP processes. * - * We map the top level kernel pagetable into the kernel's AS to make - * it easy to use bcopy for kernel entry PTEs. - * - * We were guaranteed to get a physical address < 4Gig, since the 32 bit - * boot loader uses non-PAE page tables. + * We also map the top level kernel pagetable into the kernel to make + * it easy to use bcopy to initialize new address spaces. */ if (mmu.pae_hat) { vlp_page = vmem_alloc(heap_arena, MMU_PAGESIZE, VM_SLEEP); hat_devload(kas.a_hat, (caddr_t)vlp_page, MMU_PAGESIZE, kas.a_hat->hat_htable->ht_pfn, - PROT_READ | PROT_WRITE | HAT_NOSYNC | HAT_UNORDERED_OK, + PROT_WRITE | + PROT_READ | HAT_NOSYNC | HAT_UNORDERED_OK, HAT_LOAD | HAT_LOAD_NOCONSIST); } hat_vlp_setup(CPU); + + /* + * Create kmap (cached mappings of kernel PTEs) + * for 32 bit we map from segmap_start .. ekernelheap + * for 64 bit we map from segmap_start .. segmap_start + segmapsize; + */ +#if defined(__i386) + size = (uintptr_t)ekernelheap - segmap_start; +#elif defined(__amd64) + size = segmapsize; +#endif + hat_kmap_init((uintptr_t)segmap_start, size); } /* @@ -920,9 +912,7 @@ hat_switch(hat_t *hat) * This is a spin lock at DISP_LEVEL */ if (hat != kas.a_hat) { - mutex_enter(&hat->hat_switch_mutex); CPUSET_ATOMIC_ADD(hat->hat_cpus, cpu->cpu_id); - mutex_exit(&hat->hat_switch_mutex); } cpu->cpu_current_hat = hat; @@ -968,12 +958,13 @@ hati_mkpte(pfn_t pfn, uint_t attr, level_t level, uint_t flags) PTE_SET(pte, mmu.pt_nx); /* - * set the software bits used track ref/mod sync's and hments + * Set the software bits used track ref/mod sync's and hments. + * If not using REF/MOD, set them to avoid h/w rewriting PTEs. */ - if (attr & HAT_NOSYNC) - PTE_SET(pte, PT_NOSYNC); if (flags & HAT_LOAD_NOCONSIST) - PTE_SET(pte, PT_NOCONSIST | PT_NOSYNC); + PTE_SET(pte, PT_NOCONSIST | PT_REF | PT_MOD); + else if (attr & HAT_NOSYNC) + PTE_SET(pte, PT_NOSYNC | PT_REF | PT_MOD); /* * Set the caching attributes in the PTE. The combination @@ -1138,7 +1129,7 @@ hati_sync_pte_to_page(page_t *pp, x86pte_t pte, level_t level) uint_t rm = 0; pgcnt_t pgcnt; - if (PTE_GET(pte, PT_NOSYNC)) + if (PTE_GET(pte, PT_SOFTWARE) >= PT_NOSYNC) return; if (PTE_GET(pte, PT_REF)) @@ -1171,7 +1162,7 @@ hati_sync_pte_to_page(page_t *pp, x86pte_t pte, level_t level) /* * This the set of PTE bits for PFN, permissions and caching - * that require a TLB flush (hat_demap) if changed on a HAT_LOAD_REMAP + * that require a TLB flush (hat_tlb_inval) if changed on a HAT_LOAD_REMAP */ #define PT_REMAP_BITS \ (PT_PADDR | PT_NX | PT_WRITABLE | PT_WRITETHRU | \ @@ -1182,7 +1173,7 @@ hati_sync_pte_to_page(page_t *pp, x86pte_t pte, level_t level) * Do the low-level work to get a mapping entered into a HAT's pagetables * and in the mapping list of the associated page_t. */ -static void +static int hati_pte_map( htable_t *ht, uint_t entry, @@ -1196,6 +1187,7 @@ hati_pte_map( level_t l = ht->ht_level; hment_t *hm; uint_t is_consist; + int rv = 0; /* * Is this a consistant (ie. need mapping list lock) mapping? @@ -1224,18 +1216,20 @@ hati_pte_map( old_pte = x86pte_set(ht, entry, pte, pte_ptr); /* - * If the mapping didn't change there is nothing more to do. + * did we get a large page / page table collision? */ - if (PTE_EQUIV(pte, old_pte)) { - if (is_consist) { - x86_hm_exit(pp); - if (hm != NULL) - hment_free(hm); - } - return; + if (old_pte == LPAGE_ERROR) { + rv = -1; + goto done; } /* + * If the mapping didn't change there is nothing more to do. + */ + if (PTE_EQUIV(pte, old_pte)) + goto done; + + /* * Install a new mapping in the page's mapping list */ if (!PTE_ISVALID(old_pte)) { @@ -1247,7 +1241,7 @@ hati_pte_map( } HTABLE_INC(ht->ht_valid_cnt); PGCNT_INC(hat, l); - return; + return (rv); } /* @@ -1262,7 +1256,7 @@ hati_pte_map( if (PTE2PFN(old_pte, l) != PTE2PFN(pte, l)) { REMAPASSERT(flags & HAT_LOAD_REMAP); REMAPASSERT(flags & HAT_LOAD_NOCONSIST); - REMAPASSERT(PTE_GET(old_pte, PT_NOCONSIST)); + REMAPASSERT(PTE_GET(old_pte, PT_SOFTWARE) >= PT_NOCONSIST); REMAPASSERT(pf_is_memory(PTE2PFN(old_pte, l)) == pf_is_memory(PTE2PFN(pte, l))); REMAPASSERT(!is_consist); @@ -1276,20 +1270,16 @@ hati_pte_map( PTE_GET(pte, ~PT_REMAP_BITS)); /* - * A remap requires invalidating the TLBs, since remapping the - * same PFN requires NOCONSIST, we don't have to sync R/M bits. - */ - hat_demap(hat, htable_e2va(ht, entry)); - - /* * We don't create any mapping list entries on a remap, so release * any allocated hment after we drop the mapping list lock. */ +done: if (is_consist) { x86_hm_exit(pp); if (hm != NULL) hment_free(hm); } + return (rv); } /* @@ -1402,9 +1392,10 @@ hati_reserves_exit(uint_t kmem_for_hat) } /* - * Internal routine to load a single page table entry. + * Internal routine to load a single page table entry. This only fails if + * we attempt to overwrite a page table link with a large page. */ -static void +static int hati_load_common( hat_t *hat, uintptr_t va, @@ -1418,6 +1409,7 @@ hati_load_common( uint_t entry; x86pte_t pte; uint_t kmem_for_hat = (flags & HAT_NO_KALLOC) ? 1 : 0; + int rv = 0; ASSERT(hat == kas.a_hat || AS_LOCK_HELD(hat->hat_as, &hat->hat_as->a_lock)); @@ -1476,13 +1468,14 @@ hati_load_common( /* * establish the mapping */ - hati_pte_map(ht, entry, pp, pte, flags, NULL); + rv = hati_pte_map(ht, entry, pp, pte, flags, NULL); /* * release the htable and any reserves */ htable_release(ht); hati_reserves_exit(kmem_for_hat); + return (rv); } /* @@ -1521,7 +1514,7 @@ hat_kmap_load( ht = mmu.kmap_htables[(va - mmu.kmap_htables[0]->ht_vaddr) >> LEVEL_SHIFT(1)]; entry = htable_va2entry(va, ht); - hati_pte_map(ht, entry, pp, pte, flags, pte_ptr); + (void) hati_pte_map(ht, entry, pp, pte, flags, pte_ptr); } /* @@ -1535,7 +1528,7 @@ hat_kmap_load( * and hat_devload(). * * HAT_LOAD_NOCONSIST Do not add mapping to page_t mapping list. - * sets PT_NOCONSIST (soft bit) + * sets PT_NOCONSIST * * HAT_LOAD_SHARE A flag to hat_memload() to indicate h/w page tables * that map some user pages (not kas) is shared by more @@ -1551,7 +1544,7 @@ hat_kmap_load( * * The following is a protection attribute (like PROT_READ, etc.) * - * HAT_NOSYNC set PT_NOSYNC (soft bit) - this mapping's ref/mod bits + * HAT_NOSYNC set PT_NOSYNC - this mapping's ref/mod bits * are never cleared. * * Installing new valid PTE's and creation of the mapping list @@ -1576,7 +1569,7 @@ hat_memload( HATIN(hat_memload, hat, addr, (size_t)MMU_PAGESIZE); ASSERT(IS_PAGEALIGNED(va)); - ASSERT(hat == kas.a_hat || va <= kernelbase); + ASSERT(hat == kas.a_hat || va < _userlimit); ASSERT(hat == kas.a_hat || AS_LOCK_HELD(hat->hat_as, &hat->hat_as->a_lock)); ASSERT((flags & supported_memload_flags) == flags); @@ -1598,7 +1591,8 @@ hat_memload( * always set HAT_STORECACHING_OK. */ attr |= HAT_STORECACHING_OK; - hati_load_common(hat, va, pp, attr, flags, level, pfn); + if (hati_load_common(hat, va, pp, attr, flags, level, pfn) != 0) + panic("unexpected hati_load_common() failure"); HATOUT(hat_memload, hat, addr); } @@ -1624,7 +1618,7 @@ hat_memload_array( HATIN(hat_memload_array, hat, addr, len); ASSERT(IS_PAGEALIGNED(va)); - ASSERT(hat == kas.a_hat || va + len <= kernelbase); + ASSERT(hat == kas.a_hat || va + len <= _userlimit); ASSERT(hat == kas.a_hat || AS_LOCK_HELD(hat->hat_as, &hat->hat_as->a_lock)); ASSERT((flags & supported_memload_flags) == flags); @@ -1647,9 +1641,10 @@ hat_memload_array( pgsize = LEVEL_SIZE(level); if (level == 0) break; + if (!IS_P2ALIGNED(va, pgsize) || (eaddr - va) < pgsize || - !IS_P2ALIGNED(pfn << MMU_PAGESHIFT, pgsize)) + !IS_P2ALIGNED(pfn_to_pa(pfn), pgsize)) continue; /* @@ -1675,36 +1670,17 @@ hat_memload_array( } /* - * Shared page tables for DISM might have a pre-existing - * level 0 page table that wasn't unlinked from all the - * sharing hats. If we hit this for a large page, back off - * to using level 0 pages. - * - * This can't be made better (ie. use large pages) until we - * track all the htable's sharing and rewrite hat_pageunload(). - * Note that would cost a pointer in htable_t for a rare case. - * - * Since the 32 bit kernel caches empty page tables, check - * the kernel too. - */ - if ((hat == kas.a_hat || (hat->hat_flags & HAT_SHARED)) && - level > 0) { - htable_t *lower; - - lower = htable_getpte(hat, va, NULL, NULL, level - 1); - if (lower != NULL) { - level = 0; - pgsize = LEVEL_SIZE(0); - htable_release(lower); - } - } - - /* - * load this page mapping + * Load this page mapping. If the load fails, try a smaller + * pagesize. */ ASSERT(!IN_VA_HOLE(va)); - hati_load_common(hat, va, pages[pgindx], attr, flags, - level, pfn); + while (hati_load_common(hat, va, pages[pgindx], attr, + flags, level, pfn) != 0) { + if (level == 0) + panic("unexpected hati_load_common() failure"); + --level; + pgsize = LEVEL_SIZE(level); + } /* * move to next page @@ -1764,7 +1740,7 @@ hat_devload( HATIN(hat_devload, hat, addr, len); ASSERT(IS_PAGEALIGNED(va)); - ASSERT(hat == kas.a_hat || eva <= kernelbase); + ASSERT(hat == kas.a_hat || eva <= _userlimit); ASSERT(hat == kas.a_hat || AS_LOCK_HELD(hat->hat_as, &hat->hat_as->a_lock)); ASSERT((flags & supported_devload_flags) == flags); @@ -1788,24 +1764,9 @@ hat_devload( } /* - * Some kernel addresses have permanently existing page tables, - * so be sure to use a compatible pagesize. - */ - if (hat == kas.a_hat && level > 0) { - htable_t *lower; - - lower = htable_getpte(hat, va, NULL, NULL, level - 1); - if (lower != NULL) { - level = 0; - pgsize = LEVEL_SIZE(0); - htable_release(lower); - } - } - - /* - * If it is memory get page_t and allow caching (this happens + * If this is just memory then allow caching (this happens * for the nucleus pages) - though HAT_PLAT_NOCACHE can be used - * to override that. If we don't have a page_t, make sure + * to override that. If we don't have a page_t then make sure * NOCONSIST is set. */ a = attr; @@ -1827,7 +1788,12 @@ hat_devload( * load this page mapping */ ASSERT(!IN_VA_HOLE(va)); - hati_load_common(hat, va, pp, a, f, level, pfn); + while (hati_load_common(hat, va, pp, a, f, level, pfn) != 0) { + if (level == 0) + panic("unexpected hati_load_common() failure"); + --level; + pgsize = LEVEL_SIZE(level); + } /* * move to next page @@ -1854,7 +1820,7 @@ hat_unlock(hat_t *hat, caddr_t addr, size_t len) /* * kernel entries are always locked, we don't track lock counts */ - ASSERT(hat == kas.a_hat || eaddr <= kernelbase); + ASSERT(hat == kas.a_hat || eaddr <= _userlimit); ASSERT(IS_PAGEALIGNED(vaddr)); ASSERT(IS_PAGEALIGNED(eaddr)); if (hat == kas.a_hat) @@ -1903,7 +1869,7 @@ hati_demap_func(xc_arg_t a1, xc_arg_t a2, xc_arg_t a3) * For a normal address, we just flush one page mapping */ if ((uintptr_t)addr != DEMAP_ALL_ADDR) { - mmu_tlbflush_entry((caddr_t)addr); + mmu_tlbflush_entry(addr); return (0); } @@ -1931,10 +1897,11 @@ hati_demap_func(xc_arg_t a1, xc_arg_t a2, xc_arg_t a3) * all CPUs using a given hat. */ void -hat_demap(hat_t *hat, uintptr_t va) +hat_tlb_inval(hat_t *hat, uintptr_t va) { extern int flushes_require_xcalls; /* from mp_startup.c */ cpuset_t justme; + cpuset_t cpus_to_shootdown; /* * If the hat is being destroyed, there are no more users, so @@ -1963,29 +1930,29 @@ hat_demap(hat_t *hat, uintptr_t va) /* - * All CPUs must see kernel hat changes. + * Determine CPUs to shootdown. Kernel changes always do all CPUs. + * Otherwise it's just CPUs currently executing in this hat. */ - if (hat == kas.a_hat) { - kpreempt_disable(); - xc_call((xc_arg_t)hat, (xc_arg_t)va, NULL, - X_CALL_HIPRI, khat_cpuset, hati_demap_func); - kpreempt_enable(); - return; - } - - /* - * Otherwise we notify CPUs currently running in this HAT - */ - mutex_enter(&hat->hat_switch_mutex); kpreempt_disable(); CPUSET_ONLY(justme, CPU->cpu_id); - if (CPUSET_ISEQUAL(hat->hat_cpus, justme)) - (void) hati_demap_func((xc_arg_t)hat, (xc_arg_t)va, NULL); + if (hat == kas.a_hat) + cpus_to_shootdown = khat_cpuset; else - xc_call((xc_arg_t)hat, (xc_arg_t)va, NULL, - X_CALL_HIPRI, hat->hat_cpus, hati_demap_func); + cpus_to_shootdown = hat->hat_cpus; + + if (CPUSET_ISNULL(cpus_to_shootdown) || + CPUSET_ISEQUAL(cpus_to_shootdown, justme)) { + + (void) hati_demap_func((xc_arg_t)hat, (xc_arg_t)va, NULL); + + } else { + + CPUSET_ADD(cpus_to_shootdown, CPU->cpu_id); + xc_call((xc_arg_t)hat, (xc_arg_t)va, NULL, X_CALL_HIPRI, + cpus_to_shootdown, hati_demap_func); + + } kpreempt_enable(); - mutex_exit(&hat->hat_switch_mutex); } /* @@ -2024,7 +1991,7 @@ hat_pte_unmap( ASSERT(ht->ht_busy > 0); while (PTE_ISVALID(old_pte)) { pfn = PTE2PFN(old_pte, l); - if (PTE_GET(old_pte, PT_NOCONSIST)) { + if (PTE_GET(old_pte, PT_SOFTWARE) >= PT_NOCONSIST) { pp = NULL; } else { pp = page_numtopp_nolock(pfn); @@ -2046,8 +2013,7 @@ hat_pte_unmap( if (hat->hat_flags & HAT_FREEING) old_pte = x86pte_get(ht, entry); else - old_pte = - x86pte_invalidate_pfn(ht, entry, pfn, pte_ptr); + old_pte = x86pte_inval(ht, entry, old_pte, pte_ptr); /* * If the page hadn't changed we've unmapped it and can proceed @@ -2063,7 +2029,7 @@ hat_pte_unmap( x86_hm_exit(pp); pp = NULL; } else { - ASSERT(PTE_GET(old_pte, PT_NOCONSIST)); + ASSERT(PTE_GET(old_pte, PT_SOFTWARE) >= PT_NOCONSIST); } } @@ -2104,24 +2070,19 @@ hat_kmap_unload(caddr_t addr, size_t len, uint_t flags) { uintptr_t va = (uintptr_t)addr; uintptr_t eva = va + len; - pgcnt_t pg_off; + pgcnt_t pg_index; htable_t *ht; uint_t entry; - void *pte_ptr; + x86pte_t *pte_ptr; x86pte_t old_pte; for (; va < eva; va += MMU_PAGESIZE) { /* * Get the PTE */ - pg_off = mmu_btop(va - mmu.kmap_addr); - if (mmu.pae_hat) { - pte_ptr = mmu.kmap_ptes + pg_off; - ATOMIC_LOAD64((x86pte_t *)pte_ptr, old_pte); - } else { - pte_ptr = (x86pte32_t *)mmu.kmap_ptes + pg_off; - old_pte = *(x86pte32_t *)pte_ptr; - } + pg_index = mmu_btop(va - mmu.kmap_addr); + pte_ptr = PT_INDEX_PTR(mmu.kmap_ptes, pg_index); + old_pte = GET_PTE(pte_ptr); /* * get the htable / entry @@ -2145,7 +2106,8 @@ void hat_unload(hat_t *hat, caddr_t addr, size_t len, uint_t flags) { uintptr_t va = (uintptr_t)addr; - ASSERT(hat == kas.a_hat || va + len <= kernelbase); + + ASSERT(hat == kas.a_hat || va + len <= _userlimit); /* * special case for performance. @@ -2153,9 +2115,9 @@ hat_unload(hat_t *hat, caddr_t addr, size_t len, uint_t flags) if (mmu.kmap_addr <= va && va < mmu.kmap_eaddr) { ASSERT(hat == kas.a_hat); hat_kmap_unload(addr, len, flags); - return; + } else { + hat_unload_callback(hat, addr, len, flags, NULL); } - hat_unload_callback(hat, addr, len, flags, NULL); } /* @@ -2212,10 +2174,24 @@ hat_unload_callback( x86pte_t old_pte; HATIN(hat_unload_callback, hat, addr, len); - ASSERT(hat == kas.a_hat || eaddr <= kernelbase); + ASSERT(hat == kas.a_hat || eaddr <= _userlimit); ASSERT(IS_PAGEALIGNED(vaddr)); ASSERT(IS_PAGEALIGNED(eaddr)); + /* + * Special case a single page being unloaded for speed. This happens + * quite frequently, COW faults after a fork() for example. + */ + if (cb == NULL && len == MMU_PAGESIZE) { + ht = htable_getpte(hat, vaddr, &entry, &old_pte, 0); + if (ht != NULL) { + if (PTE_ISVALID(old_pte)) + hat_pte_unmap(ht, entry, flags, old_pte, NULL); + htable_release(ht); + } + return; + } + while (vaddr < eaddr) { old_pte = htable_walk(hat, &ht, &vaddr, eaddr); if (ht == NULL) @@ -2246,7 +2222,6 @@ hat_unload_callback( */ entry = htable_va2entry(vaddr, ht); hat_pte_unmap(ht, entry, flags, old_pte, NULL); - ASSERT(ht->ht_level <= mmu.max_page_level); vaddr += LEVEL_SIZE(ht->ht_level); contig_va = vaddr; @@ -2286,7 +2261,7 @@ hat_sync(hat_t *hat, caddr_t addr, size_t len, uint_t flags) ASSERT(!IN_VA_HOLE(vaddr)); ASSERT(IS_PAGEALIGNED(vaddr)); ASSERT(IS_PAGEALIGNED(eaddr)); - ASSERT(hat == kas.a_hat || eaddr <= kernelbase); + ASSERT(hat == kas.a_hat || eaddr <= _userlimit); for (; vaddr < eaddr; vaddr += LEVEL_SIZE(ht->ht_level)) { try_again: @@ -2295,7 +2270,7 @@ try_again: break; entry = htable_va2entry(vaddr, ht); - if (PTE_GET(pte, PT_NOSYNC) || + if (PTE_GET(pte, PT_SOFTWARE) >= PT_NOSYNC || PTE_GET(pte, PT_REF | PT_MOD) == 0) continue; @@ -2313,7 +2288,7 @@ try_again: x86_hm_exit(pp); goto try_again; } - if (PTE_GET(pte, PT_NOSYNC) || + if (PTE_GET(pte, PT_SOFTWARE) >= PT_NOSYNC || PTE_GET(pte, PT_REF | PT_MOD) == 0) { x86_hm_exit(pp); continue; @@ -2366,12 +2341,12 @@ hat_getattr(hat_t *hat, caddr_t addr, uint_t *attr) htable_t *ht = NULL; x86pte_t pte; - ASSERT(hat == kas.a_hat || vaddr < kernelbase); + ASSERT(hat == kas.a_hat || vaddr <= _userlimit); if (IN_VA_HOLE(vaddr)) return ((uint_t)-1); - ht = htable_getpte(hat, vaddr, NULL, &pte, MAX_PAGE_LEVEL); + ht = htable_getpte(hat, vaddr, NULL, &pte, mmu.max_page_level); if (ht == NULL) return ((uint_t)-1); @@ -2387,7 +2362,7 @@ hat_getattr(hat_t *hat, caddr_t addr, uint_t *attr) *attr |= PROT_USER; if (!PTE_GET(pte, mmu.pt_nx)) *attr |= PROT_EXEC; - if (PTE_GET(pte, PT_NOSYNC)) + if (PTE_GET(pte, PT_SOFTWARE) >= PT_NOSYNC) *attr |= HAT_NOSYNC; htable_release(ht); return (0); @@ -2419,7 +2394,7 @@ try_again: oldpte = htable_walk(hat, &ht, &vaddr, eaddr); if (ht == NULL) break; - if (PTE_GET(oldpte, PT_NOCONSIST)) + if (PTE_GET(oldpte, PT_SOFTWARE) >= PT_NOCONSIST) continue; pp = page_numtopp_nolock(PTE2PFN(oldpte, ht->ht_level)); @@ -2437,7 +2412,8 @@ try_again: !PTE_GET(oldpte, PT_WRITABLE)) newpte |= PT_WRITABLE; - if ((attr & HAT_NOSYNC) && !PTE_GET(oldpte, PT_NOSYNC)) + if ((attr & HAT_NOSYNC) && + PTE_GET(oldpte, PT_SOFTWARE) < PT_NOSYNC) newpte |= PT_NOSYNC; if ((attr & PROT_EXEC) && PTE_GET(oldpte, mmu.pt_nx)) @@ -2449,8 +2425,9 @@ try_again: PTE_GET(oldpte, PT_WRITABLE)) newpte &= ~PT_WRITABLE; - if (!(attr & HAT_NOSYNC) && PTE_GET(oldpte, PT_NOSYNC)) - newpte &= ~PT_NOSYNC; + if (!(attr & HAT_NOSYNC) && + PTE_GET(oldpte, PT_SOFTWARE) >= PT_NOSYNC) + newpte &= ~PT_SOFTWARE; if (!(attr & PROT_EXEC) && !PTE_GET(oldpte, mmu.pt_nx)) newpte |= mmu.pt_nx; @@ -2460,14 +2437,22 @@ try_again: if ((attr & PROT_WRITE) && PTE_GET(oldpte, PT_WRITABLE)) newpte &= ~PT_WRITABLE; - if ((attr & HAT_NOSYNC) && PTE_GET(oldpte, PT_NOSYNC)) - newpte &= ~PT_NOSYNC; + if ((attr & HAT_NOSYNC) && + PTE_GET(oldpte, PT_SOFTWARE) >= PT_NOSYNC) + newpte &= ~PT_SOFTWARE; if ((attr & PROT_EXEC) && !PTE_GET(oldpte, mmu.pt_nx)) newpte |= mmu.pt_nx; } /* + * Ensure NOSYNC/NOCONSIST mappings have REF and MOD set. + * x86pte_set() depends on this. + */ + if (PTE_GET(newpte, PT_SOFTWARE) >= PT_NOSYNC) + newpte |= PT_REF | PT_MOD; + + /* * what about PROT_READ or others? this code only handles: * EXEC, WRITE, NOSYNC */ @@ -2495,38 +2480,31 @@ try_again: void hat_setattr(hat_t *hat, caddr_t addr, size_t len, uint_t attr) { - ASSERT(hat == kas.a_hat || (uintptr_t)addr + len <= kernelbase); + ASSERT(hat == kas.a_hat || (uintptr_t)addr + len <= _userlimit); hat_updateattr(hat, addr, len, attr, HAT_SET_ATTR); } void hat_clrattr(hat_t *hat, caddr_t addr, size_t len, uint_t attr) { - ASSERT(hat == kas.a_hat || (uintptr_t)addr + len <= kernelbase); + ASSERT(hat == kas.a_hat || (uintptr_t)addr + len <= _userlimit); hat_updateattr(hat, addr, len, attr, HAT_CLR_ATTR); } void hat_chgattr(hat_t *hat, caddr_t addr, size_t len, uint_t attr) { - ASSERT(hat == kas.a_hat || (uintptr_t)addr + len <= kernelbase); + ASSERT(hat == kas.a_hat || (uintptr_t)addr + len <= _userlimit); hat_updateattr(hat, addr, len, attr, HAT_LOAD_ATTR); } void hat_chgprot(hat_t *hat, caddr_t addr, size_t len, uint_t vprot) { - ASSERT(hat == kas.a_hat || (uintptr_t)addr + len <= kernelbase); + ASSERT(hat == kas.a_hat || (uintptr_t)addr + len <= _userlimit); hat_updateattr(hat, addr, len, vprot & HAT_PROT_MASK, HAT_LOAD_ATTR); } -/*ARGSUSED*/ -void -hat_chgattr_pagedir(hat_t *hat, caddr_t addr, size_t len, uint_t attr) -{ - panic("hat_chgattr_pgdir() not supported - used by 80387 emulation"); -} - /* * size_t hat_getpagesize(hat, addr) * returns pagesize in bytes for <hat, addr>. returns -1 of there is @@ -2539,7 +2517,7 @@ hat_getpagesize(hat_t *hat, caddr_t addr) htable_t *ht; size_t pagesize; - ASSERT(hat == kas.a_hat || vaddr < kernelbase); + ASSERT(hat == kas.a_hat || vaddr <= _userlimit); if (IN_VA_HOLE(vaddr)) return (-1); ht = htable_getpage(hat, vaddr, NULL); @@ -2564,9 +2542,9 @@ hat_getpfnum(hat_t *hat, caddr_t addr) uint_t entry; pfn_t pfn = PFN_INVALID; - ASSERT(hat == kas.a_hat || vaddr < kernelbase); + ASSERT(hat == kas.a_hat || vaddr <= _userlimit); if (khat_running == 0) - panic("hat_getpfnum(): called too early\n"); + return (PFN_INVALID); if (IN_VA_HOLE(vaddr)) return (PFN_INVALID); @@ -2578,14 +2556,10 @@ hat_getpfnum(hat_t *hat, caddr_t addr) */ if (mmu.kmap_addr <= vaddr && vaddr < mmu.kmap_eaddr) { x86pte_t pte; - pgcnt_t pg_off; + pgcnt_t pg_index; - pg_off = mmu_btop(vaddr - mmu.kmap_addr); - if (mmu.pae_hat) { - ATOMIC_LOAD64(mmu.kmap_ptes + pg_off, pte); - } else { - pte = ((x86pte32_t *)mmu.kmap_ptes)[pg_off]; - } + pg_index = mmu_btop(vaddr - mmu.kmap_addr); + pte = GET_PTE(PT_INDEX_PTR(mmu.kmap_ptes, pg_index)); if (!PTE_ISVALID(pte)) return (PFN_INVALID); /*LINTED [use of constant 0 causes a silly lint warning] */ @@ -2623,7 +2597,6 @@ hat_getkpfnum(caddr_t addr) pfn_t pfn; int badcaller = 0; - if (khat_running == 0) panic("hat_getkpfnum(): called too early\n"); if ((uintptr_t)addr < kernelbase) @@ -2657,7 +2630,7 @@ hat_probe(hat_t *hat, caddr_t addr) htable_t *ht; pgcnt_t pg_off; - ASSERT(hat == kas.a_hat || vaddr < kernelbase); + ASSERT(hat == kas.a_hat || vaddr <= _userlimit); ASSERT(hat == kas.a_hat || AS_LOCK_HELD(hat->hat_as, &hat->hat_as->a_lock)); if (IN_VA_HOLE(vaddr)) @@ -2721,7 +2694,7 @@ hat_share( * We might be asked to share an empty DISM hat by as_dup() */ ASSERT(hat != kas.a_hat); - ASSERT(eaddr <= kernelbase); + ASSERT(eaddr <= _userlimit); if (!(ism_hat->hat_flags & HAT_SHARED)) { ASSERT(hat_get_mapped_size(ism_hat) == 0); return (0); @@ -2833,8 +2806,12 @@ hat_share( * XX64 -- can shm ever be written to swap? * if not we could use HAT_NOSYNC here. */ - hati_load_common(hat, vaddr, pp, prot, - HAT_LOAD, l, pfn); + while (hati_load_common(hat, vaddr, pp, prot, HAT_LOAD, + l, pfn) != 0) { + if (l == 0) + panic("hati_load_common() failure"); + --l; + } vaddr += LEVEL_SIZE(l); ism_addr += LEVEL_SIZE(l); @@ -2865,7 +2842,7 @@ hat_unshare(hat_t *hat, caddr_t addr, size_t len, uint_t ismszc) uint_t need_demaps = 0; ASSERT(hat != kas.a_hat); - ASSERT(eaddr <= kernelbase); + ASSERT(eaddr <= _userlimit); HATIN(hat_unshare, hat, addr, len); ASSERT(IS_PAGEALIGNED(vaddr)); ASSERT(IS_PAGEALIGNED(eaddr)); @@ -2873,9 +2850,9 @@ hat_unshare(hat_t *hat, caddr_t addr, size_t len, uint_t ismszc) /* * First go through and remove any shared pagetables. * - * Note that it's ok to delay the demap until the entire range is + * Note that it's ok to delay the TLB shootdown till the entire range is * finished, because if hat_pageunload() were to unload a shared - * pagetable page, its hat_demap() will do a global user TLB invalidate. + * pagetable page, its hat_tlb_inval() will do a global TLB invalidate. */ while (vaddr < eaddr) { ASSERT(!IN_VA_HOLE(vaddr)); @@ -2904,7 +2881,7 @@ hat_unshare(hat_t *hat, caddr_t addr, size_t len, uint_t ismszc) * we do just one CR3 reload. */ if (!(hat->hat_flags & HAT_FREEING) && need_demaps) - hat_demap(hat, DEMAP_ALL_ADDR); + hat_tlb_inval(hat, DEMAP_ALL_ADDR); /* * Now go back and clean up any unaligned mappings that @@ -3086,9 +3063,9 @@ hati_page_unmap(page_t *pp, htable_t *ht, uint_t entry) /* * Invalidate the PTE and remove the hment. */ - old_pte = x86pte_invalidate_pfn(ht, entry, pfn, NULL); + old_pte = x86pte_inval(ht, entry, 0, NULL); if (PTE2PFN(old_pte, ht->ht_level) != pfn) { - panic("x86pte_invalidate_pfn() failure found PTE = " FMT_PTE + panic("x86pte_inval() failure found PTE = " FMT_PTE " pfn being unmapped is %lx ht=0x%lx entry=0x%x", old_pte, pfn, (uintptr_t)ht, entry); } @@ -3103,7 +3080,7 @@ hati_page_unmap(page_t *pp, htable_t *ht, uint_t entry) /* * sync ref/mod bits to the page_t */ - if (PTE_GET(old_pte, PT_NOSYNC) == 0) + if (PTE_GET(old_pte, PT_SOFTWARE) < PT_NOSYNC) hati_sync_pte_to_page(pp, old_pte, ht->ht_level); /* @@ -3165,8 +3142,9 @@ next_size: /* * If not part of a larger page, we're done. */ - if (cur_pp->p_szc <= pg_szcd) + if (cur_pp->p_szc <= pg_szcd) { return (0); + } /* * Else check the next larger page size. @@ -3459,7 +3437,8 @@ try_again: /* * Sync the PTE */ - if (!(flags & HAT_SYNC_ZERORM) && PTE_GET(old, PT_NOSYNC) == 0) + if (!(flags & HAT_SYNC_ZERORM) && + PTE_GET(old, PT_SOFTWARE) <= PT_NOSYNC) hati_sync_pte_to_page(pp, old, ht->ht_level); /* @@ -3468,7 +3447,7 @@ try_again: if ((flags & HAT_SYNC_STOPON_MOD) && PP_ISMOD(save_pp) || (flags & HAT_SYNC_STOPON_REF) && PP_ISREF(save_pp)) { x86_hm_exit(pp); - return (save_pp->p_nrm & nrmbits); + goto done; } } x86_hm_exit(pp); @@ -3481,6 +3460,7 @@ try_again: goto next_size; } } +done: return (save_pp->p_nrm & nrmbits); } @@ -3576,28 +3556,25 @@ hat_setup(hat_t *hat, int flags) * the htable can't disappear. We also hat_devload() the page table into * kernel so that the PTE is quickly accessed. */ -void * -hat_mempte_kern_setup(caddr_t addr, void *pt) +hat_mempte_t +hat_mempte_setup(caddr_t addr) { uintptr_t va = (uintptr_t)addr; htable_t *ht; uint_t entry; x86pte_t oldpte; - caddr_t p = (caddr_t)pt; + hat_mempte_t p; + uint_t created = 0; ASSERT(IS_PAGEALIGNED(va)); ASSERT(!IN_VA_HOLE(va)); ht = htable_getpte(kas.a_hat, va, &entry, &oldpte, 0); if (ht == NULL) { - /* - * Note that we don't need a hat_reserves_exit() check - * for this htable_create(), since that'll be done by the - * hat_devload() just below. - */ ht = htable_create(kas.a_hat, va, 0, NULL); entry = htable_va2entry(va, ht); ASSERT(ht->ht_level == 0); oldpte = x86pte_get(ht, entry); + created = 1; } if (PTE_ISVALID(oldpte)) panic("hat_mempte_setup(): address already mapped" @@ -3609,65 +3586,47 @@ hat_mempte_kern_setup(caddr_t addr, void *pt) HTABLE_INC(ht->ht_valid_cnt); /* - * now we need to map the page holding the pagetable for va into - * the kernel's address space. - */ - hat_devload(kas.a_hat, p, MMU_PAGESIZE, ht->ht_pfn, - PROT_READ | PROT_WRITE | HAT_NOSYNC | HAT_UNORDERED_OK, - HAT_LOAD | HAT_LOAD_NOCONSIST); - - /* - * return the PTE address to the caller. + * return the PTE physical address to the caller. */ htable_release(ht); - p += entry << mmu.pte_size_shift; - return ((void *)p); -} - -/* - * Prepare for a CPU private mapping for the given address. - */ -void * -hat_mempte_setup(caddr_t addr) -{ - x86pte_t *p; - - p = vmem_alloc(heap_arena, MMU_PAGESIZE, VM_SLEEP); - return (hat_mempte_kern_setup(addr, p)); + p = PT_INDEX_PHYSADDR(pfn_to_pa(ht->ht_pfn), entry); + if (created) + hati_reserves_exit(0); + return (p); } /* * Release a CPU private mapping for the given address. * We decrement the htable valid count so it might be destroyed. */ +/*ARGSUSED1*/ void -hat_mempte_release(caddr_t addr, void *pteptr) +hat_mempte_release(caddr_t addr, hat_mempte_t pte_pa) { htable_t *ht; - uintptr_t va = ALIGN2PAGE(pteptr); /* - * first invalidate any left over mapping and decrement the - * htable's mapping count + * invalidate any left over mapping and decrement the htable valid count */ - if (mmu.pae_hat) - *(x86pte_t *)pteptr = 0; - else - *(x86pte32_t *)pteptr = 0; - mmu_tlbflush_entry(addr); + { + x86pte_t *pteptr; + + pteptr = x86pte_mapin(mmu_btop(pte_pa), + (pte_pa & MMU_PAGEOFFSET) >> mmu.pte_size_shift, NULL); + if (mmu.pae_hat) + *pteptr = 0; + else + *(x86pte32_t *)pteptr = 0; + mmu_tlbflush_entry(addr); + x86pte_mapout(); + } + ht = htable_getpte(kas.a_hat, ALIGN2PAGE(addr), NULL, NULL, 0); if (ht == NULL) panic("hat_mempte_release(): invalid address"); ASSERT(ht->ht_level == 0); HTABLE_DEC(ht->ht_valid_cnt); htable_release(ht); - - /* - * now blow away the kernel mapping to the page table page - * XX64 -- see comment in hat_mempte_setup() - */ - hat_unload_callback(kas.a_hat, (caddr_t)va, MMU_PAGESIZE, - HAT_UNLOAD, NULL); } /* @@ -3676,11 +3635,11 @@ hat_mempte_release(caddr_t addr, void *pteptr) */ void hat_mempte_remap( - pfn_t pfn, - caddr_t addr, - void *pteptr, - uint_t attr, - uint_t flags) + pfn_t pfn, + caddr_t addr, + hat_mempte_t pte_pa, + uint_t attr, + uint_t flags) { uintptr_t va = (uintptr_t)addr; x86pte_t pte; @@ -3699,14 +3658,22 @@ hat_mempte_remap( ASSERT(ht != NULL); ASSERT(ht->ht_level == 0); ASSERT(ht->ht_valid_cnt > 0); + ASSERT(ht->ht_pfn == mmu_btop(pte_pa)); htable_release(ht); #endif pte = hati_mkpte(pfn, attr, 0, flags); - if (mmu.pae_hat) - *(x86pte_t *)pteptr = pte; - else - *(x86pte32_t *)pteptr = (x86pte32_t)pte; - mmu_tlbflush_entry(addr); + { + x86pte_t *pteptr; + + pteptr = x86pte_mapin(mmu_btop(pte_pa), + (pte_pa & MMU_PAGEOFFSET) >> mmu.pte_size_shift, NULL); + if (mmu.pae_hat) + *(x86pte_t *)pteptr = pte; + else + *(x86pte32_t *)pteptr = (x86pte32_t)pte; + mmu_tlbflush_entry(addr); + x86pte_mapout(); + } } @@ -3728,64 +3695,31 @@ hat_exit(hat_t *hat) mutex_exit(&hat->hat_mutex); } - /* - * Used by hat_kern_setup() to create initial kernel HAT mappings from - * the boot loader's mappings. - * - * - size is either PAGESIZE or some multiple of a level one pagesize - * - there may not be page_t's for every pfn. (ie. the nucleus pages) - * - pfn's are continguous for the given va range (va to va + size * cnt) + * HAT part of cpu initialization. */ void -hati_kern_setup_load( - uintptr_t va, /* starting va of range to map */ - size_t size, /* either PAGESIZE or multiple of large page size */ - pfn_t pfn, /* starting PFN */ - pgcnt_t cnt, /* number of mappings, (cnt * size) == total size */ - uint_t prot) /* protections (PROT_READ, PROT_WRITE, PROT_EXEC) */ +hat_cpu_online(struct cpu *cpup) { - level_t level = (size == MMU_PAGESIZE ? 0 : 1); - size_t bytes = size * cnt; - size_t pgsize = LEVEL_SIZE(level); - page_t *pp; - uint_t flags = HAT_LOAD; - - /* - * We're only going to throw away mappings below kernelbase or in - * boot's special double-mapping region, so set noconsist to avoid - * using hments - */ - if (BOOT_VA(va)) - flags |= HAT_LOAD_NOCONSIST; - - prot |= HAT_STORECACHING_OK; - while (bytes != 0) { - ASSERT(bytes >= pgsize); - - pp = NULL; - if (pf_is_memory(pfn) && !BOOT_VA(va) && level == 0) - pp = page_numtopp_nolock(pfn); - - hati_load_common(kas.a_hat, va, pp, prot, flags, level, pfn); - - va += pgsize; - pfn += mmu_btop(pgsize); - bytes -= pgsize; + if (cpup != CPU) { + x86pte_cpu_init(cpup); + hat_vlp_setup(cpup); } + CPUSET_ATOMIC_ADD(khat_cpuset, cpup->cpu_id); } /* - * HAT part of cpu intialization. + * HAT part of cpu deletion. + * (currently, we only call this after the cpu is safely passivated.) */ void -hat_cpu_online(struct cpu *cpup) +hat_cpu_offline(struct cpu *cpup) { - if (cpup != CPU) { - x86pte_cpu_init(cpup, NULL); - hat_vlp_setup(cpup); - } - CPUSET_ATOMIC_ADD(khat_cpuset, cpup->cpu_id); + ASSERT(cpup != CPU); + + CPUSET_ATOMIC_DEL(khat_cpuset, cpup->cpu_id); + x86pte_cpu_fini(cpup); + hat_vlp_teardown(cpup); } /* @@ -3803,7 +3737,7 @@ clear_boot_mappings(uintptr_t low, uintptr_t high) /* * On 1st CPU we can unload the prom mappings, basically we blow away - * all virtual mappings under kernelbase. + * all virtual mappings under _userlimit. */ while (vaddr < high) { pte = htable_walk(kas.a_hat, &ht, &vaddr, high); @@ -3818,7 +3752,7 @@ clear_boot_mappings(uintptr_t low, uintptr_t high) /* * Unload the mapping from the page tables. */ - (void) x86pte_set(ht, entry, 0, NULL); + (void) x86pte_inval(ht, entry, 0, NULL); ASSERT(ht->ht_valid_cnt > 0); HTABLE_DEC(ht->ht_valid_cnt); PGCNT_DEC(ht->ht_hat, ht->ht_level); @@ -3827,71 +3761,6 @@ clear_boot_mappings(uintptr_t low, uintptr_t high) } if (ht) htable_release(ht); - - /* - * cross call for a complete invalidate. - */ - hat_demap(kas.a_hat, DEMAP_ALL_ADDR); -} - -/* - * Initialize a special area in the kernel that always holds some PTEs for - * faster performance. This always holds segmap's PTEs. - * In the 32 bit kernel this maps the kernel heap too. - */ -void -hat_kmap_init(uintptr_t base, size_t len) -{ - uintptr_t map_addr; /* base rounded down to large page size */ - uintptr_t map_eaddr; /* base + len rounded up */ - size_t map_len; - caddr_t ptes; /* mapping area in kernel as for ptes */ - size_t window_size; /* size of mapping area for ptes */ - ulong_t htable_cnt; /* # of page tables to cover map_len */ - ulong_t i; - htable_t *ht; - - /* - * we have to map in an area that matches an entire page table - */ - map_addr = base & LEVEL_MASK(1); - map_eaddr = (base + len + LEVEL_SIZE(1) - 1) & LEVEL_MASK(1); - map_len = map_eaddr - map_addr; - window_size = mmu_btop(map_len) * mmu.pte_size; - htable_cnt = mmu_btop(map_len) / mmu.ptes_per_table; - - /* - * allocate vmem for the kmap_ptes - */ - ptes = vmem_xalloc(heap_arena, window_size, MMU_PAGESIZE, 0, - 0, NULL, NULL, VM_SLEEP); - mmu.kmap_htables = - kmem_alloc(htable_cnt * sizeof (htable_t *), KM_SLEEP); - - /* - * Map the page tables that cover kmap into the allocated range. - * Note we don't ever htable_release() the kmap page tables - they - * can't ever be stolen, freed, etc. - */ - for (i = 0; i < htable_cnt; ++i) { - ht = htable_create(kas.a_hat, map_addr + i * LEVEL_SIZE(1), - 0, NULL); - mmu.kmap_htables[i] = ht; - - hat_devload(kas.a_hat, ptes + i * MMU_PAGESIZE, MMU_PAGESIZE, - ht->ht_pfn, - PROT_READ | PROT_WRITE | HAT_NOSYNC | HAT_UNORDERED_OK, - HAT_LOAD | HAT_LOAD_NOCONSIST); - - } - - /* - * set information in mmu to activate handling of kmap - */ - mmu.kmap_addr = base; - mmu.kmap_eaddr = base + len; - mmu.kmap_ptes = - (x86pte_t *)(ptes + mmu.pte_size * mmu_btop(base - map_addr)); } /* @@ -3909,11 +3778,12 @@ hati_update_pte(htable_t *ht, uint_t entry, x86pte_t expected, x86pte_t new) uint_t rm = 0; x86pte_t replaced; - if (!PTE_GET(expected, PT_NOSYNC | PT_NOCONSIST) && + if (PTE_GET(expected, PT_SOFTWARE) < PT_NOSYNC && PTE_GET(expected, PT_MOD | PT_REF) && (PTE_GET(new, PT_NOSYNC) || !PTE_GET(new, PT_WRITABLE) || !PTE_GET(new, PT_MOD | PT_REF))) { + ASSERT(!pfn_is_foreign(PTE2PFN(expected, ht->ht_level))); pp = page_numtopp_nolock(PTE2PFN(expected, ht->ht_level)); ASSERT(pp != NULL); if (PTE_GET(expected, PT_MOD)) @@ -4022,11 +3892,7 @@ hat_kpm_mapout(struct page *pp, struct kpme *kpme, caddr_t vaddr) caddr_t hat_kpm_pfn2va(pfn_t pfn) { - uintptr_t vaddr; - - ASSERT(kpm_enable); - - vaddr = (uintptr_t)kpm_vbase + mmu_ptob(pfn); + uintptr_t vaddr = (uintptr_t)kpm_vbase + mmu_ptob(pfn); return ((caddr_t)vaddr); } diff --git a/usr/src/uts/i86pc/vm/hat_i86.h b/usr/src/uts/i86pc/vm/hat_i86.h index 9194efa660..f88d89b477 100644 --- a/usr/src/uts/i86pc/vm/hat_i86.h +++ b/usr/src/uts/i86pc/vm/hat_i86.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -80,7 +79,6 @@ extern "C" { */ struct hat { kmutex_t hat_mutex; - kmutex_t hat_switch_mutex; struct as *hat_as; uint_t hat_stats; pgcnt_t hat_pages_mapped[MAX_PAGE_LEVEL + 1]; @@ -173,10 +171,11 @@ extern kcondvar_t hat_list_cv; * * Used by ppcopy(), page_zero(), the memscrubber, and the kernel debugger. */ -extern void *hat_mempte_kern_setup(caddr_t addr, void *); -extern void *hat_mempte_setup(caddr_t addr); -extern void hat_mempte_remap(pfn_t, caddr_t, void *, uint_t attr, uint_t flags); -extern void hat_mempte_release(caddr_t addr, void *); +typedef paddr_t hat_mempte_t; /* phys addr of PTE */ +extern hat_mempte_t hat_mempte_setup(caddr_t addr); +extern void hat_mempte_remap(pfn_t, caddr_t, hat_mempte_t, + uint_t attr, uint_t flags); +extern void hat_mempte_release(caddr_t addr, hat_mempte_t); /* * interfaces to manage which thread has access to htable and hment reserves @@ -189,9 +188,10 @@ extern kthread_t *hat_reserves_thread; * initialization stuff needed by by startup, mp_startup... */ extern void hat_cpu_online(struct cpu *); +extern void hat_cpu_offline(struct cpu *); extern void setup_vaddr_for_ppcopy(struct cpu *); +extern void teardown_vaddr_for_ppcopy(struct cpu *); extern void clear_boot_mappings(uintptr_t, uintptr_t); -extern int hat_boot_probe(uintptr_t *va, size_t *len, pfn_t *pfn, uint_t *prot); /* * magic value to indicate that all TLB entries should be demapped. @@ -206,26 +206,26 @@ extern void halt(char *fmt); /* * x86 specific routines for use online in setup or i86pc/vm files */ -extern void hat_kern_alloc(void); -extern void hati_kern_setup_load(uintptr_t, size_t, pfn_t, pgcnt_t, uint_t); -extern void hat_demap(struct hat *hat, uintptr_t va); +extern void hat_kern_alloc(caddr_t segmap_base, size_t segmap_size, + caddr_t ekernelheap); +extern void hat_kern_setup(void); +extern void hat_tlb_inval(struct hat *hat, uintptr_t va); extern void hat_pte_unmap(htable_t *ht, uint_t entry, uint_t flags, x86pte_t old_pte, void *pte_ptr); extern void hat_init_finish(void); -extern void hat_kmap_init(uintptr_t base, size_t len); extern caddr_t hat_kpm_pfn2va(pfn_t pfn); extern pfn_t hat_kpm_va2pfn(caddr_t); extern page_t *hat_kpm_vaddr2page(caddr_t); extern uintptr_t hat_kernelbase(uintptr_t); +extern void hat_kmap_init(uintptr_t base, size_t len); -extern pfn_t hat_boot_remap(uintptr_t, pfn_t); -extern void hat_boot_demap(uintptr_t); extern hment_t *hati_page_unmap(page_t *pp, htable_t *ht, uint_t entry); /* * Hat switch function invoked to load a new context into %cr3 */ extern void hat_switch(struct hat *hat); +#define pfn_is_foreign(pfn) __lintzero #endif /* _KERNEL */ diff --git a/usr/src/uts/i86pc/vm/hat_kdi.c b/usr/src/uts/i86pc/vm/hat_kdi.c index acdc2ddbb9..3273bd746c 100644 --- a/usr/src/uts/i86pc/vm/hat_kdi.c +++ b/usr/src/uts/i86pc/vm/hat_kdi.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -43,39 +42,26 @@ #include <sys/cmn_err.h> #include <vm/seg_kmem.h> #include <vm/hat_i86.h> +#include <sys/bootinfo.h> +#include <vm/kboot_mmu.h> #include <sys/machsystm.h> /* * The debugger needs direct access to the PTE of one page table entry * in order to implement vtop and physical read/writes */ -extern uintptr_t ptable_va; static uintptr_t hat_kdi_page = 0; /* vaddr for phsical page accesses */ static x86pte_t *hat_kdi_pte = NULL; /* vaddr of pte for hat_kdi_page */ +static uint_t use_kbm = 1; uint_t hat_kdi_use_pae; /* if 0, use x86pte32_t for pte type */ /* - * Allocate virtual page to use for kernel debugger accesses to physical memory. - * This is done very early in boot - before vmem allocator is available, so - * we use a special hand picked address. (blech) The address is one page - * above where the hat will put pages for pagetables -- see ptable_alloc() -- - * and is outside of the kernel's address space. - * - * We'll pick a new VA after the kernel's hat has been initialized. + * Get the address for remapping physical pages during boot */ void hat_boot_kdi_init(void) { - - /* - * The 1st ptable_va page is for the HAT, we use the 2nd. - */ - hat_kdi_page = ptable_va + MMU_PAGESIZE; -#if defined(__amd64) - hat_kdi_use_pae = 1; -#elif defined(__i386) - hat_kdi_use_pae = 0; -#endif + hat_kdi_page = (uintptr_t)kbm_push(0); /* first call gets address... */ } /* @@ -86,6 +72,7 @@ hat_boot_kdi_init(void) void hat_kdi_init(void) { + /*LINTED:set but not used in function*/ htable_t *ht; /* @@ -95,6 +82,7 @@ hat_kdi_init(void) hat_kdi_use_pae = mmu.pae_hat; hat_kdi_page = (uintptr_t)vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP); ht = htable_create(kas.a_hat, hat_kdi_page, 0, NULL); + use_kbm = 0; /* * Get an address at which to put the pagetable and devload it. @@ -104,12 +92,14 @@ hat_kdi_init(void) hat_devload(kas.a_hat, (caddr_t)hat_kdi_pte, MMU_PAGESIZE, ht->ht_pfn, PROT_READ | PROT_WRITE | HAT_NOSYNC | HAT_UNORDERED_OK, HAT_LOAD | HAT_LOAD_NOCONSIST); - hat_kdi_pte = (x86pte_t *)((uintptr_t)hat_kdi_pte + - (htable_va2entry(hat_kdi_page, ht) << mmu.pte_size_shift)); + hat_kdi_pte = + PT_INDEX_PTR(hat_kdi_pte, htable_va2entry(hat_kdi_page, ht)); HTABLE_INC(ht->ht_valid_cnt); htable_release(ht); } +#define kdi_mtop(m) (m) +#define kdi_ptom(p) (p) /*ARGSUSED*/ int @@ -128,13 +118,13 @@ kdi_vtop(uintptr_t va, uint64_t *pap) * the boot loader's pagetables. */ if (!khat_running) { - if (hat_boot_probe(&vaddr, &len, &pfn, &prot) == 0) + if (kbm_probe(&vaddr, &len, &pfn, &prot) == 0) return (ENOENT); if (vaddr > va) return (ENOENT); if (vaddr < va) pfn += mmu_btop(va - vaddr); - *pap = (uint64_t)mmu_ptob(pfn) + (vaddr & MMU_PAGEOFFSET); + *pap = pfn_to_pa(pfn) + (vaddr & MMU_PAGEOFFSET); return (0); } @@ -153,10 +143,10 @@ kdi_vtop(uintptr_t va, uint64_t *pap) return (ENOENT); if (level > 0 && level <= mmu.max_page_level && (pte & PT_PAGESIZE)) { - *pap = pte & PT_PADDR_LGPG; + *pap = kdi_mtop(pte & PT_PADDR_LGPG); break; } else { - *pap = pte & PT_PADDR; + *pap = kdi_mtop(pte & PT_PADDR); if (level == 0) break; } @@ -189,7 +179,7 @@ kdi_prw(caddr_t buf, size_t nbytes, uint64_t pa, size_t *ncopiedp, int doread) pgoff = pa & MMU_PAGEOFFSET; sz = MIN(nbytes, MMU_PAGESIZE - pgoff); va = (caddr_t)hat_kdi_page + pgoff; - pte = MAKEPTE(btop(pa), 0); + pte = mmu_ptob(mmu_btop(pa)) | PT_VALID; if (doread) { from = va; to = buf; @@ -202,8 +192,8 @@ kdi_prw(caddr_t buf, size_t nbytes, uint64_t pa, size_t *ncopiedp, int doread) /* * map the physical page */ - if (hat_kdi_pte == NULL) - (void) hat_boot_remap(hat_kdi_page, btop(pa)); + if (use_kbm) + (void) kbm_push(pa); else if (hat_kdi_use_pae) *hat_kdi_pte = pte; else @@ -215,8 +205,8 @@ kdi_prw(caddr_t buf, size_t nbytes, uint64_t pa, size_t *ncopiedp, int doread) /* * erase the mapping */ - if (hat_kdi_pte == NULL) - hat_boot_demap(hat_kdi_page); + if (use_kbm) + kbm_pop(); else if (hat_kdi_use_pae) *hat_kdi_pte = 0; else @@ -257,7 +247,7 @@ kdi_pwrite(caddr_t buf, size_t nbytes, uint64_t addr, size_t *ncopiedp) size_t kdi_range_is_nontoxic(uintptr_t va, size_t sz, int write) { -#ifdef __amd64 +#if defined(__amd64) extern uintptr_t toxic_addr; extern size_t toxic_size; @@ -277,7 +267,7 @@ kdi_range_is_nontoxic(uintptr_t va, size_t sz, int write) return (sz); -#else +#elif defined(__i386) extern void *device_arena_contains(void *, size_t, size_t *); uintptr_t v; @@ -289,10 +279,5 @@ kdi_range_is_nontoxic(uintptr_t va, size_t sz, int write) else return (v - va); -#endif -} - -void -hat_kdi_fini(void) -{ +#endif /* __i386 */ } diff --git a/usr/src/uts/i86pc/vm/hat_pte.h b/usr/src/uts/i86pc/vm/hat_pte.h index 6230d7c93c..9bd8c31c48 100644 --- a/usr/src/uts/i86pc/vm/hat_pte.h +++ b/usr/src/uts/i86pc/vm/hat_pte.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,68 +32,8 @@ extern "C" { #endif - #include <sys/types.h> - -/* - * Defines for the bits in X86 and AMD64 Page Tables - * - * Notes: - * - * Largepages and PAT bits: - * - * bit 7 at level 0 is the PAT bit - * bit 7 above level 0 is the Pagesize bit (set for large page) - * bit 12 (when a large page) is the PAT bit - * - * In Solaris the PAT/PWT/PCD values are set up so that: - * - * PAT & PWT -> Write Protected - * PAT & PCD -> Write Combining - * PAT by itself (PWT == 0 && PCD == 0) yields uncacheable (same as PCD == 1) - * - * - * Permission bits: - * - * - PT_USER must be set in all levels for user pages - * - PT_WRITE must be set in all levels for user writable pages - * - PT_NX applies if set at any level - * - * For these, we use the "allow" settings in all tables above level 0 and only - * ever disable things in PTEs. - * - * The use of PT_GLOBAL and PT_NX depend on being enabled in processor - * control registers. Hence, we use a variable to reference these bit - * masks. During hat_kern_setup() if the feature isn't enabled we - * clear out the variables. - */ -#define PT_VALID (0x001) /* a valid translation is present */ -#define PT_WRITABLE (0x002) /* the page is writable */ -#define PT_USER (0x004) /* the page is accessible by user mode */ -#define PT_WRITETHRU (0x008) /* write back caching is disabled (non-PAT) */ -#define PT_NOCACHE (0x010) /* page is not cacheable (non-PAT) */ -#define PT_REF (0x020) /* page was referenced */ -#define PT_MOD (0x040) /* page was modified */ -#define PT_PAGESIZE (0x080) /* above level 0, indicates a large page */ -#define PT_PAT_4K (0x080) /* at level 0, used for write combining */ -#define PT_GLOBAL (0x100) /* the mapping is global */ -#define PT_SOFTWARE (0xe00) /* available for software */ - -#define PT_PAT_LARGE (0x1000) /* PAT bit for large pages */ - -#define PT_PTPBITS (PT_VALID | PT_USER | PT_WRITABLE | PT_REF) -#define PT_FLAGBITS (0xfff) /* for masking off flag bits */ - -/* - * The software bits are used by the HAT to track attributes. - * - * PT_NOSYNC - The PT_REF/PT_MOD bits are not sync'd to page_t. - * The hat will install them as always set. - * - * PT_NOCONSIST - There is no entry for this hment for this mapping. - */ -#define PT_NOSYNC (0x200) /* PTE was created with HAT_NOSYNC */ -#define PT_NOCONSIST (0x400) /* PTE was created with HAT_LOAD_NOCONSIST */ +#include <sys/mach_mmu.h> /* * macros to get/set/clear the PTE fields @@ -127,27 +66,21 @@ extern "C" { /* * Shorthand for converting a PTE to it's pfn. */ -#define PTE2PFN(p, l) \ +#define PTE2MFN(p, l) \ mmu_btop(PTE_GET((p), PTE_IS_LGPG((p), (l)) ? PT_PADDR_LGPG : PT_PADDR)) +#define PTE2PFN(p, l) PTE2MFN(p, l) -/* - * The software extraction for a single Page Table Entry will always - * be a 64 bit unsigned int. If running a non-PAE hat, the page table - * access routines know to extend/shorten it to 32 bits. - */ -typedef uint64_t x86pte_t; -typedef uint32_t x86pte32_t; #define PT_NX (0x8000000000000000ull) -#define PT_PADDR (0x00fffffffffff000ull) -#define PT_PADDR_LGPG (0x00ffffffffffe000ull) /* phys addr for large pages */ +#define PT_PADDR (0x000ffffffffff000ull) +#define PT_PADDR_LGPG (0x000fffffffffe000ull) /* phys addr for large pages */ /* * Macros to create a PTP or PTE from the pfn and level */ #define MAKEPTP(pfn, l) \ - (((x86pte_t)(pfn) << MMU_PAGESHIFT) | mmu.ptp_bits[(l) + 1]) + (pfn_to_pa(pfn) | mmu.ptp_bits[(l) + 1]) #define MAKEPTE(pfn, l) \ - (((x86pte_t)(pfn) << MMU_PAGESHIFT) | mmu.pte_bits[l]) + (pfn_to_pa(pfn) | mmu.pte_bits[l]) /* * The idea of "level" refers to the level where the page table is used in the @@ -174,7 +107,7 @@ typedef uint32_t x86pte32_t; */ #define MAX_NUM_LEVEL 4 #define MAX_PAGE_LEVEL 1 /* for now.. sigh */ -typedef int16_t level_t; +typedef int8_t level_t; #define LEVEL_SHIFT(l) (mmu.level_shift[l]) #define LEVEL_SIZE(l) (mmu.level_size[l]) #define LEVEL_OFFSET(l) (mmu.level_offset[l]) @@ -192,7 +125,7 @@ typedef int16_t level_t; /* * The CR3 register holds the physical address of the top level page table. */ -#define MAKECR3(pfn) mmu_ptob(pfn) +#define MAKECR3(pfn) mmu_ptob(pfn) /* * HAT/MMU parameters that depend on kernel mode and/or processor type @@ -229,6 +162,14 @@ struct hat_mmu_info { x86pte_t pte_bits[MAX_NUM_LEVEL]; /* bits set for leaf PTE */ /* + * A range of VA used to window pages in the i86pc/vm code. + * See PWIN_XXX macros. + */ + caddr_t pwin_base; + caddr_t pwin_pte_va; + paddr_t pwin_pte_pa; + + /* * The following tables are equivalent to PAGEXXXXX at different levels * in the page table hierarchy. */ @@ -236,12 +177,26 @@ struct hat_mmu_info { uintptr_t level_size[MAX_NUM_LEVEL]; /* PAGESIZE for given level */ uintptr_t level_offset[MAX_NUM_LEVEL]; /* PAGEOFFSET for given level */ uintptr_t level_mask[MAX_NUM_LEVEL]; /* PAGEMASK for given level */ - - uint_t tlb_entries[MAX_NUM_LEVEL]; /* tlb entries per pagesize */ }; #if defined(_KERNEL) + +/* + * Macros to access the HAT's private page windows. They're used for + * accessing pagetables, ppcopy() and page_zero(). + * The 1st two macros are used to get an index for the particular use. + * The next three give you: + * - the virtual address of the window + * - the virtual address of the pte that maps the window + * - the physical address of the pte that map the window + */ +#define PWIN_TABLE(cpuid) ((cpuid) * 2) +#define PWIN_SRC(cpuid) ((cpuid) * 2 + 1) /* for x86pte_copy() */ +#define PWIN_VA(x) (mmu.pwin_base + ((x) << MMU_PAGESHIFT)) +#define PWIN_PTE_VA(x) (mmu.pwin_pte_va + ((x) << mmu.pte_size_shift)) +#define PWIN_PTE_PA(x) (mmu.pwin_pte_pa + ((x) << mmu.pte_size_shift)) + /* * The concept of a VA hole exists in AMD64. This might need to be made * model specific eventually. @@ -256,23 +211,46 @@ struct hat_mmu_info { #define IN_VA_HOLE(va) (mmu.hole_start <= (va) && (va) < mmu.hole_end) #endif -#define FMT_PTE "%lx" -#define ATOMIC_LOAD64(ptr, pte) ((pte) = *(ptr)) +#define FMT_PTE "0x%lx" +#define GET_PTE(ptr) (*(x86pte_t *)(ptr)) +#define SET_PTE(ptr, pte) (*(x86pte_t *)(ptr) = pte) +#define CAS_PTE(ptr, x, y) cas64(ptr, x, y) #elif defined(__i386) -#ifdef lint #define IN_VA_HOLE(va) (__lintzero) -#else -#define IN_VA_HOLE(va) (0) -#endif -#define FMT_PTE "%llx" -#define ATOMIC_LOAD64(ptr, pte) (((pte) = *(ptr)), \ - ((pte) = cas64(ptr, pte, pte))) +#define FMT_PTE "0x%llx" + +/* on 32 bit kernels, 64 bit loads aren't atomic, use get_pte64() */ +extern x86pte_t get_pte64(x86pte_t *ptr); +#define GET_PTE(ptr) (mmu.pae_hat ? get_pte64(ptr) : *(x86pte32_t *)(ptr)) +#define SET_PTE(ptr, pte) \ + ((mmu.pae_hat ? ((x86pte32_t *)(ptr))[1] = (pte >> 32) : 0), \ + *(x86pte32_t *)(ptr) = pte) +#define CAS_PTE(ptr, x, y) \ + (mmu.pae_hat ? cas64(ptr, x, y) : \ + cas32((uint32_t *)(ptr), (uint32_t)(x), (uint32_t)(y))) #endif /* __i386 */ +/* + * Return a pointer to the pte entry at the given index within a page table. + */ +#define PT_INDEX_PTR(p, x) \ + ((x86pte_t *)((uintptr_t)(p) + ((x) << mmu.pte_size_shift))) + +/* + * Return the physical address of the pte entry at the given index within a + * page table. + */ +#define PT_INDEX_PHYSADDR(p, x) \ + ((paddr_t)(p) + ((x) << mmu.pte_size_shift)) + +/* + * From pfn to bytes, careful not to lose bits on PAE. + */ +#define pfn_to_pa(pfn) (mmu_ptob((paddr_t)(pfn))) extern struct hat_mmu_info mmu; diff --git a/usr/src/uts/i86pc/vm/htable.c b/usr/src/uts/i86pc/vm/htable.c index 3105ad9e27..bd1ac11630 100644 --- a/usr/src/uts/i86pc/vm/htable.c +++ b/usr/src/uts/i86pc/vm/htable.c @@ -18,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -45,6 +46,7 @@ #include <sys/promif.h> #include <sys/var.h> #include <sys/x86_archext.h> +#include <sys/archsystm.h> #include <sys/bootconf.h> #include <sys/dumphdr.h> #include <vm/seg_kmem.h> @@ -53,8 +55,12 @@ #include <vm/hat_i86.h> #include <sys/cmn_err.h> +#include <sys/bootinfo.h> +#include <vm/kboot_mmu.h> + +static void x86pte_zero(htable_t *dest, uint_t entry, uint_t count); + kmem_cache_t *htable_cache; -extern cpuset_t khat_cpuset; /* * The variable htable_reserve_amount, rather than HTABLE_RESERVE_AMOUNT, @@ -98,18 +104,12 @@ kmutex_t htable_mutex[NUM_HTABLE_MUTEX]; static void link_ptp(htable_t *higher, htable_t *new, uintptr_t vaddr); static void unlink_ptp(htable_t *higher, htable_t *old, uintptr_t vaddr); static void htable_free(htable_t *ht); -static x86pte_t *x86pte_access_pagetable(htable_t *ht); +static x86pte_t *x86pte_access_pagetable(htable_t *ht, uint_t index); static void x86pte_release_pagetable(htable_t *ht); static x86pte_t x86pte_cas(htable_t *ht, uint_t entry, x86pte_t old, x86pte_t new); /* - * Address used for kernel page tables. See ptable_alloc() below. - */ -uintptr_t ptable_va = 0; -size_t ptable_sz = 2 * MMU_PAGESIZE; - -/* * A counter to track if we are stealing or reaping htables. When non-zero * htable_free() will directly free htables (either to the reserve or kmem) * instead of putting them in a hat's htable cache. @@ -124,142 +124,54 @@ static uint32_t active_ptables = 0; /* * Allocate a memory page for a hardware page table. * - * The pages allocated for page tables are currently gotten in a hacked up - * way. It works for now, but really needs to be fixed up a bit. - * - * During boot: The boot loader controls physical memory allocation via - * boot_alloc(). To avoid conflict with vmem, we just do boot_alloc()s with - * addresses less than kernelbase. These addresses are ignored when we take - * over mappings from the boot loader. - * - * Post-boot: we currently use page_create_va() on the kvp with fake offsets, - * segments and virt address. This is pretty bogus, but was copied from the - * old hat_i86.c code. A better approach would be to have a custom - * page_get_physical() interface that can specify either mnode random or - * mnode local and takes a page from whatever color has the MOST available - - * this would have a minimal impact on page coloring. - * - * For now the htable pointer in ht is only used to compute a unique vnode - * offset for the page. + * A wrapper around page_get_physical(), with some extra checks. */ -static void -ptable_alloc(htable_t *ht) +static pfn_t +ptable_alloc(uintptr_t seed) { pfn_t pfn; page_t *pp; - u_offset_t offset; - static struct seg tmpseg; - static int first_time = 1; - /* - * Allocating the associated hardware page table is very different - * before boot has finished. We get a physical page to from boot - * w/o eating up any kernel address space. - */ - ht->ht_pfn = PFN_INVALID; + pfn = PFN_INVALID; atomic_add_32(&active_ptables, 1); - if (use_boot_reserve) { - ASSERT(ptable_va != 0); - - /* - * Allocate, then demap the ptable_va, so that we're - * sure there exist page table entries for the addresses - */ - if (first_time) { - first_time = 0; - if ((uintptr_t)BOP_ALLOC(bootops, (caddr_t)ptable_va, - ptable_sz, BO_NO_ALIGN) != ptable_va) - panic("BOP_ALLOC failed"); - - hat_boot_demap(ptable_va); - hat_boot_demap(ptable_va + MMU_PAGESIZE); - } - - pfn = ((uintptr_t)BOP_EALLOC(bootops, 0, MMU_PAGESIZE, - BO_NO_ALIGN, BOPF_X86_ALLOC_PHYS)) >> MMU_PAGESHIFT; - if (page_resv(1, KM_NOSLEEP) == 0) - panic("page_resv() failed in ptable alloc"); - - pp = page_numtopp_nolock(pfn); - ASSERT(pp != NULL); - if (pp->p_szc != 0) - page_boot_demote(pp); - pp = page_numtopp(pfn, SE_EXCL); - ASSERT(pp != NULL); - - } else { - /* - * Post boot get a page for the table. - * - * The first check is to see if there is memory in - * the system. If we drop to throttlefree, then fail - * the ptable_alloc() and let the stealing code kick in. - * Note that we have to do this test here, since the test in - * page_create_throttle() would let the NOSLEEP allocation - * go through and deplete the page reserves. - * - * The !NOMEMWAIT() lets pageout, fsflush, etc. skip this check. - */ - if (!NOMEMWAIT() && freemem <= throttlefree + 1) - return; + /* + * The first check is to see if there is memory in the system. If we + * drop to throttlefree, then fail the ptable_alloc() and let the + * stealing code kick in. Note that we have to do this test here, + * since the test in page_create_throttle() would let the NOSLEEP + * allocation go through and deplete the page reserves. + * + * The !NOMEMWAIT() lets pageout, fsflush, etc. skip this check. + */ + if (!NOMEMWAIT() && freemem <= throttlefree + 1) + return (PFN_INVALID); #ifdef DEBUG - /* - * This code makes htable_ steal() easier to test. By setting - * force_steal we force pagetable allocations to fall - * into the stealing code. Roughly 1 in ever "force_steal" - * page table allocations will fail. - */ - if (ht->ht_hat != kas.a_hat && force_steal > 1 && - ++ptable_cnt > force_steal) { - ptable_cnt = 0; - return; - } + /* + * This code makes htable_steal() easier to test. By setting + * force_steal we force pagetable allocations to fall + * into the stealing code. Roughly 1 in ever "force_steal" + * page table allocations will fail. + */ + if (proc_pageout != NULL && force_steal > 1 && + ++ptable_cnt > force_steal) { + ptable_cnt = 0; + return (PFN_INVALID); + } #endif /* DEBUG */ - /* - * This code is temporary, so don't review too critically. - * I'm awaiting a new phys page allocator from Kit -- Joe - * - * We need assign an offset for the page to call - * page_create_va. To avoid conflicts with other pages, - * we get creative with the offset. - * for 32 bits, we pic an offset > 4Gig - * for 64 bits, pic an offset somewhere in the VA hole. - */ - offset = (uintptr_t)ht - kernelbase; - offset <<= MMU_PAGESHIFT; -#if defined(__amd64) - offset += mmu.hole_start; /* something in VA hole */ -#else - offset += 1ULL << 40; /* something > 4 Gig */ -#endif - - if (page_resv(1, KM_NOSLEEP) == 0) - return; - -#ifdef DEBUG - pp = page_exists(&kvp, offset); - if (pp != NULL) - panic("ptable already exists %p", pp); -#endif - pp = page_create_va(&kvp, offset, MMU_PAGESIZE, - PG_EXCL | PG_NORELOC, &tmpseg, - (void *)((uintptr_t)ht << MMU_PAGESHIFT)); - if (pp == NULL) - return; - page_io_unlock(pp); - page_hashout(pp, NULL); - pfn = pp->p_pagenum; - } + pp = page_get_physical(seed); + if (pp == NULL) + return (PFN_INVALID); + pfn = pp->p_pagenum; page_downgrade(pp); ASSERT(PAGE_SHARED(pp)); if (pfn == PFN_INVALID) panic("ptable_alloc(): Invalid PFN!!"); - ht->ht_pfn = pfn; HATSTAT_INC(hs_ptable_allocs); + return (pfn); } /* @@ -267,10 +179,9 @@ ptable_alloc(htable_t *ht) * for ptable_alloc(). */ static void -ptable_free(htable_t *ht) +ptable_free(pfn_t pfn) { - pfn_t pfn = ht->ht_pfn; - page_t *pp; + page_t *pp = page_numtopp_nolock(pfn); /* * need to destroy the page used for the pagetable @@ -278,7 +189,6 @@ ptable_free(htable_t *ht) ASSERT(pfn != PFN_INVALID); HATSTAT_INC(hs_ptable_frees); atomic_add_32(&active_ptables, -1); - pp = page_numtopp_nolock(pfn); if (pp == NULL) panic("ptable_free(): no page for pfn!"); ASSERT(PAGE_SHARED(pp)); @@ -299,7 +209,6 @@ ptable_free(htable_t *ht) } page_free(pp, 1); page_unresv(1); - ht->ht_pfn = PFN_INVALID; } /* @@ -340,14 +249,12 @@ htable_get_reserve(void) } /* - * Allocate initial htables with page tables and put them on the kernel hat's - * cache list. + * Allocate initial htables and put them on the reserve list */ void htable_initial_reserve(uint_t count) { htable_t *ht; - hat_t *hat = kas.a_hat; count += HTABLE_RESERVE_AMOUNT; while (count > 0) { @@ -355,51 +262,23 @@ htable_initial_reserve(uint_t count) ASSERT(ht != NULL); ASSERT(use_boot_reserve); - ht->ht_hat = kas.a_hat; /* so htable_free() works */ - ht->ht_flags = 0; /* so x86pte_zero works */ - ptable_alloc(ht); - if (ht->ht_pfn == PFN_INVALID) - panic("ptable_alloc() failed"); - - x86pte_zero(ht, 0, mmu.ptes_per_table); - - ht->ht_next = hat->hat_ht_cached; - hat->hat_ht_cached = ht; + ht->ht_pfn = PFN_INVALID; + htable_put_reserve(ht); --count; } } /* * Readjust the reserves after a thread finishes using them. - * - * The first time this is called post boot, we'll also clear out the - * extra boot htables that were put in the kernel hat's cache list. */ void htable_adjust_reserve() { - static int first_time = 1; htable_t *ht; ASSERT(curthread != hat_reserves_thread); /* - * The first time this is called after we can steal, we free up the - * the kernel's cache htable list. It has lots of extra htable/page - * tables that were allocated for boot up. - */ - if (first_time) { - first_time = 0; - while ((ht = kas.a_hat->hat_ht_cached) != NULL) { - kas.a_hat->hat_ht_cached = ht->ht_next; - ASSERT(ht->ht_hat == kas.a_hat); - ptable_free(ht); - htable_put_reserve(ht); - } - return; - } - - /* * Free any excess htables in the reserve list */ while (htable_reserve_cnt > htable_reserve_amount) { @@ -586,7 +465,7 @@ htable_steal(uint_t cnt) * - unload and invalidate all PTEs */ for (e = 0, va = ht->ht_vaddr; - e < ht->ht_num_ptes && + e < HTABLE_NUM_PTES(ht) && ht->ht_valid_cnt > 0 && ht->ht_busy == 1 && ht->ht_lock_cnt == 0; @@ -637,7 +516,7 @@ htable_steal(uint_t cnt) /* * Break to outer loop to release the - * higher (ht_parent) pagtable. This + * higher (ht_parent) pagetable. This * spreads out the pain caused by * pagefaults. */ @@ -699,7 +578,7 @@ htable_reap(void *handle) } /* - * allocate an htable, stealing one or using the reserve if necessary + * Allocate an htable, stealing one or using the reserve if necessary */ static htable_t * htable_alloc( @@ -723,8 +602,7 @@ htable_alloc( /* * First reuse a cached htable from the hat_ht_cached field, this - * avoids unnecessary trips through kmem/page allocators. This is also - * what happens during use_boot_reserve. + * avoids unnecessary trips through kmem/page allocators. */ if (hat->hat_ht_cached != NULL && !is_bare) { hat_enter(hat); @@ -739,15 +617,12 @@ htable_alloc( } if (ht == NULL) { - ASSERT(!use_boot_reserve); /* * When allocating for hat_memload_arena, we use the reserve. * Also use reserves if we are in a panic(). */ - if (curthread == hat_reserves_thread || panicstr != NULL) { - ASSERT(panicstr != NULL || !is_bare); - ASSERT(panicstr != NULL || - curthread == hat_reserves_thread); + if (use_boot_reserve || curthread == hat_reserves_thread || + panicstr != NULL) { ht = htable_get_reserve(); } else { /* @@ -772,7 +647,7 @@ htable_alloc( */ if (ht != NULL && !is_bare) { ht->ht_hat = hat; - ptable_alloc(ht); + ht->ht_pfn = ptable_alloc((uintptr_t)ht); if (ht->ht_pfn == PFN_INVALID) { kmem_cache_free(htable_cache, ht); ht = NULL; @@ -796,8 +671,12 @@ htable_alloc( /* * If we stole for a bare htable, release the pagetable page. */ - if (ht != NULL && is_bare) - ptable_free(ht); + if (ht != NULL) { + if (is_bare) { + ptable_free(ht->ht_pfn); + ht->ht_pfn = PFN_INVALID; + } + } } /* @@ -833,13 +712,8 @@ htable_alloc( */ if (is_vlp) { ht->ht_flags |= HTABLE_VLP; - ht->ht_num_ptes = VLP_NUM_PTES; ASSERT(ht->ht_pfn == PFN_INVALID); need_to_zero = 0; - } else if (level == mmu.max_level) { - ht->ht_num_ptes = mmu.top_level_count; - } else { - ht->ht_num_ptes = mmu.ptes_per_table; } /* @@ -858,6 +732,7 @@ htable_alloc( */ if (need_to_zero) x86pte_zero(ht, 0, mmu.ptes_per_table); + return (ht); } @@ -890,14 +765,14 @@ htable_free(htable_t *ht) /* * If we have a hardware page table, free it. - * We don't free page tables that are accessed by sharing someone else. + * We don't free page tables that are accessed by sharing. */ if (ht->ht_flags & HTABLE_SHARED_PFN) { ASSERT(ht->ht_pfn != PFN_INVALID); - ht->ht_pfn = PFN_INVALID; } else if (!(ht->ht_flags & HTABLE_VLP)) { - ptable_free(ht); + ptable_free(ht->ht_pfn); } + ht->ht_pfn = PFN_INVALID; /* * If we are the thread using the reserves, put free htables @@ -1015,12 +890,9 @@ link_ptp(htable_t *higher, htable_t *new, uintptr_t vaddr) } /* - * Release of an htable. - * - * During process exit, some empty page tables are not unlinked - hat_free_end() - * cleans them up. Upper level pagetable (mmu.max_page_level and higher) are - * only released during hat_free_end() or by htable_steal(). We always - * release SHARED page tables. + * Release of hold on an htable. If this is the last use and the pagetable + * is empty we may want to free it, then recursively look at the pagetable + * above it. The recursion is handled by the outer while() loop. */ void htable_release(htable_t *ht) @@ -1074,8 +946,8 @@ htable_release(htable_t *ht) } /* - * remember if we destroy an htable that shares its PFN - * from elsewhere + * Remember if we destroy an htable that shares its PFN + * from elsewhere. */ if (ht->ht_flags & HTABLE_SHARED_PFN) { ASSERT(ht->ht_level == 0); @@ -1103,7 +975,7 @@ htable_release(htable_t *ht) */ if ((hat->hat_flags & HAT_VLP) && level == VLP_LEVEL - 1) - hat_demap(hat, DEMAP_ALL_ADDR); + hat_tlb_inval(hat, DEMAP_ALL_ADDR); /* * remove this htable from its hash list @@ -1303,7 +1175,7 @@ try_again: if ((hat->hat_flags & HAT_VLP) && #endif /* __i386 */ l == VLP_LEVEL - 1) - hat_demap(hat, DEMAP_ALL_ADDR); + hat_tlb_inval(hat, DEMAP_ALL_ADDR); } ht->ht_next = hat->hat_ht_hash[h]; ASSERT(ht->ht_prev == NULL); @@ -1336,6 +1208,96 @@ try_again: } /* + * Inherit initial pagetables from the boot program. + */ +void +htable_attach( + hat_t *hat, + uintptr_t base, + level_t level, + htable_t *parent, + pfn_t pfn) +{ + htable_t *ht; + uint_t h; + uint_t i; + x86pte_t pte; + x86pte_t *ptep; + page_t *pp; + extern page_t *boot_claim_page(pfn_t); + + ht = htable_get_reserve(); + if (level == mmu.max_level) + kas.a_hat->hat_htable = ht; + ht->ht_hat = hat; + ht->ht_parent = parent; + ht->ht_vaddr = base; + ht->ht_level = level; + ht->ht_busy = 1; + ht->ht_next = NULL; + ht->ht_prev = NULL; + ht->ht_flags = 0; + ht->ht_pfn = pfn; + ht->ht_lock_cnt = 0; + ht->ht_valid_cnt = 0; + if (parent != NULL) + ++parent->ht_busy; + + h = HTABLE_HASH(hat, base, level); + HTABLE_ENTER(h); + ht->ht_next = hat->hat_ht_hash[h]; + ASSERT(ht->ht_prev == NULL); + if (hat->hat_ht_hash[h]) + hat->hat_ht_hash[h]->ht_prev = ht; + hat->hat_ht_hash[h] = ht; + HTABLE_EXIT(h); + + /* + * make sure the page table physical page is not FREE + */ + if (page_resv(1, KM_NOSLEEP) == 0) + panic("page_resv() failed in ptable alloc"); + + pp = boot_claim_page(pfn); + ASSERT(pp != NULL); + page_downgrade(pp); + /* + * Record in the page_t that is a pagetable for segkpm setup. + */ + if (kpm_vbase) + pp->p_index = 1; + + /* + * Count valid mappings and recursively attach lower level pagetables. + */ + ptep = kbm_remap_window(pfn_to_pa(pfn), 0); + for (i = 0; i < HTABLE_NUM_PTES(ht); ++i) { + if (mmu.pae_hat) + pte = ptep[i]; + else + pte = ((x86pte32_t *)ptep)[i]; + if (!IN_HYPERVISOR_VA(base) && PTE_ISVALID(pte)) { + ++ht->ht_valid_cnt; + if (!PTE_ISPAGE(pte, level)) { + htable_attach(hat, base, level - 1, + ht, PTE2PFN(pte, level)); + ptep = kbm_remap_window(pfn_to_pa(pfn), 0); + } + } + base += LEVEL_SIZE(level); + if (base == mmu.hole_start) + base = (mmu.hole_end + MMU_PAGEOFFSET) & MMU_PAGEMASK; + } + + /* + * As long as all the mappings we had were below kernel base + * we can release the htable. + */ + if (base < kernelbase) + htable_release(ht); +} + +/* * Walk through a given htable looking for the first valid entry. This * routine takes both a starting and ending address. The starting address * is required to be within the htable provided by the caller, but there is @@ -1355,8 +1317,8 @@ htable_scan(htable_t *ht, uintptr_t *vap, uintptr_t eaddr) { uint_t e; x86pte_t found_pte = (x86pte_t)0; - char *pte_ptr; - char *end_pte_ptr; + caddr_t pte_ptr; + caddr_t end_pte_ptr; int l = ht->ht_level; uintptr_t va = *vap & LEVEL_MASK(l); size_t pgsize = LEVEL_SIZE(l); @@ -1373,9 +1335,9 @@ htable_scan(htable_t *ht, uintptr_t *vap, uintptr_t eaddr) * The following page table scan code knows that the valid * bit of a PTE is in the lowest byte AND that x86 is little endian!! */ - pte_ptr = (char *)x86pte_access_pagetable(ht); - end_pte_ptr = pte_ptr + (ht->ht_num_ptes << mmu.pte_size_shift); - pte_ptr += e << mmu.pte_size_shift; + pte_ptr = (caddr_t)x86pte_access_pagetable(ht, 0); + end_pte_ptr = (caddr_t)PT_INDEX_PTR(pte_ptr, HTABLE_NUM_PTES(ht)); + pte_ptr = (caddr_t)PT_INDEX_PTR((x86pte_t *)pte_ptr, e); while (!PTE_ISVALID(*pte_ptr)) { va += pgsize; if (va >= eaddr) @@ -1389,13 +1351,8 @@ htable_scan(htable_t *ht, uintptr_t *vap, uintptr_t eaddr) /* * if we found a valid PTE, load the entire PTE */ - if (va < eaddr && pte_ptr != end_pte_ptr) { - if (mmu.pae_hat) { - ATOMIC_LOAD64((x86pte_t *)pte_ptr, found_pte); - } else { - found_pte = *(x86pte32_t *)pte_ptr; - } - } + if (va < eaddr && pte_ptr != end_pte_ptr) + found_pte = GET_PTE((x86pte_t *)pte_ptr); x86pte_release_pagetable(ht); #if defined(__amd64) @@ -1611,7 +1568,7 @@ htable_va2entry(uintptr_t va, htable_t *ht) ASSERT(va >= ht->ht_vaddr); ASSERT(va <= HTABLE_LAST_PAGE(ht)); - return ((va >> LEVEL_SHIFT(l)) & (ht->ht_num_ptes - 1)); + return ((va >> LEVEL_SHIFT(l)) & (HTABLE_NUM_PTES(ht) - 1)); } /* @@ -1624,7 +1581,7 @@ htable_e2va(htable_t *ht, uint_t entry) level_t l = ht->ht_level; uintptr_t va; - ASSERT(entry < ht->ht_num_ptes); + ASSERT(entry < HTABLE_NUM_PTES(ht)); va = ht->ht_vaddr + ((uintptr_t)entry << LEVEL_SHIFT(l)); /* @@ -1641,7 +1598,6 @@ htable_e2va(htable_t *ht, uint_t entry) /* * The code uses compare and swap instructions to read/write PTE's to * avoid atomicity problems, since PTEs can be 8 bytes on 32 bit systems. - * Again this can be optimized on 64 bit systems, since aligned load/store * will naturally be atomic. * * The combination of using kpreempt_disable()/_enable() and the hci_mutex @@ -1649,69 +1605,44 @@ htable_e2va(htable_t *ht, uint_t entry) * while it's in use. If an interrupt thread tries to access a PTE, it will * yield briefly back to the pinned thread which holds the cpu's hci_mutex. */ - -static struct hat_cpu_info init_hci; /* used for cpu 0 */ - -/* - * Initialize a CPU private window for mapping page tables. - * There will be 3 total pages of addressing needed: - * - * 1 for r/w access to pagetables - * 1 for r access when copying pagetables (hat_alloc) - * 1 that will map the PTEs for the 1st 2, so we can access them quickly - * - * We use vmem_xalloc() to get a correct alignment so that only one - * hat_mempte_setup() is needed. - */ void -x86pte_cpu_init(cpu_t *cpu, void *pages) +x86pte_cpu_init(cpu_t *cpu) { struct hat_cpu_info *hci; - caddr_t va; - /* - * We can't use kmem_alloc/vmem_alloc for the 1st CPU, as this is - * called before we've activated our own HAT - */ - if (pages != NULL) { - hci = &init_hci; - va = pages; - } else { - hci = kmem_alloc(sizeof (struct hat_cpu_info), KM_SLEEP); - va = vmem_xalloc(heap_arena, 3 * MMU_PAGESIZE, MMU_PAGESIZE, 0, - LEVEL_SIZE(1), NULL, NULL, VM_SLEEP); - } + hci = kmem_zalloc(sizeof (*hci), KM_SLEEP); mutex_init(&hci->hci_mutex, NULL, MUTEX_DEFAULT, NULL); + cpu->cpu_hat_info = hci; +} - /* - * If we are using segkpm, then there is no need for any of the - * mempte support. We can access the desired memory through a kpm - * mapping rather than setting up a temporary mempte mapping. - */ - if (kpm_enable == 0) { - hci->hci_mapped_pfn = PFN_INVALID; - - hci->hci_kernel_pte = - hat_mempte_kern_setup(va, va + (2 * MMU_PAGESIZE)); - hci->hci_pagetable_va = (void *)va; - } +void +x86pte_cpu_fini(cpu_t *cpu) +{ + struct hat_cpu_info *hci = cpu->cpu_hat_info; - cpu->cpu_hat_info = hci; + kmem_free(hci, sizeof (*hci)); + cpu->cpu_hat_info = NULL; } +#ifdef __i386 /* - * Macro to establish temporary mappings for x86pte_XXX routines. + * On 32 bit kernels, loading a 64 bit PTE is a little tricky */ -#define X86PTE_REMAP(addr, pte, index, perm, pfn) { \ - x86pte_t t; \ - \ - t = MAKEPTE((pfn), 0) | (perm) | mmu.pt_global | mmu.pt_nx;\ - if (mmu.pae_hat) \ - pte[index] = t; \ - else \ - ((x86pte32_t *)(pte))[index] = t; \ - mmu_tlbflush_entry((caddr_t)(addr)); \ +x86pte_t +get_pte64(x86pte_t *ptr) +{ + volatile uint32_t *p = (uint32_t *)ptr; + x86pte_t t; + + ASSERT(mmu.pae_hat != 0); + for (;;) { + t = p[0]; + t |= (uint64_t)p[1] << 32; + if ((t & 0xffffffff) == p[0]) + return (t); + } } +#endif /* __i386 */ /* * Disable preemption and establish a mapping to the pagetable with the @@ -1719,47 +1650,65 @@ x86pte_cpu_init(cpu_t *cpu, void *pages) * pfn as we last used referenced from this CPU. */ static x86pte_t * -x86pte_access_pagetable(htable_t *ht) +x86pte_access_pagetable(htable_t *ht, uint_t index) { - pfn_t pfn; - struct hat_cpu_info *hci; - /* * VLP pagetables are contained in the hat_t */ if (ht->ht_flags & HTABLE_VLP) - return (ht->ht_hat->hat_vlp_ptes); + return (PT_INDEX_PTR(ht->ht_hat->hat_vlp_ptes, index)); + return (x86pte_mapin(ht->ht_pfn, index, ht)); +} + +/* + * map the given pfn into the page table window. + */ +/*ARGSUSED*/ +x86pte_t * +x86pte_mapin(pfn_t pfn, uint_t index, htable_t *ht) +{ + x86pte_t *pteptr; + x86pte_t pte; + x86pte_t newpte; + int x; - /* - * During early boot, use hat_boot_remap() of a page table adddress. - */ - pfn = ht->ht_pfn; ASSERT(pfn != PFN_INVALID); - if (kpm_enable) - return ((x86pte_t *)hat_kpm_pfn2va(pfn)); if (!khat_running) { - (void) hat_boot_remap(ptable_va, pfn); - return ((x86pte_t *)ptable_va); + caddr_t va = kbm_remap_window(pfn_to_pa(pfn), 1); + return (PT_INDEX_PTR(va, index)); } /* - * Normally, disable preemption and grab the CPU's hci_mutex + * If kpm is available, use it. + */ + if (kpm_vbase) + return (PT_INDEX_PTR(hat_kpm_pfn2va(pfn), index)); + + /* + * Disable preemption and grab the CPU's hci_mutex */ kpreempt_disable(); - hci = CPU->cpu_hat_info; - ASSERT(hci != NULL); - mutex_enter(&hci->hci_mutex); - if (hci->hci_mapped_pfn != pfn) { - /* - * The current mapping doesn't already point to this page. - * Update the CPU specific pagetable mapping to map the pfn. - */ - X86PTE_REMAP(hci->hci_pagetable_va, hci->hci_kernel_pte, 0, - PT_WRITABLE, pfn); - hci->hci_mapped_pfn = pfn; + ASSERT(CPU->cpu_hat_info != NULL); + mutex_enter(&CPU->cpu_hat_info->hci_mutex); + x = PWIN_TABLE(CPU->cpu_id); + pteptr = (x86pte_t *)PWIN_PTE_VA(x); + if (mmu.pae_hat) + pte = *pteptr; + else + pte = *(x86pte32_t *)pteptr; + + newpte = MAKEPTE(pfn, 0) | mmu.pt_global | mmu.pt_nx; + newpte |= PT_WRITABLE; + + if (!PTE_EQUIV(newpte, pte)) { + if (mmu.pae_hat) + *pteptr = newpte; + else + *(x86pte32_t *)pteptr = newpte; + mmu_tlbflush_entry((caddr_t)(PWIN_VA(x))); } - return (hci->hci_pagetable_va); + return (PT_INDEX_PTR(PWIN_VA(x), index)); } /* @@ -1768,31 +1717,25 @@ x86pte_access_pagetable(htable_t *ht) static void x86pte_release_pagetable(htable_t *ht) { - struct hat_cpu_info *hci; - - if (kpm_enable) - return; - /* * nothing to do for VLP htables */ if (ht->ht_flags & HTABLE_VLP) return; - /* - * During boot-up hat_kern_setup(), erase the boot loader remapping. - */ - if (!khat_running) { - hat_boot_demap(ptable_va); + x86pte_mapout(); +} + +void +x86pte_mapout(void) +{ + if (mmu.pwin_base == NULL || !khat_running) return; - } /* - * Normal Operation: drop the CPU's hci_mutex and restore preemption + * Drop the CPU's hci_mutex and restore preemption. */ - hci = CPU->cpu_hat_info; - ASSERT(hci != NULL); - mutex_exit(&hci->hci_mutex); + mutex_exit(&CPU->cpu_hat_info->hci_mutex); kpreempt_enable(); } @@ -1803,362 +1746,267 @@ x86pte_t x86pte_get(htable_t *ht, uint_t entry) { x86pte_t pte; - x86pte32_t *pte32p; x86pte_t *ptep; /* * Be careful that loading PAE entries in 32 bit kernel is atomic. */ - ptep = x86pte_access_pagetable(ht); - if (mmu.pae_hat) { - ATOMIC_LOAD64(ptep + entry, pte); - } else { - pte32p = (x86pte32_t *)ptep; - pte = pte32p[entry]; - } + ASSERT(entry < mmu.ptes_per_table); + ptep = x86pte_access_pagetable(ht, entry); + pte = GET_PTE(ptep); x86pte_release_pagetable(ht); return (pte); } /* * Atomic unconditional set of a page table entry, it returns the previous - * value. + * value. For pre-existing mappings if the PFN changes, then we don't care + * about the old pte's REF / MOD bits. If the PFN remains the same, we leave + * the MOD/REF bits unchanged. + * + * If asked to overwrite a link to a lower page table with a large page + * mapping, this routine returns the special value of LPAGE_ERROR. This + * allows the upper HAT layers to retry with a smaller mapping size. */ x86pte_t x86pte_set(htable_t *ht, uint_t entry, x86pte_t new, void *ptr) { x86pte_t old; - x86pte_t prev, n; + x86pte_t prev; x86pte_t *ptep; - x86pte32_t *pte32p; - x86pte32_t n32, p32; + level_t l = ht->ht_level; + x86pte_t pfn_mask = (l != 0) ? PT_PADDR_LGPG : PT_PADDR; + x86pte_t n; + uintptr_t addr = htable_e2va(ht, entry); + hat_t *hat = ht->ht_hat; + ASSERT(new != 0); /* don't use to invalidate a PTE, see x86pte_update */ ASSERT(!(ht->ht_flags & HTABLE_SHARED_PFN)); - if (ptr == NULL) { - ptep = x86pte_access_pagetable(ht); - ptep = (void *)((caddr_t)ptep + (entry << mmu.pte_size_shift)); - } else { + if (ptr == NULL) + ptep = x86pte_access_pagetable(ht, entry); + else ptep = ptr; - } - if (mmu.pae_hat) { - for (;;) { - prev = *ptep; - n = new; - /* - * prevent potential data loss by preserving the - * MOD/REF bits if set in the current PTE, the pfns are - * the same and the 'new' pte is non-zero. For example, - * segmap can reissue a read-only hat_memload on top - * of a dirty page. - * - * 'new' is required to be non-zero on a remap as at - * least the valid bit should be non-zero. The 'new' - * check also avoids incorrectly preserving the REF/MOD - * bit when unmapping pfn 0. - */ - if (new != 0 && PTE_ISVALID(prev) && - PTE2PFN(prev, ht->ht_level) == - PTE2PFN(n, ht->ht_level)) { - n |= prev & (PT_REF | PT_MOD); - } - if (prev == n) { - old = new; - break; - } - old = cas64(ptep, prev, n); - if (old == prev) - break; - } - } else { - pte32p = (x86pte32_t *)ptep; - for (;;) { - p32 = *pte32p; - n32 = new; - if (new != 0 && PTE_ISVALID(p32) && - PTE2PFN(p32, ht->ht_level) == - PTE2PFN(n32, ht->ht_level)) { - n32 |= p32 & (PT_REF | PT_MOD); - } - if (p32 == n32) { - old = new; - break; - } - old = cas32(pte32p, p32, n32); - if (old == p32) - break; + /* + * Install the new PTE. If remapping the same PFN, then + * copy existing REF/MOD bits to new mapping. + */ + do { + prev = GET_PTE(ptep); + n = new; + if (PTE_ISVALID(n) && (prev & pfn_mask) == (new & pfn_mask)) + n |= prev & (PT_REF | PT_MOD); + + /* + * Another thread may have installed this mapping already, + * flush the local TLB and be done. + */ + if (prev == n) { + old = new; + mmu_tlbflush_entry((caddr_t)addr); + goto done; } - } + + /* + * Detect if we have a collision of installing a large + * page mapping where there already is a lower page table. + */ + if (l > 0 && (prev & PT_VALID) && !(prev & PT_PAGESIZE)) + return (LPAGE_ERROR); + + old = CAS_PTE(ptep, prev, n); + } while (old != prev); + + /* + * Do a TLB demap if needed, ie. the old pte was valid. + * + * Note that a stale TLB writeback to the PTE here either can't happen + * or doesn't matter. The PFN can only change for NOSYNC|NOCONSIST + * mappings, but they were created with REF and MOD already set, so + * no stale writeback will happen. + * + * Segmap is the only place where remaps happen on the same pfn and for + * that we want to preserve the stale REF/MOD bits. + */ + if (old & PT_REF) + hat_tlb_inval(hat, addr); + +done: if (ptr == NULL) x86pte_release_pagetable(ht); return (old); } /* - * Atomic compare and swap of a page table entry. + * Atomic compare and swap of a page table entry. No TLB invalidates are done. + * This is used for links between pagetables of different levels. + * Note we always create these links with dirty/access set, so they should + * never change. */ -static x86pte_t +x86pte_t x86pte_cas(htable_t *ht, uint_t entry, x86pte_t old, x86pte_t new) { x86pte_t pte; x86pte_t *ptep; - x86pte32_t pte32, o32, n32; - x86pte32_t *pte32p; - ASSERT(!(ht->ht_flags & HTABLE_SHARED_PFN)); - ptep = x86pte_access_pagetable(ht); - if (mmu.pae_hat) { - pte = cas64(&ptep[entry], old, new); - } else { - o32 = old; - n32 = new; - pte32p = (x86pte32_t *)ptep; - pte32 = cas32(&pte32p[entry], o32, n32); - pte = pte32; - } + ptep = x86pte_access_pagetable(ht, entry); + pte = CAS_PTE(ptep, old, new); x86pte_release_pagetable(ht); - return (pte); } /* - * data structure for cross call information + * Make sure the zero we wrote to a page table entry sticks in memory + * after invalidating all TLB entries on all CPUs. */ -typedef struct xcall_info { - x86pte_t xi_pte; - x86pte_t xi_old; - x86pte_t *xi_pteptr; - pfn_t xi_pfn; - processorid_t xi_cpuid; - level_t xi_level; - xc_func_t xi_func; -} xcall_info_t; - -/* - * Cross call service function to atomically invalidate a PTE and flush TLBs - */ -/*ARGSUSED*/ -static int -x86pte_inval_func(xc_arg_t a1, xc_arg_t a2, xc_arg_t a3) +static x86pte_t +handle_tlbs(x86pte_t oldpte, x86pte_t *ptep, htable_t *ht, uint_t entry) { - xcall_info_t *xi = (xcall_info_t *)a1; - caddr_t addr = (caddr_t)a2; - - /* - * Only the initiating cpu invalidates the page table entry. - * It returns the previous PTE value to the caller. - */ - if (CPU->cpu_id == xi->xi_cpuid) { - x86pte_t *ptep = xi->xi_pteptr; - pfn_t pfn = xi->xi_pfn; - level_t level = xi->xi_level; - x86pte_t old; - x86pte_t prev; - x86pte32_t *pte32p; - x86pte32_t p32; - - if (mmu.pae_hat) { - for (;;) { - prev = *ptep; - if (PTE2PFN(prev, level) != pfn) - break; - old = cas64(ptep, prev, 0); - if (old == prev) - break; - } - } else { - pte32p = (x86pte32_t *)ptep; - for (;;) { - p32 = *pte32p; - if (PTE2PFN(p32, level) != pfn) - break; - old = cas32(pte32p, p32, 0); - if (old == p32) - break; - } - prev = p32; - } - xi->xi_pte = prev; - } + hat_t *hat = ht->ht_hat; + uintptr_t addr = htable_e2va(ht, entry); + x86pte_t found; /* - * For a normal address, we just flush one page mapping - * Otherwise reload cr3 to effect a complete TLB flush. - * - * Note we don't reload VLP pte's -- this assume we never have a - * large page size at VLP_LEVEL for VLP processes. + * Was the PTE ever used? If not there can't be any TLB entries. */ - if ((uintptr_t)addr != DEMAP_ALL_ADDR) { - mmu_tlbflush_entry(addr); - } else { - reload_cr3(); - } - return (0); -} - -/* - * Cross call service function to atomically change a PTE and flush TLBs - */ -/*ARGSUSED*/ -static int -x86pte_update_func(xc_arg_t a1, xc_arg_t a2, xc_arg_t a3) -{ - xcall_info_t *xi = (xcall_info_t *)a1; - caddr_t addr = (caddr_t)a2; + if ((oldpte & PT_REF) == 0) + return (oldpte); /* - * Only the initiating cpu changes the page table entry. - * It returns the previous PTE value to the caller. + * Do a full global TLB invalidation. + * We may have to loop until the new PTE in memory stays zero. + * Why? Because Intel/AMD don't document how the REF/MOD bits are + * copied back from the TLB to the PTE, sigh. We're protecting + * here against a blind write back of the MOD (and other) bits. */ - if (CPU->cpu_id == xi->xi_cpuid) { - x86pte_t *ptep = xi->xi_pteptr; - x86pte_t new = xi->xi_pte; - x86pte_t old = xi->xi_old; - x86pte_t prev; - - if (mmu.pae_hat) { - prev = cas64(ptep, old, new); - } else { - x86pte32_t o32 = old; - x86pte32_t n32 = new; - x86pte32_t *pte32p = (x86pte32_t *)ptep; - prev = cas32(pte32p, o32, n32); - } + for (;;) { + hat_tlb_inval(hat, addr); - xi->xi_pte = prev; - } - - /* - * Flush the TLB entry - */ - if ((uintptr_t)addr != DEMAP_ALL_ADDR) - mmu_tlbflush_entry(addr); - else - reload_cr3(); - return (0); -} + /* + * Check for a stale writeback of a oldpte TLB entry. + * Done when the PTE stays zero. + */ + found = GET_PTE(ptep); + if (found == 0) + return (oldpte); -/* - * Use cross calls to change a page table entry and invalidate TLBs. - */ -void -x86pte_xcall(hat_t *hat, xcall_info_t *xi, uintptr_t addr) -{ - cpuset_t cpus; + /* + * The only acceptable PTE change must be from a TLB + * flush setting the MOD bit in, hence oldpte must + * have been writable. + */ + if (!(oldpte & PT_WRITABLE) || !(found & PT_MOD)) + break; - /* - * Given the current implementation of hat_share(), doing a - * hat_pageunload() on a shared page table requries invalidating - * all user TLB entries on all CPUs. - */ - if (hat->hat_flags & HAT_SHARED) { - hat = kas.a_hat; - addr = DEMAP_ALL_ADDR; - } + /* + * Did we see a complete writeback of oldpte? + * or + * Did we see the MOD bit set (plus possibly other + * bits rewritten) in a still invalid mapping? + */ + if (found == (oldpte | PT_MOD) || + (!(found & PT_VALID) && + (oldpte | found) == (oldpte | PT_MOD))) + oldpte |= PT_MOD; + else + break; - /* - * Use a cross call to do the invalidations. - * Note the current CPU always has to be in the cross call CPU set. - */ - kpreempt_disable(); - xi->xi_cpuid = CPU->cpu_id; - CPUSET_ZERO(cpus); - if (hat == kas.a_hat) { - CPUSET_OR(cpus, khat_cpuset); - } else { - mutex_enter(&hat->hat_switch_mutex); - CPUSET_OR(cpus, hat->hat_cpus); - CPUSET_ADD(cpus, CPU->cpu_id); + (void) CAS_PTE(ptep, found, 0); } /* - * Use a cross call to modify the page table entry and invalidate TLBs. - * If we're panic'ing, don't bother with the cross call. - * Note the panicstr check isn't bullet proof and the panic system - * ought to be made tighter. + * If we hit this, a processor attempted to set the DIRTY bit + * of a page table entry happened in a way we didn't anticipate */ - if (panicstr == NULL) - xc_wait_sync((xc_arg_t)xi, addr, NULL, X_CALL_HIPRI, - cpus, xi->xi_func); - else - (void) xi->xi_func((xc_arg_t)xi, (xc_arg_t)addr, NULL); - if (hat != kas.a_hat) - mutex_exit(&hat->hat_switch_mutex); - kpreempt_enable(); + panic("handle_tlbs(): unanticipated TLB shootdown scenario" + " oldpte=" FMT_PTE " found=" FMT_PTE, oldpte, found); + /*LINTED*/ } /* - * Invalidate a page table entry if it currently maps the given pfn. - * This returns the previous value of the PTE. + * Invalidate a page table entry as long as it currently maps something that + * matches the value determined by expect. + * + * Also invalidates any TLB entries and returns the previous value of the PTE. */ x86pte_t -x86pte_invalidate_pfn(htable_t *ht, uint_t entry, pfn_t pfn, void *pte_ptr) +x86pte_inval( + htable_t *ht, + uint_t entry, + x86pte_t expect, + x86pte_t *pte_ptr) { - xcall_info_t xi; x86pte_t *ptep; - hat_t *hat; - uintptr_t addr; + x86pte_t oldpte; + x86pte_t found; ASSERT(!(ht->ht_flags & HTABLE_SHARED_PFN)); - if (pte_ptr != NULL) { + ASSERT(ht->ht_level != VLP_LEVEL); + if (pte_ptr != NULL) ptep = pte_ptr; - } else { - ptep = x86pte_access_pagetable(ht); - ptep = (void *)((caddr_t)ptep + (entry << mmu.pte_size_shift)); - } + else + ptep = x86pte_access_pagetable(ht, entry); /* - * Fill in the structure used by the cross call function to do the - * invalidation. + * This loop deals with REF/MOD bits changing between the + * GET_PTE() and the CAS_PTE(). */ - xi.xi_pte = 0; - xi.xi_pteptr = ptep; - xi.xi_pfn = pfn; - xi.xi_level = ht->ht_level; - xi.xi_func = x86pte_inval_func; - ASSERT(xi.xi_level != VLP_LEVEL); - - hat = ht->ht_hat; - addr = htable_e2va(ht, entry); - - x86pte_xcall(hat, &xi, addr); - + do { + oldpte = GET_PTE(ptep); + if (expect != 0 && (oldpte & PT_PADDR) != (expect & PT_PADDR)) + goto give_up; + found = CAS_PTE(ptep, oldpte, 0); + } while (found != oldpte); + oldpte = handle_tlbs(oldpte, ptep, ht, entry); + +give_up: if (pte_ptr == NULL) x86pte_release_pagetable(ht); - return (xi.xi_pte); + return (oldpte); } /* - * update a PTE and invalidate any stale TLB entries. + * Change a page table entry af it currently matches the value in expect. */ x86pte_t -x86pte_update(htable_t *ht, uint_t entry, x86pte_t expected, x86pte_t new) +x86pte_update( + htable_t *ht, + uint_t entry, + x86pte_t expect, + x86pte_t new) { - xcall_info_t xi; x86pte_t *ptep; - hat_t *hat; - uintptr_t addr; + x86pte_t found; + ASSERT(new != 0); ASSERT(!(ht->ht_flags & HTABLE_SHARED_PFN)); - ptep = x86pte_access_pagetable(ht); - ptep = (void *)((caddr_t)ptep + (entry << mmu.pte_size_shift)); - - /* - * Fill in the structure used by the cross call function to do the - * invalidation. - */ - xi.xi_pte = new; - xi.xi_old = expected; - xi.xi_pteptr = ptep; - xi.xi_func = x86pte_update_func; - - hat = ht->ht_hat; - addr = htable_e2va(ht, entry); + ASSERT(ht->ht_level != VLP_LEVEL); - x86pte_xcall(hat, &xi, addr); + ptep = x86pte_access_pagetable(ht, entry); + found = CAS_PTE(ptep, expect, new); + if (found == expect) { + hat_tlb_inval(ht->ht_hat, htable_e2va(ht, entry)); + /* + * When removing write permission *and* clearing the + * MOD bit, check if a write happened via a stale + * TLB entry before the TLB shootdown finished. + * + * If it did happen, simply re-enable write permission and + * act like the original CAS failed. + */ + if ((expect & (PT_WRITABLE | PT_MOD)) == PT_WRITABLE && + (new & (PT_WRITABLE | PT_MOD)) == 0 && + (GET_PTE(ptep) & PT_MOD) != 0) { + do { + found = GET_PTE(ptep); + found = + CAS_PTE(ptep, found, found | PT_WRITABLE); + } while ((found & PT_WRITABLE) == 0); + } + } x86pte_release_pagetable(ht); - return (xi.xi_pte); + return (found); } /* @@ -2169,10 +2017,11 @@ x86pte_update(htable_t *ht, uint_t entry, x86pte_t expected, x86pte_t new) void x86pte_copy(htable_t *src, htable_t *dest, uint_t entry, uint_t count) { - struct hat_cpu_info *hci; caddr_t src_va; caddr_t dst_va; size_t size; + x86pte_t *pteptr; + x86pte_t pte; ASSERT(khat_running); ASSERT(!(dest->ht_flags & HTABLE_VLP)); @@ -2181,27 +2030,31 @@ x86pte_copy(htable_t *src, htable_t *dest, uint_t entry, uint_t count) ASSERT(!(dest->ht_flags & HTABLE_SHARED_PFN)); /* - * Acquire access to the CPU pagetable window for the destination. + * Acquire access to the CPU pagetable windows for the dest and source. */ - dst_va = (caddr_t)x86pte_access_pagetable(dest); - if (kpm_enable) { - src_va = (caddr_t)x86pte_access_pagetable(src); + dst_va = (caddr_t)x86pte_access_pagetable(dest, entry); + if (kpm_vbase) { + src_va = (caddr_t) + PT_INDEX_PTR(hat_kpm_pfn2va(src->ht_pfn), entry); } else { - hci = CPU->cpu_hat_info; + uint_t x = PWIN_SRC(CPU->cpu_id); /* * Finish defining the src pagetable mapping */ - src_va = dst_va + MMU_PAGESIZE; - X86PTE_REMAP(src_va, hci->hci_kernel_pte, 1, 0, src->ht_pfn); + src_va = (caddr_t)PT_INDEX_PTR(PWIN_VA(x), entry); + pte = MAKEPTE(src->ht_pfn, 0) | mmu.pt_global | mmu.pt_nx; + pteptr = (x86pte_t *)PWIN_PTE_VA(x); + if (mmu.pae_hat) + *pteptr = pte; + else + *(x86pte32_t *)pteptr = pte; + mmu_tlbflush_entry((caddr_t)(PWIN_VA(x))); } /* * now do the copy */ - - dst_va += entry << mmu.pte_size_shift; - src_va += entry << mmu.pte_size_shift; size = count << mmu.pte_size_shift; bcopy(src_va, dst_va, size); @@ -2211,42 +2064,29 @@ x86pte_copy(htable_t *src, htable_t *dest, uint_t entry, uint_t count) /* * Zero page table entries - Note this doesn't use atomic stores! */ -void +static void x86pte_zero(htable_t *dest, uint_t entry, uint_t count) { caddr_t dst_va; - x86pte_t *p; - x86pte32_t *p32; size_t size; - extern void hat_pte_zero(void *, size_t); /* * Map in the page table to be zeroed. */ ASSERT(!(dest->ht_flags & HTABLE_SHARED_PFN)); ASSERT(!(dest->ht_flags & HTABLE_VLP)); - dst_va = (caddr_t)x86pte_access_pagetable(dest); - dst_va += entry << mmu.pte_size_shift; + + dst_va = (caddr_t)x86pte_access_pagetable(dest, entry); + size = count << mmu.pte_size_shift; - if (x86_feature & X86_SSE2) { - hat_pte_zero(dst_va, size); - } else if (khat_running) { + ASSERT(size > BLOCKZEROALIGN); +#ifdef __i386 + if ((x86_feature & X86_SSE2) == 0) bzero(dst_va, size); - } else { - /* - * Can't just use bzero during boot because it checks the - * address against kernelbase. Instead just use a zero loop. - */ - if (mmu.pae_hat) { - p = (x86pte_t *)dst_va; - while (count-- > 0) - *p++ = 0; - } else { - p32 = (x86pte32_t *)dst_va; - while (count-- > 0) - *p32++ = 0; - } - } + else +#endif + block_zero_no_xmm(dst_va, size); + x86pte_release_pagetable(dest); } diff --git a/usr/src/uts/i86pc/vm/htable.h b/usr/src/uts/i86pc/vm/htable.h index 7f4e691c57..a3bcc81b29 100644 --- a/usr/src/uts/i86pc/vm/htable.h +++ b/usr/src/uts/i86pc/vm/htable.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -69,10 +68,9 @@ struct htable { struct htable *ht_next; /* forward link for hash table */ struct hat *ht_hat; /* hat this mapping comes from */ uintptr_t ht_vaddr; /* virt addr at start of this table */ - level_t ht_level; /* page table level: 0=4K, 1=2M, ... */ - uint16_t ht_flags; /* see below */ + int8_t ht_level; /* page table level: 0=4K, 1=2M, ... */ + uint8_t ht_flags; /* see below */ int16_t ht_busy; /* implements locking protocol */ - uint16_t ht_num_ptes; /* # of PTEs in page table */ int16_t ht_valid_cnt; /* # of valid entries in this table */ uint32_t ht_lock_cnt; /* # of locked entries in this table */ /* never used for kernel hat */ @@ -88,11 +86,11 @@ typedef struct htable htable_t; * * HTABLE_VLP - this is the top level htable of a VLP HAT. * - * HTABLE_SHARED_PFN - this htable had it's PFN assigned from sharing another + * HTABLE_SHARED_PFN - this htable had its PFN assigned from sharing another * htable. Used by hat_share() for ISM. */ -#define HTABLE_VLP (0x0001) -#define HTABLE_SHARED_PFN (0x0002) +#define HTABLE_VLP (0x01) +#define HTABLE_SHARED_PFN (0x02) /* * The htable hash table hashing function. The 28 is so that high @@ -107,23 +105,9 @@ typedef struct htable htable_t; ((uintptr_t)(hat) >> 4)) & ((hat)->hat_num_hash - 1)) /* - * For 32 bit, access to page table entries is done via the page table's PFN and - * the index of the PTE. We use a CPU specific mapping (a la ppcopy) to map - * in page tables on an "as needed" basis. - * - * 64 bit kernels will use seg_kpm style mappings and avoid any overhead. - * - * The code uses compare and swap instructions to read/write PTE's to - * avoid atomicity problems, since PTEs can be 8 bytes on 32 bit systems. - * Again this can be optimized on 64 bit systems, since aligned load/store - * will naturally be atomic. - * * Each CPU gets a unique hat_cpu_info structure in cpu_hat_info. */ struct hat_cpu_info { - pfn_t hci_mapped_pfn; /* pfn of currently mapped page table */ - x86pte_t *hci_pagetable_va; /* VA to use for mappings */ - x86pte_t *hci_kernel_pte; /* kernel PTE for cpu_pagetable_va */ kmutex_t hci_mutex; /* mutex to ensure sequential usage */ #if defined(__amd64) pfn_t hci_vlp_pfn; /* pfn of hci_vlp_l3ptes */ @@ -141,12 +125,15 @@ struct hat_cpu_info { * * XX64 - The check for the VA hole needs to be better generalized. */ +#define HTABLE_NUM_PTES_PAE(ht) \ + (((ht)->ht_flags & HTABLE_VLP) ? 4 : 512) #if defined(__amd64) +#define HTABLE_NUM_PTES(ht) HTABLE_NUM_PTES_PAE(ht) #define HTABLE_LAST_PAGE(ht) \ ((ht)->ht_level == mmu.max_level ? ((uintptr_t)0UL - MMU_PAGESIZE) :\ ((ht)->ht_vaddr - MMU_PAGESIZE + \ - ((uintptr_t)((ht)->ht_num_ptes) << LEVEL_SHIFT((ht)->ht_level)))) + ((uintptr_t)HTABLE_NUM_PTES(ht) << LEVEL_SHIFT((ht)->ht_level)))) #define NEXT_ENTRY_VA(va, l) \ ((va & LEVEL_MASK(l)) + LEVEL_SIZE(l) == mmu.hole_start ? \ @@ -154,8 +141,10 @@ struct hat_cpu_info { #elif defined(__i386) +#define HTABLE_NUM_PTES(ht) (!mmu.pae_hat ? 1024 : HTABLE_NUM_PTES_PAE(ht)) + #define HTABLE_LAST_PAGE(ht) ((ht)->ht_vaddr - MMU_PAGESIZE + \ - ((uintptr_t)((ht)->ht_num_ptes) << LEVEL_SHIFT((ht)->ht_level))) + ((uintptr_t)HTABLE_NUM_PTES(ht) << LEVEL_SHIFT((ht)->ht_level))) #define NEXT_ENTRY_VA(va, l) ((va & LEVEL_MASK(l)) + LEVEL_SIZE(l)) @@ -188,6 +177,7 @@ extern htable_t *htable_create(struct hat *hat, uintptr_t vaddr, level_t level, extern void htable_acquire(htable_t *); extern void htable_release(htable_t *ht); +extern void htable_destroy(htable_t *ht); /* * Code to free all remaining htables for a hat. Called after the hat is no @@ -222,6 +212,17 @@ extern void htable_reserve(uint_t); extern void htable_adjust_reserve(void); /* + * Attach initial pagetables as htables + */ +extern void htable_attach(struct hat *, uintptr_t, level_t, struct htable *, + pfn_t); + +/* + * return the number of pages mapped by a hat + */ +extern pgcnt_t htable_count_pages(struct hat *); + +/* * Routine to find the next populated htable at or above a given virtual * address. Can specify an upper limit, or HTABLE_WALK_TO_END to indicate * that it should search the entire address space. Similar to @@ -259,14 +260,20 @@ extern uintptr_t htable_e2va(htable_t *ht, uint_t entry); * * Note that all accesses except x86pte_copy() and x86pte_zero() are atomic. */ -extern void x86pte_cpu_init(cpu_t *, void *); +extern void x86pte_cpu_init(cpu_t *); +extern void x86pte_cpu_fini(cpu_t *); extern x86pte_t x86pte_get(htable_t *, uint_t entry); +/* + * x86pte_set returns LPAGE_ERROR if it's asked to overwrite a page table + * link with a large page mapping. + */ +#define LPAGE_ERROR (-(x86pte_t)1) extern x86pte_t x86pte_set(htable_t *, uint_t entry, x86pte_t new, void *); -extern x86pte_t x86pte_invalidate_pfn(htable_t *ht, uint_t entry, pfn_t pfn, - void *pte_ptr); +extern x86pte_t x86pte_inval(htable_t *ht, uint_t entry, + x86pte_t old, x86pte_t *ptr); extern x86pte_t x86pte_update(htable_t *ht, uint_t entry, x86pte_t old, x86pte_t new); @@ -274,8 +281,11 @@ extern x86pte_t x86pte_update(htable_t *ht, uint_t entry, extern void x86pte_copy(htable_t *src, htable_t *dest, uint_t entry, uint_t cnt); -extern void x86pte_zero(htable_t *ht, uint_t entry, uint_t cnt); - +/* + * access to a pagetable knowing only the pfn + */ +extern x86pte_t *x86pte_mapin(pfn_t, uint_t, htable_t *); +extern void x86pte_mapout(void); /* * these are actually inlines for "lock; incw", "lock; decw", etc. instructions. diff --git a/usr/src/uts/i86pc/vm/i86_mmu.c b/usr/src/uts/i86pc/vm/i86_mmu.c new file mode 100644 index 0000000000..7bf91af9b5 --- /dev/null +++ b/usr/src/uts/i86pc/vm/i86_mmu.c @@ -0,0 +1,408 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/t_lock.h> +#include <sys/memlist.h> +#include <sys/cpuvar.h> +#include <sys/vmem.h> +#include <sys/mman.h> +#include <sys/vm.h> +#include <sys/kmem.h> +#include <sys/cmn_err.h> +#include <sys/debug.h> +#include <sys/vm_machparam.h> +#include <sys/tss.h> +#include <sys/vnode.h> +#include <vm/hat.h> +#include <vm/anon.h> +#include <vm/as.h> +#include <vm/page.h> +#include <vm/seg.h> +#include <vm/seg_kmem.h> +#include <vm/seg_map.h> +#include <vm/hat_i86.h> +#include <sys/promif.h> +#include <sys/x86_archext.h> +#include <sys/systm.h> +#include <sys/archsystm.h> +#include <sys/sunddi.h> +#include <sys/ddidmareq.h> +#include <sys/controlregs.h> +#include <sys/reboot.h> +#include <sys/kdi.h> +#include <sys/bootconf.h> +#include <sys/bootsvcs.h> +#include <sys/bootinfo.h> +#include <vm/kboot_mmu.h> + +caddr_t +i86devmap(pfn_t pf, pgcnt_t pgcnt, uint_t prot) +{ + caddr_t addr; + caddr_t addr1; + page_t *pp; + + addr1 = addr = vmem_alloc(heap_arena, mmu_ptob(pgcnt), VM_SLEEP); + + for (; pgcnt != 0; addr += MMU_PAGESIZE, ++pf, --pgcnt) { + pp = page_numtopp_nolock(pf); + if (pp == NULL) { + hat_devload(kas.a_hat, addr, MMU_PAGESIZE, pf, + prot | HAT_NOSYNC, HAT_LOAD_LOCK); + } else { + hat_memload(kas.a_hat, addr, pp, + prot | HAT_NOSYNC, HAT_LOAD_LOCK); + } + } + + return (addr1); +} + +/* + * This routine is like page_numtopp, but accepts only free pages, which + * it allocates (unfrees) and returns with the exclusive lock held. + * It is used by machdep.c/dma_init() to find contiguous free pages. + * + * XXX this and some others should probably be in vm_machdep.c + */ +page_t * +page_numtopp_alloc(pfn_t pfnum) +{ + page_t *pp; + +retry: + pp = page_numtopp_nolock(pfnum); + if (pp == NULL) { + return (NULL); + } + + if (!page_trylock(pp, SE_EXCL)) { + return (NULL); + } + + if (page_pptonum(pp) != pfnum) { + page_unlock(pp); + goto retry; + } + + if (!PP_ISFREE(pp)) { + page_unlock(pp); + return (NULL); + } + if (pp->p_szc) { + page_demote_free_pages(pp); + page_unlock(pp); + goto retry; + } + + /* If associated with a vnode, destroy mappings */ + + if (pp->p_vnode) { + + page_destroy_free(pp); + + if (!page_lock(pp, SE_EXCL, (kmutex_t *)NULL, P_NO_RECLAIM)) { + return (NULL); + } + + if (page_pptonum(pp) != pfnum) { + page_unlock(pp); + goto retry; + } + } + + if (!PP_ISFREE(pp) || !page_reclaim(pp, (kmutex_t *)NULL)) { + page_unlock(pp); + return (NULL); + } + + return (pp); +} + +/* + * Flag is not set early in boot. Once it is set we are no longer + * using boot's page tables. + */ +uint_t khat_running = 0; + +/* + * This procedure is callable only while the boot loader is in charge of the + * MMU. It assumes that PA == VA for page table pointers. It doesn't live in + * kboot_mmu.c since it's used from common code. + */ +pfn_t +va_to_pfn(void *vaddr) +{ + uintptr_t des_va = ALIGN2PAGE(vaddr); + uintptr_t va = des_va; + size_t len; + uint_t prot; + pfn_t pfn; + + if (khat_running) + panic("va_to_pfn(): called too late\n"); + + if (kbm_probe(&va, &len, &pfn, &prot) == 0) + return (PFN_INVALID); + if (va > des_va) + return (PFN_INVALID); + if (va < des_va) + pfn += mmu_btop(des_va - va); + return (pfn); +} + +/* + * Initialize a special area in the kernel that always holds some PTEs for + * faster performance. This always holds segmap's PTEs. + * In the 32 bit kernel this maps the kernel heap too. + */ +void +hat_kmap_init(uintptr_t base, size_t len) +{ + uintptr_t map_addr; /* base rounded down to large page size */ + uintptr_t map_eaddr; /* base + len rounded up */ + size_t map_len; + caddr_t ptes; /* mapping area in kernel for kmap ptes */ + size_t window_size; /* size of mapping area for ptes */ + ulong_t htable_cnt; /* # of page tables to cover map_len */ + ulong_t i; + htable_t *ht; + uintptr_t va; + + /* + * We have to map in an area that matches an entire page table. + */ + map_addr = base & LEVEL_MASK(1); + map_eaddr = (base + len + LEVEL_SIZE(1) - 1) & LEVEL_MASK(1); + map_len = map_eaddr - map_addr; + window_size = mmu_btop(map_len) * mmu.pte_size; + window_size = (window_size + LEVEL_SIZE(1)) & LEVEL_MASK(1); + htable_cnt = map_len >> LEVEL_SHIFT(1); + + /* + * allocate vmem for the kmap_ptes + */ + ptes = vmem_xalloc(heap_arena, window_size, LEVEL_SIZE(1), 0, + 0, NULL, NULL, VM_SLEEP); + mmu.kmap_htables = + kmem_alloc(htable_cnt * sizeof (htable_t *), KM_SLEEP); + + /* + * Map the page tables that cover kmap into the allocated range. + * Note we don't ever htable_release() the kmap page tables - they + * can't ever be stolen, freed, etc. + */ + for (va = map_addr, i = 0; i < htable_cnt; va += LEVEL_SIZE(1), ++i) { + ht = htable_create(kas.a_hat, va, 0, NULL); + if (ht == NULL) + panic("hat_kmap_init: ht == NULL"); + mmu.kmap_htables[i] = ht; + + hat_devload(kas.a_hat, ptes + i * MMU_PAGESIZE, + MMU_PAGESIZE, ht->ht_pfn, + PROT_READ | PROT_WRITE | HAT_NOSYNC | HAT_UNORDERED_OK, + HAT_LOAD | HAT_LOAD_NOCONSIST); + } + + /* + * set information in mmu to activate handling of kmap + */ + mmu.kmap_addr = map_addr; + mmu.kmap_eaddr = map_eaddr; + mmu.kmap_ptes = (x86pte_t *)ptes; +} + +extern caddr_t kpm_vbase; +extern size_t kpm_size; + +/* + * Routine to pre-allocate data structures for hat_kern_setup(). It computes + * how many pagetables it needs by walking the boot loader's page tables. + */ +/*ARGSUSED*/ +void +hat_kern_alloc( + caddr_t segmap_base, + size_t segmap_size, + caddr_t ekernelheap) +{ + uintptr_t last_va = (uintptr_t)-1; /* catch 1st time */ + uintptr_t va = 0; + size_t size; + pfn_t pfn; + uint_t prot; + uint_t table_cnt = 1; + uint_t mapping_cnt; + level_t start_level; + level_t l; + struct memlist *pmem; + level_t lpagel = mmu.max_page_level; + uint64_t paddr; + int64_t psize; + + + if (kpm_size > 0) { + /* + * Create the kpm page tables. + */ + for (pmem = phys_install; pmem; pmem = pmem->next) { + paddr = pmem->address; + psize = pmem->size; + while (psize >= MMU_PAGESIZE) { + if ((paddr & LEVEL_OFFSET(lpagel)) == 0 && + psize > LEVEL_SIZE(lpagel)) + l = lpagel; + else + l = 0; + kbm_map((uintptr_t)kpm_vbase + paddr, paddr, + l, 1); + paddr += LEVEL_SIZE(l); + psize -= LEVEL_SIZE(l); + } + } + } else { + /* + * Create the page windows and 1 page of VA in + * which we map the PTEs of those windows. + */ + mmu.pwin_base = vmem_xalloc(heap_arena, 2 * NCPU * MMU_PAGESIZE, + LEVEL_SIZE(1), 0, 0, NULL, NULL, VM_SLEEP); + ASSERT(NCPU * 2 <= MMU_PAGESIZE / mmu.pte_size); + mmu.pwin_pte_va = vmem_xalloc(heap_arena, MMU_PAGESIZE, + MMU_PAGESIZE, 0, 0, NULL, NULL, VM_SLEEP); + + /* + * Find/Create the page table window mappings. + */ + paddr = 0; + (void) find_pte((uintptr_t)mmu.pwin_base, &paddr, 0, 0); + ASSERT(paddr != 0); + ASSERT((paddr & MMU_PAGEOFFSET) == 0); + mmu.pwin_pte_pa = paddr; + kbm_map((uintptr_t)mmu.pwin_pte_va, mmu.pwin_pte_pa, 0, 1); + } + + /* + * Walk the boot loader's page tables and figure out + * how many tables and page mappings there will be. + */ + while (kbm_probe(&va, &size, &pfn, &prot) != 0) { + /* + * At each level, if the last_va falls into a new htable, + * increment table_cnt. We can stop at the 1st level where + * they are in the same htable. + */ + if (size == MMU_PAGESIZE) + start_level = 0; + else + start_level = 1; + + for (l = start_level; l < mmu.max_level; ++l) { + if (va >> LEVEL_SHIFT(l + 1) == + last_va >> LEVEL_SHIFT(l + 1)) + break; + ++table_cnt; + } + last_va = va; + va = (va & LEVEL_MASK(1)) + LEVEL_SIZE(1); + } + + /* + * Besides the boot loader mappings, we're going to fill in + * the entire top level page table for the kernel. Make sure there's + * enough reserve for that too. + */ + table_cnt += mmu.top_level_count - ((kernelbase >> + LEVEL_SHIFT(mmu.max_level)) & (mmu.top_level_count - 1)); + +#if defined(__i386) + /* + * The 32 bit PAE hat allocates tables one level below the top when + * kernelbase isn't 1 Gig aligned. We'll just be sloppy and allocate + * a bunch more to the reserve. Any unused will be returned later. + * Note we've already counted these mappings, just not the extra + * pagetables. + */ + if (mmu.pae_hat != 0 && (kernelbase & LEVEL_OFFSET(mmu.max_level)) != 0) + table_cnt += mmu.ptes_per_table - + ((kernelbase & LEVEL_OFFSET(mmu.max_level)) >> + LEVEL_SHIFT(mmu.max_level - 1)); +#endif + + /* + * Add 1/4 more into table_cnt for extra slop. The unused + * slop is freed back when we htable_adjust_reserve() later. + */ + table_cnt += table_cnt >> 2; + + /* + * We only need mapping entries (hments) for shared pages. + * This should be far, far fewer than the total possible, + * We'll allocate enough for 1/16 of all possible PTEs. + */ + mapping_cnt = (table_cnt * mmu.ptes_per_table) >> 4; + + /* + * Now create the initial htable/hment reserves + */ + htable_initial_reserve(table_cnt); + hment_reserve(mapping_cnt); + x86pte_cpu_init(CPU); +} + + +/* + * This routine handles the work of creating the kernel's initial mappings + * by deciphering the mappings in the page tables created by the boot program. + * + * We maintain large page mappings, but only to a level 1 pagesize. + * The boot loader can only add new mappings once this function starts. + * In particular it can not change the pagesize used for any existing + * mappings or this code breaks! + */ + +void +hat_kern_setup(void) +{ + /* + * Attach htables to the existing pagetables + */ + htable_attach(kas.a_hat, 0, mmu.max_level, NULL, + mmu_btop(getcr3())); + +#if defined(__i386) + CPU->cpu_tss->tss_cr3 = dftss0.tss_cr3 = getcr3(); +#endif /* __i386 */ + + /* + * The kernel HAT is now officially open for business. + */ + khat_running = 1; + + CPUSET_ATOMIC_ADD(kas.a_hat->hat_cpus, CPU->cpu_id); + CPU->cpu_current_hat = kas.a_hat; +} diff --git a/usr/src/uts/i86pc/vm/kboot_mmu.c b/usr/src/uts/i86pc/vm/kboot_mmu.c new file mode 100644 index 0000000000..fdf7e85460 --- /dev/null +++ b/usr/src/uts/i86pc/vm/kboot_mmu.c @@ -0,0 +1,420 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/archsystm.h> +#include <sys/debug.h> +#include <sys/bootconf.h> +#include <sys/bootsvcs.h> +#include <sys/bootinfo.h> +#include <sys/mman.h> +#include <sys/cmn_err.h> +#include <sys/param.h> +#include <sys/machparam.h> +#include <sys/machsystm.h> +#include <sys/promif.h> +#include <sys/kobj.h> +#include <vm/kboot_mmu.h> +#include <vm/hat_pte.h> +#include <vm/hat_i86.h> +#include <vm/seg_kmem.h> + +#if 0 +/* + * Joe's debug printing + */ +#define DBG(x) \ + bop_printf(NULL, "boot_mmu.c: %s is %" PRIx64 "\n", #x, (uint64_t)(x)); +#else +#define DBG(x) /* naught */ +#endif + +/* + * Page table and memory stuff. + */ +static caddr_t window; +static caddr_t pte_to_window; + +/* + * this are needed by mmu_init() + */ +int kbm_nx_support = 0; /* NX bit in PTEs is in use */ +int kbm_pae_support = 0; /* PAE is 64 bit Page table entries */ +int kbm_pge_support = 0; /* PGE is Page table global bit enabled */ +int kbm_largepage_support = 0; +uint_t kbm_nucleus_size = 0; + +#define BOOT_SHIFT(l) (shift_amt[l]) +#define BOOT_SZ(l) ((size_t)1 << BOOT_SHIFT(l)) +#define BOOT_OFFSET(l) (BOOT_SZ(l) - 1) +#define BOOT_MASK(l) (~BOOT_OFFSET(l)) + +/* + * Initialize memory management parameters for boot time page table management + */ +void +kbm_init(struct xboot_info *bi) +{ + /* + * configure mmu information + */ + kbm_nucleus_size = (uintptr_t)bi->bi_kseg_size; + kbm_largepage_support = bi->bi_use_largepage; + kbm_nx_support = bi->bi_use_nx; + kbm_pae_support = bi->bi_use_pae; + kbm_pge_support = bi->bi_use_pge; + window = bi->bi_pt_window; + DBG(window); + pte_to_window = bi->bi_pte_to_pt_window; + DBG(pte_to_window); + if (kbm_pae_support) { + shift_amt = shift_amt_pae; + ptes_per_table = 512; + pte_size = 8; + lpagesize = TWO_MEG; +#ifdef __amd64 + top_level = 3; +#else + top_level = 2; +#endif + } else { + shift_amt = shift_amt_nopae; + ptes_per_table = 1024; + pte_size = 4; + lpagesize = FOUR_MEG; + top_level = 1; + } + + top_page_table = bi->bi_top_page_table; + DBG(top_page_table); +} + +/* + * Change the addressible page table window to point at a given page + */ +/*ARGSUSED*/ +void * +kbm_remap_window(paddr_t physaddr, int writeable) +{ + uint_t pt_bits = PT_NOCONSIST | PT_VALID | PT_WRITABLE; + + DBG(physaddr); + + if (kbm_pae_support) + *((x86pte_t *)pte_to_window) = physaddr | pt_bits; + else + *((x86pte32_t *)pte_to_window) = physaddr | pt_bits; + mmu_tlbflush_entry(window); + DBG(window); + return (window); +} + +/* + * Add a mapping for the physical page at the given virtual address. + */ +void +kbm_map(uintptr_t va, paddr_t pa, uint_t level, uint_t is_kernel) +{ + x86pte_t *ptep; + paddr_t pte_physaddr; + x86pte_t pteval; + + if (khat_running) + panic("kbm_map() called too late"); + + pteval = pa_to_ma(pa) | PT_NOCONSIST | PT_VALID | PT_WRITABLE; + if (level == 1) + pteval |= PT_PAGESIZE; + if (kbm_pge_support && is_kernel) + pteval |= PT_GLOBAL; + + /* + * Find the pte that will map this address. This creates any + * missing intermediate level page tables. + */ + ptep = find_pte(va, &pte_physaddr, level, 0); + if (ptep == NULL) + bop_panic("kbm_map: find_pte returned NULL"); + + if (kbm_pae_support) + *ptep = pteval; + else + *((x86pte32_t *)ptep) = pteval; + mmu_tlbflush_entry((caddr_t)va); +} + +/* + * Probe the boot time page tables to find the first mapping + * including va (or higher) and return non-zero if one is found. + * va is updated to the starting address and len to the pagesize. + * pp will be set to point to the 1st page_t of the mapped page(s). + * + * Note that if va is in the middle of a large page, the returned va + * will be less than what was asked for. + */ +int +kbm_probe(uintptr_t *va, size_t *len, pfn_t *pfn, uint_t *prot) +{ + uintptr_t probe_va; + x86pte_t *ptep; + paddr_t pte_physaddr; + x86pte_t pte_val; + level_t l; + + if (khat_running) + panic("kbm_probe() called too late"); + *len = 0; + *pfn = PFN_INVALID; + *prot = 0; + probe_va = *va; +restart_new_va: + l = top_level; + for (;;) { + if (IN_VA_HOLE(probe_va)) + probe_va = mmu.hole_end; + + if (IN_HYPERVISOR_VA(probe_va)) + return (0); + + /* + * If we don't have a valid PTP/PTE at this level + * then we can bump VA by this level's pagesize and try again. + * When the probe_va wraps around, we are done. + */ + ptep = find_pte(probe_va, &pte_physaddr, l, 1); + if (ptep == NULL) + bop_panic("kbm_probe: find_pte returned NULL"); + if (kbm_pae_support) + pte_val = *ptep; + else + pte_val = *((x86pte32_t *)ptep); + if (!PTE_ISVALID(pte_val)) { + probe_va = (probe_va & BOOT_MASK(l)) + BOOT_SZ(l); + if (probe_va <= *va) + return (0); + goto restart_new_va; + } + + /* + * If this entry is a pointer to a lower level page table + * go down to it. + */ + if (!PTE_ISPAGE(pte_val, l)) { + ASSERT(l > 0); + --l; + continue; + } + + /* + * We found a boot level page table entry + */ + *len = BOOT_SZ(l); + *va = probe_va & ~(*len - 1); + *pfn = PTE2PFN(pte_val, l); + + + *prot = PROT_READ | PROT_EXEC; + if (PTE_GET(pte_val, PT_WRITABLE)) + *prot |= PROT_WRITE; + + /* + * pt_nx is cleared if processor doesn't support NX bit + */ + if (PTE_GET(pte_val, mmu.pt_nx)) + *prot &= ~PROT_EXEC; + + return (1); + } +} + + +/* + * Destroy a boot loader page table 4K mapping. + */ +void +kbm_unmap(uintptr_t va) +{ + if (khat_running) + panic("kbm_unmap() called too late"); + else { + x86pte_t *ptep; + level_t level = 0; + uint_t probe_only = 1; + + ptep = find_pte(va, NULL, level, probe_only); + if (ptep == NULL) + return; + + if (kbm_pae_support) + *ptep = 0; + else + *((x86pte32_t *)ptep) = 0; + mmu_tlbflush_entry((caddr_t)va); + } +} + + +/* + * Change a boot loader page table 4K mapping. + * Returns the pfn of the old mapping. + */ +pfn_t +kbm_remap(uintptr_t va, pfn_t pfn) +{ + x86pte_t *ptep; + level_t level = 0; + uint_t probe_only = 1; + x86pte_t pte_val = pa_to_ma(pfn_to_pa(pfn)) | PT_WRITABLE | + PT_NOCONSIST | PT_VALID; + x86pte_t old_pte; + + if (khat_running) + panic("kbm_remap() called too late"); + ptep = find_pte(va, NULL, level, probe_only); + if (ptep == NULL) + bop_panic("kbm_remap: find_pte returned NULL"); + + if (kbm_pae_support) + old_pte = *ptep; + else + old_pte = *((x86pte32_t *)ptep); + + if (kbm_pae_support) + *((x86pte_t *)ptep) = pte_val; + else + *((x86pte32_t *)ptep) = pte_val; + mmu_tlbflush_entry((caddr_t)va); + + if (!(old_pte & PT_VALID) || ma_to_pa(old_pte) == -1) + return (PFN_INVALID); + return (mmu_btop(ma_to_pa(old_pte))); +} + + +/* + * Change a boot loader page table 4K mapping to read only. + */ +void +kbm_read_only(uintptr_t va, paddr_t pa) +{ + x86pte_t pte_val = pa_to_ma(pa) | + PT_NOCONSIST | PT_REF | PT_MOD | PT_VALID; + x86pte_t *ptep; + level_t level = 0; + + ptep = find_pte(va, NULL, level, 0); + if (ptep == NULL) + bop_panic("kbm_read_only: find_pte returned NULL"); + + if (kbm_pae_support) + *ptep = pte_val; + else + *((x86pte32_t *)ptep) = pte_val; + mmu_tlbflush_entry((caddr_t)va); +} + +/* + * interfaces for kernel debugger to access physical memory + */ +static x86pte_t save_pte; + +void * +kbm_push(paddr_t pa) +{ + static int first_time = 1; + + if (first_time) { + first_time = 0; + return (window); + } + + if (kbm_pae_support) + save_pte = *((x86pte_t *)pte_to_window); + else + save_pte = *((x86pte32_t *)pte_to_window); + return (kbm_remap_window(pa, 0)); +} + +void +kbm_pop(void) +{ + if (kbm_pae_support) + *((x86pte_t *)pte_to_window) = save_pte; + else + *((x86pte32_t *)pte_to_window) = save_pte; + mmu_tlbflush_entry(window); +} + +x86pte_t +get_pteval(paddr_t table, uint_t index) +{ + void *table_ptr = kbm_remap_window(table, 0); + + if (kbm_pae_support) + return (((x86pte_t *)table_ptr)[index]); + return (((x86pte32_t *)table_ptr)[index]); +} + +void +set_pteval(paddr_t table, uint_t index, uint_t level, x86pte_t pteval) +{ + void *table_ptr = kbm_remap_window(table, 0); + if (kbm_pae_support) + ((x86pte_t *)table_ptr)[index] = pteval; + else + ((x86pte32_t *)table_ptr)[index] = pteval; + if (level == top_level && level == 2) + reload_cr3(); +} + +paddr_t +make_ptable(x86pte_t *pteval, uint_t level) +{ + paddr_t new_table; + void *table_ptr; + + new_table = do_bop_phys_alloc(MMU_PAGESIZE, MMU_PAGESIZE); + table_ptr = kbm_remap_window(new_table, 1); + bzero(table_ptr, MMU_PAGESIZE); + + if (level == top_level && level == 2) + *pteval = pa_to_ma(new_table) | PT_VALID; + else + *pteval = pa_to_ma(new_table) | + PT_VALID | PT_REF | PT_USER | PT_WRITABLE; + + return (new_table); +} + +x86pte_t * +map_pte(paddr_t table, uint_t index) +{ + void *table_ptr = kbm_remap_window(table, 0); + return ((x86pte_t *)((caddr_t)table_ptr + index * pte_size)); +} diff --git a/usr/src/uts/i86pc/vm/kboot_mmu.h b/usr/src/uts/i86pc/vm/kboot_mmu.h new file mode 100644 index 0000000000..8c34ad2187 --- /dev/null +++ b/usr/src/uts/i86pc/vm/kboot_mmu.h @@ -0,0 +1,106 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _KBOOT_MMU_H +#define _KBOOT_MMU_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Kernel boot-time interfaces for handling MMU mappings before the HAT proper + * is running (i.e. before khat_running is set). + */ + +#include <sys/mach_mmu.h> + +struct xboot_info; + +extern void kbm_init(struct xboot_info *); + +/* + * Interface to remap the page table window, also used by HAT during init. + */ +extern void *kbm_remap_window(paddr_t physaddr, int writeable); + +/* + * Find the next mapping at or above VA, if found returns non-zero and sets: + * - va : virtual address + * - pfn : pfn of real address + * - size : pagesize of the mapping + * - prot : protections + */ +extern int kbm_probe(uintptr_t *va, size_t *len, pfn_t *pfn, uint_t *prot); + +/* + * Add a new mapping + */ +extern void kbm_map(uintptr_t va, paddr_t pa, uint_t level, uint_t is_kernel); + +/* + * unmap a single 4K page at VA + */ +extern void kbm_unmap(uintptr_t va); + +/* + * Remap a single 4K page at VA (always PROT_READ|PROT_WRITE). + * Returns the pfn of the old mapping. + */ +extern pfn_t kbm_remap(uintptr_t va, pfn_t pfn); + +/* + * Make a page mapping read only + */ +extern void kbm_read_only(uintptr_t va, paddr_t pa); + + +/* + * interface for kmdb to map a physical page, stack is only 1 deep + */ +extern void *kbm_push(paddr_t pa); +extern void kbm_pop(void); + +/* + * These are needed by mmu_init() + */ +extern int kbm_nx_support; +extern int kbm_pae_support; +extern int kbm_largepage_support; + +/* + * The size of memory mapped for the initial kernel nucleus text + * and data regions setup by the boot loader. needed for startup + */ +extern uint_t kbm_nucleus_size; + +#ifdef __cplusplus +} +#endif + +#endif /* _KBOOT_MMU_H */ diff --git a/usr/src/uts/i86pc/vm/mach_i86mmu.c b/usr/src/uts/i86pc/vm/mach_i86mmu.c deleted file mode 100644 index 2e7e305e2e..0000000000 --- a/usr/src/uts/i86pc/vm/mach_i86mmu.c +++ /dev/null @@ -1,708 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/t_lock.h> -#include <sys/memlist.h> -#include <sys/cpuvar.h> -#include <sys/vmem.h> -#include <sys/mman.h> -#include <sys/vm.h> -#include <sys/kmem.h> -#include <sys/cmn_err.h> -#include <sys/debug.h> -#include <sys/vm_machparam.h> -#include <sys/tss.h> -#include <sys/vnode.h> -#include <vm/hat.h> -#include <vm/anon.h> -#include <vm/as.h> -#include <vm/page.h> -#include <vm/seg.h> -#include <vm/seg_kmem.h> -#include <vm/seg_map.h> -#include <vm/hat_i86.h> -#include <sys/promif.h> -#include <sys/x86_archext.h> -#include <sys/systm.h> -#include <sys/archsystm.h> -#include <sys/sunddi.h> -#include <sys/ddidmareq.h> -#include <sys/controlregs.h> -#include <sys/reboot.h> -#include <sys/kdi.h> - -caddr_t -i86devmap(pfn_t pf, pgcnt_t pgcnt, uint_t prot) -{ - caddr_t addr; - caddr_t addr1; - page_t *pp; - - addr1 = addr = vmem_alloc(heap_arena, mmu_ptob(pgcnt), VM_SLEEP); - - for (; pgcnt != 0; addr += MMU_PAGESIZE, ++pf, --pgcnt) { - pp = page_numtopp_nolock(pf); - if (pp == NULL) { - hat_devload(kas.a_hat, addr, MMU_PAGESIZE, pf, - prot | HAT_NOSYNC, HAT_LOAD_LOCK); - } else { - hat_memload(kas.a_hat, addr, pp, - prot | HAT_NOSYNC, HAT_LOAD_LOCK); - } - } - - return (addr1); -} - -/* - * This routine is like page_numtopp, but accepts only free pages, which - * it allocates (unfrees) and returns with the exclusive lock held. - * It is used by machdep.c/dma_init() to find contiguous free pages. - */ -page_t * -page_numtopp_alloc(pfn_t pfnum) -{ - page_t *pp; - -retry: - pp = page_numtopp_nolock(pfnum); - if (pp == NULL) { - return (NULL); - } - - if (!page_trylock(pp, SE_EXCL)) { - return (NULL); - } - - if (page_pptonum(pp) != pfnum) { - page_unlock(pp); - goto retry; - } - - if (!PP_ISFREE(pp)) { - page_unlock(pp); - return (NULL); - } - if (pp->p_szc) { - page_demote_free_pages(pp); - page_unlock(pp); - goto retry; - } - - /* If associated with a vnode, destroy mappings */ - - if (pp->p_vnode) { - - page_destroy_free(pp); - - if (!page_lock(pp, SE_EXCL, (kmutex_t *)NULL, P_NO_RECLAIM)) { - return (NULL); - } - - if (page_pptonum(pp) != pfnum) { - page_unlock(pp); - goto retry; - } - } - - if (!PP_ISFREE(pp) || !page_reclaim(pp, (kmutex_t *)NULL)) { - page_unlock(pp); - return (NULL); - } - - return (pp); -} - -/* - * The boot loader doesn't use PAE page tables for 32 bit platforms - * so the definitions in hat_pte for LEVEL_SHIFT, etc. don't apply. - */ -#if defined(__i386) /* 32 bit boot loader */ - -#define BOOT_TOP_LEVEL 1 -#define BOOT_PTES_PER_TABLE 1024 -#define BOOT_PADDR 0xfffff000 -static uint_t boot_shift[] = {12, 22}; - -#elif defined(__amd64) /* 64 bit boot loader */ - -#define BOOT_TOP_LEVEL 3 -#define BOOT_PTES_PER_TABLE 512 -static uint_t boot_shift[] = {12, 21, 30, 39}; -#define BOOT_PADDR PT_PADDR /* boot won't use PAT, so this is ok */ - -#endif /* __amd64 */ - -#define BOOT_SHIFT(l) (boot_shift[l]) -#define BOOT_SZ(l) ((size_t)1 << BOOT_SHIFT(l)) -#define BOOT_OFFSET(l) (BOOT_SZ(l) - 1) -#define BOOT_MASK(l) (~BOOT_OFFSET(l)) - -/* - * Flag is not set early in boot. Once it is set we are no longer - * using boot's page tables. - */ -uint_t khat_running = 0; - - -/* - * Probe the boot loader's page tables to find the first mapping - * including va (or higher) and return non-zero if one is found. - * va is updated to the starting address and len to the pagesize. - * pp will be set to point to the 1st page_t of the mapped page(s). - * - * Note that if va is in the middle of a large page, the returned va - * will be less than what was asked for. - * - * This works by walking the actual page table's currently in use - * and rooted at control register 3. This code has the following fundamental - * assumptions: - * - In 32 bit mode the boot loader never uses PAE, so the size/type - * of boot pte_t is compatibile with uintptr_t - * - The 64 bit mode boot loader has enabled NX bit usage - * - The pagetables allocated by boot have identity mappings, ie. - * Virtual address == Physical address - */ -int -hat_boot_probe(uintptr_t *va, size_t *len, pfn_t *pfn, uint_t *prot) -{ - uintptr_t probe_va; - uint_t entry; - uintptr_t *top_ptable; - uintptr_t *ptable; - level_t l = BOOT_TOP_LEVEL; - - *len = 0; - *pfn = PFN_INVALID; - *prot = 0; - probe_va = *va; - top_ptable = (uintptr_t *)(getcr3() & MMU_PAGEMASK); -restart_new_va: - l = BOOT_TOP_LEVEL; - ptable = top_ptable; - for (;;) { - if (IN_VA_HOLE(probe_va)) - probe_va = mmu.hole_end; - - /* - * If we don't have a valid PTP/PTE at this level - * then we can bump VA by this level's pagesize and try again. - * When the probe_va wraps around, we are done. - */ - entry = (probe_va >> BOOT_SHIFT(l)) & (BOOT_PTES_PER_TABLE - 1); - if (!PTE_ISVALID(ptable[entry])) { - probe_va = (probe_va & BOOT_MASK(l)) + BOOT_SZ(l); - if (probe_va <= *va) - return (0); - goto restart_new_va; - } - - /* - * If this entry is a pointer to a lower level page table - * go down to it. - */ - if (!PTE_ISPAGE(ptable[entry], l)) { - ASSERT(l > 0); - --l; - ptable = (uintptr_t *)(ptable[entry] & MMU_PAGEMASK); - continue; - } - - /* - * We found a boot level page table entry - */ - *len = BOOT_SZ(l); - *va = probe_va & ~(*len - 1); - *pfn = mmu_btop(ptable[entry] & BOOT_PADDR); - - - *prot = PROT_READ | PROT_EXEC; - if (PTE_GET(ptable[entry], PT_WRITABLE)) - *prot |= PROT_WRITE; - - /* - * pt_nx is cleared if processor doesn't support NX bit - */ - if (PTE_GET(ptable[entry], mmu.pt_nx)) - *prot &= ~PROT_EXEC; - - return (1); - } -} - - -/* - * Destroy a boot loader page table 4K mapping. - * See hat_boot_probe() for assumptions. - */ -void -hat_boot_demap(uintptr_t va) -{ - uintptr_t *ptable; - level_t level = BOOT_TOP_LEVEL; - uint_t entry; - - /* - * Walk down the page tables, which are 1 to 1 mapped, to the - * desired mapping. - */ - ptable = (uintptr_t *)(getcr3() & MMU_PAGEMASK); - for (level = BOOT_TOP_LEVEL; ; --level) { - - entry = (va >> BOOT_SHIFT(level)) & (BOOT_PTES_PER_TABLE - 1); - - if (!PTE_ISVALID(ptable[entry])) - panic("hat_boot_demap(): no pte at desired addr"); - - if (level == 0) - break; - - if (PTE_ISPAGE(ptable[entry], level)) - panic("hat_boot_demap(): large page at va"); - - ptable = (uintptr_t *)(ptable[entry] & MMU_PAGEMASK); - } - - /* - * We found a boot level page table entry, invalidate it - */ - ptable[entry] = 0; - mmu_tlbflush_entry((caddr_t)va); -} - - -/* - * Change a boot loader page table 4K mapping. - * Returns the pfn of the old mapping. - * See hat_boot_probe() for assumptions. - */ -pfn_t -hat_boot_remap(uintptr_t va, pfn_t pfn) -{ - uintptr_t *ptable; - level_t level = BOOT_TOP_LEVEL; - pfn_t old_pfn; - uint_t entry; - - /* - * Walk down the page tables, which are 1 to 1 mapped, to the - * desired mapping. - */ - ptable = (uintptr_t *)(getcr3() & MMU_PAGEMASK); - for (level = BOOT_TOP_LEVEL; ; --level) { - - entry = (va >> BOOT_SHIFT(level)) & (BOOT_PTES_PER_TABLE - 1); - - if (level == 0) - break; - - if (!PTE_ISVALID(ptable[entry])) - panic("hat_boot_remap(): no pte at desired addr"); - - if (PTE_ISPAGE(ptable[entry], level)) - panic("hat_boot_remap(): large page at va"); - - ptable = (uintptr_t *)(ptable[entry] & MMU_PAGEMASK); - } - - /* - * We found a boot level page table entry, change it and return - * the old pfn. Assume full permissions. - */ - old_pfn = mmu_btop(ptable[entry] & BOOT_PADDR); - ptable[entry] = mmu_ptob((uintptr_t)pfn) | PT_VALID | PT_WRITABLE; - mmu_tlbflush_entry((caddr_t)va); - return (old_pfn); -} - -/* - * This procedure is callable only while the boot loader is in charge - * of the MMU. It assumes that PA == VA for page table pointers. - */ -pfn_t -va_to_pfn(void *vaddr) -{ - uintptr_t des_va = ALIGN2PAGE(vaddr); - uintptr_t va = des_va; - size_t len; - uint_t prot; - pfn_t pfn; - - if (khat_running) - panic("va_to_pfn(): called too late\n"); - - if (hat_boot_probe(&va, &len, &pfn, &prot) == 0) - return (PFN_INVALID); - if (va > des_va) - return (PFN_INVALID); - if (va < des_va) - pfn += mmu_btop(des_va - va); - return (pfn); -} - -/* - * Routine to pre-allocate any htable's and hments that should be needed in - * hat_kern_setup(). It computes how many pagetables it needs by walking the - * boot loader's page tables. - */ -void -hat_kern_alloc() -{ - uintptr_t last_va = (uintptr_t)-1; /* catch 1st time */ - uintptr_t va = 0; - size_t size; - pfn_t pfn; - uint_t prot; - uint_t table_cnt = 1; - uint_t mapping_cnt; - level_t start_level; - level_t l; - extern pgcnt_t npages; - extern pgcnt_t boot_npages; - - /* - * Walk the boot loader's page tables and figure out - * how many tables and page mappings there will be. - */ - while (hat_boot_probe(&va, &size, &pfn, &prot) != 0) { - /* - * At each level, if the last_va falls into a new htable, - * increment table_cnt. We can stop at the 1st level where - * they are in the same htable. - */ - if (size == MMU_PAGESIZE) - start_level = 0; - else - start_level = 1; - - for (l = start_level; l < mmu.max_level; ++l) { - if (va >> LEVEL_SHIFT(l + 1) == - last_va >> LEVEL_SHIFT(l + 1)) - break; - ++table_cnt; - } - last_va = va; - va += size; - } - - /* - * Besides the boot loader mappings, we're going to fill in - * the entire top level page table for the kernel. Make sure there's - * enough reserve for that too. - */ - table_cnt += mmu.top_level_count - ((kernelbase >> - LEVEL_SHIFT(mmu.max_level)) & (mmu.top_level_count - 1)); - - /* - * If we still have pages that need page_t's created for them, then - * make sure we create the pagetables needed to map them in. - * - * (yes. We need pagetables to map the page_t's for the unmapped - * pages. We also need pagetables to map the vmem structures - * allocated to support the VA range into which they are mapped. - * Does your head hurt yet?) - */ - if (boot_npages < npages) { - pgcnt_t pages; - pgcnt_t ptables; - - /* - * Number of pages needed for all the new pages_ts. This - * assumes that they will all be mapped consecutively. - */ - pages = (npages - boot_npages) / sizeof (page_t); - - /* - * Number of level 0 pagetables needed to map these pages. - * The '+1' is to handle the likely case that the address - * range doesn't align with a pagetable boundary. - */ - ptables = pages / mmu.ptes_per_table + 1; - - /* - * We also add in some extra to account for the higher level - * pagetables and for the vmem structures that get - * allocated along the way. - */ - table_cnt += (ptables * 3); - } - -#if defined(__i386) - /* - * The 32 bit PAE hat allocates tables one level below the top when - * kernelbase isn't 1 Gig aligned. We'll just be sloppy and allocate - * a bunch more to the reserve. Any unused will be returned later. - * Note we've already counted these mappings, just not the extra - * pagetables. - */ - if (mmu.pae_hat != 0 && (kernelbase & LEVEL_OFFSET(mmu.max_level)) != 0) - table_cnt += mmu.ptes_per_table - - ((kernelbase & LEVEL_OFFSET(mmu.max_level)) >> - LEVEL_SHIFT(mmu.max_level - 1)); -#endif - - /* - * Add 1/4 more into table_cnt for extra slop. The unused - * slop is freed back when we htable_adjust_reserve() later. - */ - table_cnt += table_cnt >> 2; - - /* - * We only need mapping entries (hments) for shared pages. - * This should be far, far fewer than the total possible, - * We'll allocate enough for 1/16 of all possible PTEs. - */ - mapping_cnt = (table_cnt * mmu.ptes_per_table) >> 4; - - /* - * Now create the initial htable/hment reserves - */ - htable_initial_reserve(table_cnt); - hment_reserve(mapping_cnt); -} - -extern void enable_pae(uintptr_t); -extern void setup_121_andcall(); - -/* - * We need to setup a 1:1 (virtual to physical) mapping for the - * page containing enable_pae() in the new kernel hat. - */ -void -activate_pae(void *pages) -{ -#if defined(__amd64) - int turning_on_pae = 0; /* it's already on */ -#elif defined(__i386) - pfn_t pfn; - uintptr_t va_1to1; - htable_t *ht; - uint_t entry; - int turning_on_pae = mmu.pae_hat; -#endif - - if (!turning_on_pae) { - /* - * Finish setup for x86pte_access_pagetable() - */ - x86pte_cpu_init(CPU, pages); - - /* - * switch off of boot's page tables onto the ones we've built - */ - setcr3(MAKECR3(kas.a_hat->hat_htable->ht_pfn)); - khat_running = 1; - return; - } - -#if defined(__i386) - if (PFN_ABOVE4G(kas.a_hat->hat_htable->ht_pfn)) - panic("cr3 value would be > 4G on 32 bit PAE"); - - /* - * find the htable containing the physical address that would be - * an identity mapping for enable_pae, save the current pte, - * then fill in the identity mapping - */ - pfn = va_to_pfn((void *)enable_pae); - - if (pfn == PFN_INVALID) - panic("activate_pae(): va_to_pfn(enable_pae) failed"); - va_1to1 = mmu_ptob(pfn) + - ((uintptr_t)(void *)enable_pae & MMU_PAGEOFFSET); - - ht = htable_create(kas.a_hat, va_1to1, 0, NULL); - - if (ht == NULL || ht->ht_level != 0) - panic("no htable va %p pfn %lx", (void *)va_1to1, pfn); - entry = htable_va2entry(va_1to1, ht); - if (x86pte_get(ht, entry) != 0) - panic("pte used at va %p", (void *)va_1to1); - (void) x86pte_set(ht, entry, MAKEPTE(pfn, 0) | PT_WRITABLE, NULL); - - /* - * Finish setup for x86pte_access_pagetable(), this has to be - * done after the last reference to a newly built page table and - * before switching to the newly built pagetables. - */ - x86pte_cpu_init(CPU, pages); - - /* - * now switch to kernel hat activating PAE - */ - setup_121_andcall(enable_pae, MAKECR3(kas.a_hat->hat_htable->ht_pfn)); - khat_running = 1; - - /* - * release the mapping we used for the kernel hat - */ - (void) x86pte_set(ht, entry, 0, NULL); - mmu_tlbflush_entry((caddr_t)va_1to1); - htable_release(ht); -#endif /* __i386 */ -} - - -/* - * Function to set the EFER.NXE bit if we want to use No eXecute. - * Note that since this is called from manually relocated code from - * mpcore.s, we have to use an indirect call with set_nxe_func. - * This is due to the "call" instruction always being PC relative, - * unless you go through an indirect pointer in memory. - */ -static void -set_nxe(void) -{ - if (mmu.pt_nx == 0) - return; - - /* - * AMD64 EFER is model specific register #0xc0000080 and NXE is bit 11 - */ - wrmsr(MSR_AMD_EFER, rdmsr(MSR_AMD_EFER) | - (uint64_t)(uintptr_t)AMD_EFER_NXE); -} - -void (*set_nxe_func)(void) = set_nxe; - -/* - * This routine handles the work of creating the kernel's initial mappings - * by deciphering the mappings in the page tables created by the boot program. - * - * We maintain large page mappings, but only to a level 1 pagesize. - * The boot loader can only add new mappings once this function starts. - * In particular it can not change the pagesize used for any existing - * mappings or this code breaks! - */ - -uint_t hks_debug = 0; -#define HKS_DBG if (hks_debug) prom_printf - -void -hat_kern_setup(void) -{ - uintptr_t last_va; - uintptr_t va; - size_t last_size; - size_t size; - uint_t last_prot = 0; - uint_t prot; - pfn_t last_pfn = PFN_INVALID; - pfn_t pfn; - pgcnt_t cnt = 0; - void *pages; - - /* - * activate AMD processor NX bit support - */ - if (mmu.pt_nx != 0) - set_nxe(); - - /* - * Allocate 3 initial page addresses for x86pte_cpu_init(). - */ - pages = vmem_xalloc(heap_arena, 3 * MMU_PAGESIZE, MMU_PAGESIZE, 0, - LEVEL_SIZE(1), NULL, NULL, VM_SLEEP); - - /* - * next allocate the kernel hat's top level - */ - kas.a_hat->hat_htable = - htable_create(kas.a_hat, 0, mmu.max_level, NULL); - - /* - * Now walk through the address space copying all the page mappings. - */ - va = 0; - last_va = 1; /* so va doesn't match on the 1st page */ - last_size = 0; - cnt = 0; -#ifdef DEBUG - HKS_DBG(" Start VA / PERM / PFN / # Mappings\n"); -#endif - while (hat_boot_probe(&va, &size, &pfn, &prot) != 0) { - - if (va == last_va + (last_size * cnt) && - pfn == last_pfn + ((va - last_va) >> PAGESHIFT) && - last_prot == prot && - last_size == size) { - ++cnt; - } else { - if (cnt) { -#ifdef DEBUG - HKS_DBG(" %p", (void *)last_va); - HKS_DBG(last_size > MMU_PAGESIZE ? - " / L" : " / -"); - HKS_DBG(last_prot & PROT_READ ? " R" : " -"); - HKS_DBG(last_prot & PROT_WRITE ? "W" : "-"); - HKS_DBG(last_prot & PROT_EXEC ? "X" : "-"); - HKS_DBG(" / %lx", last_pfn); - HKS_DBG(" / %ld\n", cnt); - if (va != last_va + (last_size * cnt)) - HKS_DBG("----skip----\n"); -#endif /* DEBUG */ - hati_kern_setup_load(last_va, last_size, - last_pfn, cnt, last_prot); - } - last_va = va; - last_size = size; - last_pfn = pfn; - last_prot = prot; - cnt = 1; - } - va += size; - } - - if (cnt != 0) { -#ifdef DEBUG - HKS_DBG(" %p", (void *)last_va); - HKS_DBG(last_size > MMU_PAGESIZE ? " / L" : " / -"); - HKS_DBG(last_prot & PROT_READ ? " R" : " -"); - HKS_DBG(last_prot & PROT_WRITE ? "W" : "-"); - HKS_DBG(last_prot & PROT_EXEC ? "X" : "-"); - HKS_DBG(" / %lx", last_pfn); - HKS_DBG(" / %ld\n", cnt); -#endif - hati_kern_setup_load(last_va, last_size, last_pfn, cnt, - last_prot); - } - -#if defined(__i386) - CPU->cpu_tss->tss_cr3 = dftss0.tss_cr3 = - MAKECR3(kas.a_hat->hat_htable->ht_pfn); -#endif /* __i386 */ - - /* - * Now switch cr3 to the newly built page tables. This includes - * turning on PAE for 32 bit if necessary. - */ - activate_pae(pages); - - CPUSET_ATOMIC_ADD(kas.a_hat->hat_cpus, CPU->cpu_id); - CPU->cpu_current_hat = kas.a_hat; -} diff --git a/usr/src/uts/i86pc/vm/vm_dep.h b/usr/src/uts/i86pc/vm/vm_dep.h index ec5177b86b..b95f6b8e17 100644 --- a/usr/src/uts/i86pc/vm/vm_dep.h +++ b/usr/src/uts/i86pc/vm/vm_dep.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,6 +38,7 @@ extern "C" { #include <sys/clock.h> #include <vm/hat_pte.h> +#include <sys/param.h> /* * WARNING: vm_dep.h is included by files in common. As such, macros @@ -333,7 +334,7 @@ extern page_t *page_get_mnode_cachelist(uint_t, uint_t, int, int); #define PP_2_BIN(pp) (PP_2_BIN_SZC(pp, pp->p_szc)) #define PP_2_MEM_NODE(pp) (PFN_2_MEM_NODE(pp->p_pagenum)) -#define PP_2_MTYPE(pp) (pfn_2_mtype(pp->p_pagenum)) +#define PP_2_MTYPE(pp) (pfn_2_mtype(pfn_to_mfn(pp->p_pagenum))) #define PP_2_SZC(pp) (pp->p_szc) #define SZCPAGES(szc) (1 << PAGE_BSZS_SHIFT(szc)) diff --git a/usr/src/uts/i86pc/vm/vm_machdep.c b/usr/src/uts/i86pc/vm/vm_machdep.c index 2d87417a56..d274494d8c 100644 --- a/usr/src/uts/i86pc/vm/vm_machdep.c +++ b/usr/src/uts/i86pc/vm/vm_machdep.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -91,8 +91,10 @@ extern uint_t page_create_new; extern uint_t page_create_exists; extern uint_t page_create_putbacks; extern uint_t page_create_putbacks; -extern uintptr_t eprom_kernelbase; -extern int use_sse_pagecopy, use_sse_pagezero; /* in ml/float.s */ +/* + * Allow users to disable the kernel's use of SSE. + */ +extern int use_sse_pagecopy, use_sse_pagezero; /* 4g memory management */ pgcnt_t maxmem4g; @@ -425,7 +427,7 @@ map_addr_vacalign_check(caddr_t addr, u_offset_t off) /* * map_addr_proc() is the routine called when the system is to * choose an address for the user. We will pick an address - * range which is the highest available below kernelbase. + * range which is the highest available below userlimit. * * addrp is a value/result parameter. * On input it is a hint from the user to be used in a completely @@ -667,7 +669,9 @@ valid_usr_range(caddr_t addr, size_t len, uint_t prot, struct as *as, int pf_is_memory(pfn_t pf) { - return (address_in_memlist(phys_install, mmu_ptob((uint64_t)pf), 1)); + if (pfn_is_foreign(pf)) + return (0); + return (address_in_memlist(phys_install, pfn_to_pa(pf), 1)); } @@ -872,10 +876,10 @@ check_dma(ddi_dma_attr_t *dma_attr, page_t *pp, int cnt) return; while (cnt-- > 0) { - if (mmu_ptob((uint64_t)pp->p_pagenum) < + if (pa_to_ma(pfn_to_pa(pp->p_pagenum)) < dma_attr->dma_attr_addr_lo) panic("PFN (pp=%p) below dma_attr_addr_lo", pp); - if (mmu_ptob((uint64_t)pp->p_pagenum) >= + if (pa_to_ma(pfn_to_pa(pp->p_pagenum)) >= dma_attr->dma_attr_addr_hi) panic("PFN (pp=%p) above dma_attr_addr_hi", pp); pp = pp->p_next; @@ -1430,8 +1434,7 @@ page_get_mnode_anylist(ulong_t origbin, uchar_t szc, uint_t flags, ASSERT(pp->p_szc == szc); ASSERT(PFN_2_MEM_NODE(pp->p_pagenum) == mnode); /* check if page within DMA attributes */ - pgaddr = mmu_ptob((uint64_t)(pp->p_pagenum)); - + pgaddr = pa_to_ma(pfn_to_pa(pp->p_pagenum)); if ((pgaddr >= dma_attr->dma_attr_addr_lo) && (pgaddr + MMU_PAGESIZE - 1 <= dma_attr->dma_attr_addr_hi)) { @@ -1519,8 +1522,7 @@ nextfreebin: /* check if page within DMA attributes */ - pgaddr = ptob((uint64_t)(pp->p_pagenum)); - + pgaddr = pa_to_ma(pfn_to_pa(pp->p_pagenum)); if ((pgaddr >= dma_attr->dma_attr_addr_lo) && (pgaddr + MMU_PAGESIZE - 1 <= dma_attr->dma_attr_addr_hi)) { @@ -1844,7 +1846,6 @@ top: delay(10); goto top; } - goto fail; /* undo accounting stuff */ } @@ -1997,8 +1998,8 @@ ppcopy(page_t *frompp, page_t *topp) { caddr_t pp_addr1; caddr_t pp_addr2; - void *pte1; - void *pte2; + hat_mempte_t pte1; + hat_mempte_t pte2; kmutex_t *ppaddr_mutex; label_t ljb; int ret = 1; @@ -2019,8 +2020,8 @@ ppcopy(page_t *frompp, page_t *topp) pp_addr1 = CPU->cpu_caddr1; pp_addr2 = CPU->cpu_caddr2; - pte1 = (void *)CPU->cpu_caddr1pte; - pte2 = (void *)CPU->cpu_caddr2pte; + pte1 = CPU->cpu_caddr1pte; + pte2 = CPU->cpu_caddr2pte; ppaddr_mutex = &CPU->cpu_ppaddr_mutex; mutex_enter(ppaddr_mutex); @@ -2043,8 +2044,9 @@ ppcopy(page_t *frompp, page_t *topp) no_fault(); faulted: - if (!kpm_enable) + if (!kpm_enable) { mutex_exit(ppaddr_mutex); + } kpreempt_enable(); return (ret); } @@ -2060,7 +2062,7 @@ void pagezero(page_t *pp, uint_t off, uint_t len) { caddr_t pp_addr2; - void *pte2; + hat_mempte_t pte2; kmutex_t *ppaddr_mutex; ASSERT_STACK_ALIGNED(); @@ -2076,7 +2078,7 @@ pagezero(page_t *pp, uint_t off, uint_t len) kpreempt_disable(); pp_addr2 = CPU->cpu_caddr2; - pte2 = (void *)CPU->cpu_caddr2pte; + pte2 = CPU->cpu_caddr2pte; ppaddr_mutex = &CPU->cpu_ppaddr_mutex; mutex_enter(ppaddr_mutex); @@ -2086,10 +2088,11 @@ pagezero(page_t *pp, uint_t off, uint_t len) HAT_LOAD_NOCONSIST); } - if (use_sse_pagezero) + if (use_sse_pagezero) { hwblkclr(pp_addr2 + off, len); - else + } else { bzero(pp_addr2 + off, len); + } if (!kpm_enable) mutex_exit(ppaddr_mutex); @@ -2116,21 +2119,39 @@ void setup_vaddr_for_ppcopy(struct cpu *cpup) { void *addr; - void *pte; + hat_mempte_t pte_pa; addr = vmem_alloc(heap_arena, mmu_ptob(1), VM_SLEEP); - pte = hat_mempte_setup(addr); + pte_pa = hat_mempte_setup(addr); cpup->cpu_caddr1 = addr; - cpup->cpu_caddr1pte = (pteptr_t)pte; + cpup->cpu_caddr1pte = pte_pa; addr = vmem_alloc(heap_arena, mmu_ptob(1), VM_SLEEP); - pte = hat_mempte_setup(addr); + pte_pa = hat_mempte_setup(addr); cpup->cpu_caddr2 = addr; - cpup->cpu_caddr2pte = (pteptr_t)pte; + cpup->cpu_caddr2pte = pte_pa; mutex_init(&cpup->cpu_ppaddr_mutex, NULL, MUTEX_DEFAULT, NULL); } +/* + * Undo setup_vaddr_for_ppcopy + */ +void +teardown_vaddr_for_ppcopy(struct cpu *cpup) +{ + mutex_destroy(&cpup->cpu_ppaddr_mutex); + + hat_mempte_release(cpup->cpu_caddr2, cpup->cpu_caddr2pte); + cpup->cpu_caddr2pte = 0; + vmem_free(heap_arena, cpup->cpu_caddr2, mmu_ptob(1)); + cpup->cpu_caddr2 = 0; + + hat_mempte_release(cpup->cpu_caddr1, cpup->cpu_caddr1pte); + cpup->cpu_caddr1pte = 0; + vmem_free(heap_arena, cpup->cpu_caddr1, mmu_ptob(1)); + cpup->cpu_caddr1 = 0; +} /* * Create the pageout scanner thread. The thread has to @@ -2155,3 +2176,58 @@ exec_get_spslew(void) { return (0); } + +/* + * Allocate a memory page. The argument 'seed' can be any pseudo-random + * number to vary where the pages come from. This is quite a hacked up + * method -- it works for now, but really needs to be fixed up a bit. + * + * We currently use page_create_va() on the kvp with fake offsets, + * segments and virt address. This is pretty bogus, but was copied from the + * old hat_i86.c code. A better approach would be to specify either mnode + * random or mnode local and takes a page from whatever color has the MOST + * available - this would have a minimal impact on page coloring. + */ +page_t * +page_get_physical(uintptr_t seed) +{ + page_t *pp; + u_offset_t offset; + static struct seg tmpseg; + static uintptr_t ctr = 0; + + /* + * This code is gross, we really need a simpler page allocator. + * + * We need assign an offset for the page to call page_create_va(). + * To avoid conflicts with other pages, we get creative with the offset. + * For 32 bits, we pick an offset > 4Gig + * For 64 bits, pick an offset somewhere in the VA hole. + */ + offset = seed; + if (offset > kernelbase) + offset -= kernelbase; + offset <<= MMU_PAGESHIFT; +#if defined(__amd64) + offset += mmu.hole_start; /* something in VA hole */ +#else + offset += 1ULL << 40; /* something > 4 Gig */ +#endif + + if (page_resv(1, KM_NOSLEEP) == 0) + return (NULL); + +#ifdef DEBUG + pp = page_exists(&kvp, offset); + if (pp != NULL) + panic("page already exists %p", pp); +#endif + + pp = page_create_va(&kvp, offset, MMU_PAGESIZE, PG_EXCL | PG_NORELOC, + &tmpseg, (caddr_t)(ctr += MMU_PAGESIZE)); /* changing VA usage */ + if (pp == NULL) + return (NULL); + page_io_unlock(pp); + page_hashout(pp, NULL); + return (pp); +} diff --git a/usr/src/uts/i86pc/xsvc/Makefile b/usr/src/uts/i86pc/xsvc/Makefile new file mode 100644 index 0000000000..6dd8477ad5 --- /dev/null +++ b/usr/src/uts/i86pc/xsvc/Makefile @@ -0,0 +1,95 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# uts/i86pc/xsvc/Makefile +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# This makefile drives the production of the xsvc driver kernel +# module. +# + +# +# Path to the base of the uts directory tree (usually /usr/src/uts). +# +UTSBASE = ../.. + +# +# Define the module and object file sets. +# +MODULE = xsvc +OBJECTS = $(XSVC_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(XSVC_OBJS:%.o=$(LINTS_DIR)/%.ln) +ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) +CONF_SRCDIR = $(UTSBASE)/i86pc/io/xsvc + +# +# Include common rules. +# +include $(UTSBASE)/i86pc/Makefile.i86pc + +# +# Define targets +# +ALL_TARGET = $(BINARY) $(SRC_CONFILE) +LINT_TARGET = $(MODULE).lint +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) + +# +# Dependency +# +LDFLAGS += -dy + +# +# Override defaults to build a unique, local modstubs.o. +# +MODSTUBS_DIR = $(OBJS_DIR) +CLEANFILES += $(MODSTUBS_O) + +# +# Default build targets. +# +.KEEP_STATE: + +def: $(DEF_DEPS) + +all: $(ALL_DEPS) + +clean: $(CLEAN_DEPS) + +clobber: $(CLOBBER_DEPS) + +lint: $(LINT_DEPS) + +modlintlib: $(MODLINTLIB_DEPS) + +clean.lint: $(CLEAN_LINT_DEPS) + +install: $(INSTALL_DEPS) + +# +# Include common targets. +# +include $(UTSBASE)/i86pc/Makefile.targ + diff --git a/usr/src/uts/intel/Makefile b/usr/src/uts/intel/Makefile index adaa4d6158..578916b474 100644 --- a/usr/src/uts/intel/Makefile +++ b/usr/src/uts/intel/Makefile @@ -20,7 +20,7 @@ # # uts/intel/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -39,9 +39,10 @@ LINT_LIBS = $(LINT_LIB) $(GEN_LINT_LIB) \ # EXPORT DELETE START $(CLOSED_BUILD)LINT_LIBS += $(SVVS_KMODS:%=$(LINT_LIB_DIR)/llib-l%.ln) -$(CLOSED_BUILD)LINT_CLOSED_XMOD3 = $(CLOSED_XMODS:lsimega=) -$(CLOSED_BUILD)LINT_CLOSED_XMOD2 = $(LINT_CLOSED_XMOD3:adpu320=) -$(CLOSED_BUILD)LINT_CLOSED_XMOD1 = $(LINT_CLOSED_XMOD2:e1000g=) +$(CLOSED_BUILD)LINT_CLOSED_XMOD4 = $(CLOSED_XMODS:lsimega=) +$(CLOSED_BUILD)LINT_CLOSED_XMOD3 = $(LINT_CLOSED_XMOD4:spwr=) +$(CLOSED_BUILD)LINT_CLOSED_XMOD2 = $(LINT_CLOSED_XMOD3:adpu320=) +$(CLOSED_BUILD)LINT_CLOSED_XMOD1 = $(LINT_CLOSED_XMOD2:e1000g=) $(CLOSED_BUILD)LINT_XMODLIBS = $(LINT_CLOSED_XMOD1:nge=) $(CLOSED_BUILD)LINT_LIBS += $(LINT_XMODLIBS:%=$(LINT_LIB_DIR)/llib-l%.ln) @@ -82,8 +83,8 @@ install_h := TARGET= install_h .KEEP_STATE: -.PARALLEL: $(KMODS) $(CLOSED_KMODS) $(SVVS) $(XMODS) $(CLOSED_XMODS) \ - config $(LINT_DEPS) +.PARALLEL: $(PARALLEL_KMODS) $(CLOSED_KMODS) $(SVVS) $(XMODS) \ + $(CLOSED_XMODS) config $(LINT_DEPS) def all install clean clobber modlist: genassym $(KMODS) $(CLOSED_KMODS) \ $(SVVS) $(XMODS) $(CLOSED_XMODS) config @@ -119,13 +120,21 @@ install_h check: FRC @cd amd64/sys; pwd; $(MAKE) $(TARGET) # +# Work-around to disable acpica global crosscheck lint warnings +# +LGREP.intel = grep -v 'intel/io/acpica' + +# # Full kernel lint target. # LINT_TARGET = globallint +# workaround for multiply defined errors +globallint := LINTFLAGS += -erroff=E_NAME_MULTIPLY_DEF2 + globallint: @-$(ECHO) "\nFULL KERNEL: global crosschecks:" - @-$(LINT) $(LINTFLAGS) $(LINT_LIBS) 2>&1 | $(LGREP.2) + @-$(LINT) $(LINTFLAGS) $(LINT_LIBS) 2>&1 | $(LGREP.2) | $(LGREP.intel) lint: modlintlib .WAIT $(LINT_DEPS) diff --git a/usr/src/uts/intel/Makefile.files b/usr/src/uts/intel/Makefile.files index 2cdbe02a14..f401fc5507 100644 --- a/usr/src/uts/intel/Makefile.files +++ b/usr/src/uts/intel/Makefile.files @@ -36,6 +36,7 @@ # Core (unix) objects # CORE_OBJS += \ + arch_kdi.o \ copy.o \ copy_subr.o \ cpc_subr.o \ @@ -70,7 +71,6 @@ SPECIAL_OBJS_32 += \ # GENUNIX_OBJS += \ archdep.o \ - arch_kdi.o \ getcontext.o \ install_utrap.o \ prom_enter.o \ @@ -110,33 +110,52 @@ LX_AUTOFS_OBJS += \ lx_autofs.o # -# Driver modules +# Decompression code # -CMDK_OBJS += cmdk.o +CORE_OBJS += decompress.o adler32.o infblock.o infcodes.o inffast.o \ + inflate.o inftrees.o infutil.o zutil.o zmod.o +# +# Driver modules +# +AGPGART_OBJS += agpgart.o agp_kstat.o +AGPTARGET_OBJS += agptarget.o +AMD64GART_OBJS += amd64_gart.o +ATA_OBJS += $(GHD_OBJS) ata_blacklist.o ata_common.o ata_disk.o \ + ata_dma.o atapi.o atapi_fsm.o ata_debug.o \ + sil3xxx.o +CMDK_OBJS += cmdk.o CMLB_OBJS += cmlb.o - -DADK_OBJS += dadk.o - -GDA_OBJS += gda.o - +DADK_OBJS += dadk.o +DNET_OBJS += dnet.o mii.o +FD_OBJS += fd.o +GDA_OBJS += gda.o +GHD_OBJS += ghd.o ghd_debug.o ghd_dma.o ghd_queue.o ghd_scsa.o \ + ghd_scsi.o ghd_timer.o ghd_waitq.o ghd_gcmd.o +I915_OBJS += i915_sundrv.o i915_dma.o i915_drv.o i915_irq.o i915_mem.o +LOGI_OBJS += logi.o +MSMOUSE_OBJS += msm.o +MSCSI_OBJS += mscsi.o +PCI_E_PCINEXUS_OBJS += pcie_pci.o +PCI_PCINEXUS_OBJS += pci_pci.o +PCIEHPCNEXUS_OBJS += pciehpc_x86.o pciehpc_acpi.o pciehpc_nvidia.o +PCN_OBJS += mii.o +POWER_OBJS += power.o +PCI_AUTOCONFIG_OBJS += pci_autoconfig.o pci_boot.o pcie_nvidia.o \ + pci_memlist.o pci_resource.o SD_OBJS += sd.o sd_xbuf.o - STRATEGY_OBJS += strategy.o - VGATEXT_OBJS += vgatext.o vgasubr.o # -# misc. modules +# Kernel linker # -KRTLD_BOOT_OBJS += \ - kobj_boot.o - KRTLD_OBJS += \ bootrd.o \ ufsops.o \ hsfs.o \ doreloc.o \ + kobj_boot.o \ kobj_convrelstr.o \ kobj_crt.o \ kobj_isa.o \ @@ -145,12 +164,42 @@ KRTLD_OBJS += \ # # misc. modules # +ACPICA_OBJS += dbcmds.o dbdisply.o \ + dbexec.o dbfileio.o dbhistry.o dbinput.o dbstats.o \ + dbutils.o dbxface.o evevent.o evgpe.o evgpeblk.o \ + evmisc.o evregion.o evrgnini.o evsci.o evxface.o \ + evxfevnt.o evxfregn.o hwacpi.o hwgpe.o hwregs.o \ + hwsleep.o hwtimer.o dsfield.o dsinit.o dsmethod.o \ + dsmthdat.o dsobject.o dsopcode.o dsutils.o dswexec.o \ + dswload.o dswscope.o dswstate.o exconfig.o exconvrt.o \ + excreate.o exdump.o exfield.o exfldio.o exmisc.o \ + exmutex.o exnames.o exoparg1.o exoparg2.o exoparg3.o \ + exoparg6.o exprep.o exregion.o exresnte.o exresolv.o \ + exresop.o exstore.o exstoren.o exstorob.o exsystem.o \ + exutils.o psargs.o psopcode.o psparse.o psscope.o \ + pstree.o psutils.o pswalk.o psxface.o nsaccess.o \ + nsalloc.o nsdump.o nsdumpdv.o nseval.o nsinit.o \ + nsload.o nsnames.o nsobject.o nsparse.o nssearch.o \ + nsutils.o nswalk.o nsxfeval.o nsxfname.o nsxfobj.o \ + rsaddr.o rscalc.o rscreate.o rsdump.o \ + rsinfo.o rsio.o rsirq.o rslist.o rsmemory.o rsmisc.o \ + rsutils.o rsxface.o tbconvrt.o tbget.o tbgetall.o \ + tbinstal.o tbrsdt.o tbutils.o tbxface.o tbxfroot.o \ + utalloc.o utclib.o utcopy.o utdebug.o utdelete.o \ + uteval.o utglobal.o utinit.o utmath.o utmisc.o \ + utobject.o utresrc.o utxface.o acpica.o acpi_enum.o \ + master_ops.o osl.o osl_ml.o acpica_ec.o utcache.o \ + utmutex.o utstate.o dmbuffer.o dmnames.o dmobject.o \ + dmopcode.o dmresrc.o dmresrcl.o dmresrcs.o dmutils.o \ + dmwalk.o psloop.o uttrack.o + ACPI_INTP_OBJS += acpi_inf.o acpi_mod.o acpi_ml.o \ acpi_decl.o acpi_exe.o acpi_gram.o acpi_io.o acpi_lex.o \ acpi_name.o acpi_ns.o acpi_op1.o acpi_op2.o acpi_rule.o \ acpi_tab.o acpi_thr.o acpi_val.o \ acpi_exc.o acpi_bst.o acpi_node.o acpi_stk.o acpi_par.o +AGP_OBJS += agpmaster.o FBT_OBJS += fbt.o SDT_OBJS += sdt.o diff --git a/usr/src/uts/intel/Makefile.intel.shared b/usr/src/uts/intel/Makefile.intel.shared index 22f043eaeb..8a923fd369 100644 --- a/usr/src/uts/intel/Makefile.intel.shared +++ b/usr/src/uts/intel/Makefile.intel.shared @@ -146,16 +146,6 @@ AS_INC_PATH += -I$(GENASSYM_DIR)/$(OBJS_DIR) BASE_INS_DIR = $(ROOT) # -# -# Simulator flag -# -i386_SIMULATOR = -D_SIMULATOR_SUPPORT -amd64_SIMULATOR = -D_SIMULATOR_SUPPORT - -SIMULATOR = $($(MACH)_SIMULATOR) - - -# # Debugging level # # Special knowledge of which special debugging options affect which @@ -163,10 +153,8 @@ SIMULATOR = $($(MACH)_SIMULATOR) # DEBUG_DEFS_OBJ32 = DEBUG_DEFS_DBG32 = -DDEBUG -DEBUG_DEFS_DBG32 += $(SIMULATOR) DEBUG_DEFS_OBJ64 = DEBUG_DEFS_DBG64 = -DDEBUG -DEBUG_DEFS_DBG64 += $(SIMULATOR) DEBUG_DEFS = $(DEBUG_DEFS_$(BUILD_TYPE)) DEBUG_COND_OBJ32 :sh = echo \\043 @@ -216,10 +204,17 @@ ALL_DEFS = $(DEBUG_DEFS) $(OPTION_DEFS) DRV_KMODS += aac DRV_KMODS += aggr DRV_KMODS += ahci +DRV_KMODS += amd64_gart DRV_KMODS += amr +DRV_KMODS += agpgart +DRV_KMODS += agptarget DRV_KMODS += arp DRV_KMODS += asy +DRV_KMODS += ata DRV_KMODS += ath +DRV_KMODS += audio810 +DRV_KMODS += audiohd +DRV_KMODS += audioixp DRV_KMODS += bl DRV_KMODS += bge DRV_KMODS += bofi @@ -233,10 +228,14 @@ DRV_KMODS += crypto DRV_KMODS += cryptoadm DRV_KMODS += devinfo DRV_KMODS += dld +DRV_KMODS_32 += dnet DRV_KMODS += dump DRV_KMODS += ecpp +DRV_KMODS += fd +DRV_KMODS += fdc DRV_KMODS += fssnap DRV_KMODS += i8042 +DRV_KMODS += i915 DRV_KMODS += icmp DRV_KMODS += icmp6 DRV_KMODS += ip @@ -246,6 +245,7 @@ DRV_KMODS += ippctl DRV_KMODS += ipsecah DRV_KMODS += ipsecesp DRV_KMODS += iwscn +DRV_KMODS += kb8042 DRV_KMODS += keysock DRV_KMODS += kssl DRV_KMODS += kstat @@ -254,15 +254,22 @@ DRV_KMODS += kmdb DRV_KMODS += llc1 DRV_KMODS += lofi DRV_KMODS += log +DRV_KMODS += logi DRV_KMODS += logindmux DRV_KMODS += mm DRV_KMODS += mouse8042 +DRV_KMODS_32 += mscsi +DRV_KMODS_32 += msm DRV_KMODS += nca DRV_KMODS += openeepr +DRV_KMODS += pci_pci +DRV_KMODS += pcic +DRV_KMODS += pcie_pci DRV_KMODS += physmem DRV_KMODS += pm DRV_KMODS += poll DRV_KMODS += pool +DRV_KMODS += power DRV_KMODS += pseudo DRV_KMODS += ptc DRV_KMODS += ptm @@ -280,8 +287,8 @@ DRV_KMODS += sctp6 DRV_KMODS += sd DRV_KMODS += sgen DRV_KMODS += si3124 -DRV_KMODS += spdsock DRV_KMODS += smbios +DRV_KMODS += spdsock DRV_KMODS += sppp DRV_KMODS += sppptun DRV_KMODS += st @@ -307,11 +314,22 @@ DRV_KMODS += zcons # $(CLOSED_BUILD)DRV_KMODS += dca -$(CLOSED_BUILD)CLOSED_DRV_KMODS += chxge -$(CLOSED_BUILD)CLOSED_DRV_KMODS += glm -$(CLOSED_BUILD)CLOSED_DRV_KMODS += llc2 -$(CLOSED_BUILD)CLOSED_DRV_KMODS += mpt -$(CLOSED_BUILD)CLOSED_DRV_KMODS += marvell88sx +$(CLOSED_BUILD)CLOSED_DRV_KMODS += audioens +$(CLOSED_BUILD)CLOSED_DRV_KMODS += audiovia823x +$(CLOSED_BUILD)CLOSED_DRV_KMODS += bmc +$(CLOSED_BUILD)CLOSED_DRV_KMODS += bscbus +$(CLOSED_BUILD)CLOSED_DRV_KMODS += bscv +$(CLOSED_BUILD)CLOSED_DRV_KMODS += chxge +$(CLOSED_BUILD)CLOSED_DRV_KMODS += elxl +$(CLOSED_BUILD)CLOSED_DRV_KMODS += glm +$(CLOSED_BUILD)CLOSED_DRV_KMODS += iprb +$(CLOSED_BUILD)CLOSED_DRV_KMODS += llc2 +$(CLOSED_BUILD)CLOSED_DRV_KMODS += marvell88sx +$(CLOSED_BUILD)CLOSED_DRV_KMODS += mpt +$(CLOSED_BUILD)CLOSED_DRV_KMODS_32 += ncrs +$(CLOSED_BUILD)CLOSED_DRV_KMODS += pcn +$(CLOSED_BUILD)CLOSED_DRV_KMODS += rtls +$(CLOSED_BUILD)CLOSED_DRV_KMODS_32 += sbpro # # Common code drivers @@ -446,6 +464,11 @@ STRMOD_KMODS += usb_ah STRMOD_KMODS += drcompat STRMOD_KMODS += nattymod STRMOD_KMODS += cryptmod +STRMOD_KMODS += vuid2ps2 +STRMOD_KMODS += vuid3ps2 +STRMOD_KMODS += vuidm3p +STRMOD_KMODS += vuidm4p +STRMOD_KMODS += vuidm5p # # 'System' Modules (/kernel/sys): @@ -470,8 +493,11 @@ SYS_KMODS += acctctl # MISC_KMODS_32 are built only 32-bit # MISC_KMODS_64 are built only 64-bit # +MISC_KMODS += acpica +MISC_KMODS += agpmaster MISC_KMODS += amsrc2 MISC_KMODS += audiosup +MISC_KMODS += bootdev MISC_KMODS += busra MISC_KMODS += cmlb MISC_KMODS += consconfig @@ -479,6 +505,7 @@ MISC_KMODS += ctf MISC_KMODS += dadk MISC_KMODS += diaudio MISC_KMODS += dls +MISC_KMODS += drm MISC_KMODS += fssnap_if MISC_KMODS += gda MISC_KMODS += gld @@ -496,14 +523,15 @@ MISC_KMODS += kcf MISC_KMODS += kgssapi MISC_KMODS += kmech_dummy MISC_KMODS += kmech_krb5 -MISC_KMODS += krtld MISC_KMODS += mac MISC_KMODS += mixer MISC_KMODS += net80211 MISC_KMODS += nfs_dlboot MISC_KMODS += nfssrv MISC_KMODS += neti +MISC_KMODS += pci_autoconfig MISC_KMODS += pcicfg +MISC_KMODS += pciehpc MISC_KMODS += pcihp MISC_KMODS += pcmcia MISC_KMODS += rpcsec @@ -517,7 +545,6 @@ MISC_KMODS += sysinit MISC_KMODS += tem MISC_KMODS += tlimod MISC_KMODS += usba usba10 usbs49_fw -MISC_KMODS += zmod $(CLOSED_BUILD)CLOSED_MISC_KMODS += amsrc1 $(CLOSED_BUILD)CLOSED_MISC_KMODS += klmmod klmops @@ -550,11 +577,6 @@ IPP_KMODS += tokenmt IPP_KMODS += tswtclmt # -# 'Dacf' modules (/kernel/dacf) -# -DACF_KMODS += consconfig_dacf - -# # generic-unix module (/kernel/genunix): # GENUNIX_KMODS += genunix @@ -580,6 +602,7 @@ $(CLOSED_BUILD)CLOSED_XMODS = \ lsimega \ nge \ sdpib \ + spwr \ tavor diff --git a/usr/src/uts/intel/Makefile.rules b/usr/src/uts/intel/Makefile.rules index 3770e4e9dd..0ea5247643 100644 --- a/usr/src/uts/intel/Makefile.rules +++ b/usr/src/uts/intel/Makefile.rules @@ -37,12 +37,23 @@ # alphabetically by the remaining components. # +# Need a way to distinguish between the ia32 and amd64 subdirs. +# +SUBARCH_DIR_32 = ia32 +SUBARCH_DIR_64 = amd64 +SUBARCH_DIR = $(SUBARCH_DIR_$(CLASS)) + +# # Section 1a: C object build rules # $(OBJS_DIR)/%.o: $(SRC)/common/fs/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) +$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/power/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + $(OBJS_DIR)/%.o: $(SRC)/common/util/i386/%.s $(COMPILE.s) -o $@ $< @@ -83,10 +94,88 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/aac/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/acpica/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/acpica/%.s + $(COMPILE.s) -o $@ $< + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/acpica/debugger/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/acpica/events/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/acpica/hardware/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/acpica/interpreter/dispatcher/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/acpica/interpreter/executer/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/acpica/interpreter/parser/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/acpica/namespace/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/acpica/resources/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/acpica/tables/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/acpica/utilities/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/acpica/disassembler/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/agpgart/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/agpmaster/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + $(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/amr/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/drm/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/drm/%.s + $(COMPILE.s) -o $@ $< + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/pci/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/pciex/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/pciex/hotplug/pciehpc/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + $(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/dktp/controller/ata/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) @@ -135,6 +224,44 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/common/os/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/kdi/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/kdi/%.s + $(COMPILE.s) -o $@ $< + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/kdi/$(SUBARCH_DIR)/%.s + $(COMPILE.s) -o $@ $< + +# +# krtld compiled into unix +# + +KRTLD_INC_PATH = -I$(UTSBASE)/common/krtld -I$(UTSBASE)/intel/sys +KRTLD_INC_PATH += -I$(UTSBASE)/intel/$(SUBARCH_DIR)/krtld + +KRTLD_CPPFLAGS_32 = -DELF_TARGET_386 +KRTLD_CPPFLAGS_64 = -DELF_TARGET_AMD64 -DMODDIR_SUFFIX=\"amd64\" +KRTLD_CPPFLAGS = $(KRTLD_CPPFLAGS_$(CLASS)) -D_KRTLD + +$(OBJS_DIR)/%.o: $(UTSBASE)/common/krtld/%.c + $(COMPILE.c) $(KRTLD_INC_PATH) $(KRTLD_CPPFLAGS) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/$(SUBARCH_DIR)/krtld/%.c + $(COMPILE.c) $(KRTLD_INC_PATH) $(KRTLD_CPPFLAGS) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/$(SUBARCH_DIR)/krtld/%.s + $(COMPILE.s) $(KRTLD_INC_PATH) $(KRTLD_CPPFLAGS) -o $@ $< + $(CTFCONVERT_O) + +$(OBJS_DIR)/%.o: $(SRC)/common/util/$(SUBARCH_DIR)/%.c + $(COMPILE.c) $(KRTLD_INC_PATH) $(KRTLD_CPPFLAGS) -o $@ $< + $(CTFCONVERT_O) + + # # Section 1b: Lint `object' build rules. # @@ -174,9 +301,69 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/%.c $(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/aac/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/acpica/%.s + @($(LHEAD) $(LINT.s) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/acpica/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/acpica/debugger/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/acpica/events/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/acpica/hardware/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/acpica/interpreter/dispatcher/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/acpica/interpreter/executer/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/acpica/interpreter/parser/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/acpica/namespace/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/acpica/resources/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/acpica/tables/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/acpica/utilities/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/acpica/disassembler/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/agpgart/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/agpmaster/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + $(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/amr/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/drm/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/drm/%.s + @($(LHEAD) $(LINT.s) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/pci/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/pciex/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/pciex/hotplug/pciehpc/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + $(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/dktp/controller/ata/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) @@ -212,3 +399,28 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/intel/syscall/%.c $(LINTS_DIR)/%.ln: $(UTSBASE)/common/os/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/kdi/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/kdi/%.s + @($(LHEAD) $(LINT.s) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/kdi/$(SUBARCH_DIR)/%.s + @($(LHEAD) $(LINT.s) $< $(LTAIL)) + +# +# krtld lints +# +$(LINTS_DIR)/%.ln: $(UTSBASE)/common/krtld/%.c + @($(LHEAD) $(LINT.c) $(KRTLD_INC_PATH) $(KRTLD_CPPFLAGS) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/$(SUBARCH_DIR)/krtld/%.c + @($(LHEAD) $(LINT.c) $(KRTLD_INC_PATH) $(KRTLD_CPPFLAGS) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/$(SUBARCH_DIR)/krtld/%.s + @($(LHEAD) $(LINT.s) $(KRTLD_INC_PATH) $(KRTLD_CPPFLAGS) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(SRC)/common/util/$(SUBARCH_DIR)/%.c + @($(LHEAD) $(LINT.c) $(KRTLD_INC_PATH) $(KRTLD_CPPFLAGS) $< $(LTAIL)) + diff --git a/usr/src/uts/i86pc/acpica/Makefile b/usr/src/uts/intel/acpica/Makefile index 2649bae96c..5cd44bec14 100644 --- a/usr/src/uts/i86pc/acpica/Makefile +++ b/usr/src/uts/intel/acpica/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -7,7 +7,7 @@ # This makefile drives the production of the ACPI CA services # kernel module. # -# i86pc implementation architecture dependent +# intel architecture dependent # # @@ -23,11 +23,12 @@ OBJECTS = $(ACPICA_OBJS:%=$(OBJS_DIR)/%) LINTS = $(ACPICA_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE) INC_PATH += -I$(UTSBASE)/intel/sys/acpi +INC_PATH += -I$(UTSBASE)/i86pc # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -80,4 +81,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/agpgart/Makefile b/usr/src/uts/intel/agpgart/Makefile index d50aed1e56..305f8888d7 100644 --- a/usr/src/uts/i86pc/agpgart/Makefile +++ b/usr/src/uts/intel/agpgart/Makefile @@ -1,8 +1,8 @@ # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# uts/i86pc/agpgart/Makefile +# uts/intel/agpgart/Makefile # # #ident "%Z%%M% %I% %E% SMI" @@ -21,13 +21,13 @@ UTSBASE = ../.. MODULE = agpgart OBJECTS = $(AGPGART_OBJS:%=$(OBJS_DIR)/%) LINTS = $(AGPGART_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/i86pc/io/agpgart +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) +CONF_SRCDIR = $(UTSBASE)/intel/io/agpgart # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -69,4 +69,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/agpmaster/Makefile b/usr/src/uts/intel/agpmaster/Makefile index 138a967e2d..c6a25d3f77 100644 --- a/usr/src/uts/i86pc/agpmaster/Makefile +++ b/usr/src/uts/intel/agpmaster/Makefile @@ -19,9 +19,9 @@ # CDDL HEADER END # -# uts/i86pc/agpmaster/Makefile +# uts/intel/agpmaster/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -29,7 +29,7 @@ # This makefile drives the production of the common graphics # interface kernel module. # -# i86pc platform dependent +# intel platform dependent # # @@ -43,8 +43,8 @@ UTSBASE = ../.. MODULE = agpmaster OBJECTS = $(AGP_OBJS:%=$(OBJS_DIR)/%) LINTS = $(AGP_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_MISC_DIR)/$(MODULE) -INC_PATH += -I$(UTSBASE)/i86pc/io/agpmaster +ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE) +INC_PATH += -I$(UTSBASE)/intel/io/agpmaster # # dependency @@ -54,7 +54,7 @@ LDFLAGS += -dy -Nmisc/pci_autoconfig # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -94,4 +94,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/agptarget/Makefile b/usr/src/uts/intel/agptarget/Makefile index 821f70c7ef..6d90d9f676 100644 --- a/usr/src/uts/i86pc/agptarget/Makefile +++ b/usr/src/uts/intel/agptarget/Makefile @@ -1,8 +1,8 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# uts/i86pc/agptarget/Makefile +# uts/intel/agptarget/Makefile # # #pragma ident "%Z%%M% %I% %E% SMI" @@ -21,12 +21,12 @@ UTSBASE = ../.. MODULE = agptarget OBJECTS = $(AGPTARGET_OBJS:%=$(OBJS_DIR)/%) LINTS = $(AGPTARGET_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -59,4 +59,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/intel/amd64/Makefile.rules b/usr/src/uts/intel/amd64/Makefile.rules deleted file mode 100644 index 83dfec5f2a..0000000000 --- a/usr/src/uts/intel/amd64/Makefile.rules +++ /dev/null @@ -1,66 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# uts/intel/amd64/Makefile.rules -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# This Makefile defines all file modules and build rules for the -# amd64-specific sources. These are the source files -# which are specific to the processors whose kernels use the amd64 ABI. -# -# The following two-level ordering must be maintained in this file. -# Lines are sorted first in order of decreasing specificity based on -# the first directory component. That is, sun4u rules come before -# sparc rules come before common rules. -# -# Lines whose initial directory components are equal are sorted -# alphabetically by the remaining components. - -# -# Section 1a: C object build rules -# -$(OBJS_DIR)/%.o: $(UTSBASE)/intel/amd64/krtld/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/intel/amd64/krtld/%.s - $(COMPILE.s) -o $@ $< - -$(OBJS_DIR)/%.o: $(SRC)/common/util/amd64/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -# -# Section 1b: Lint `object' build rules. -# -$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/amd64/krtld/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/amd64/krtld/%.s - @($(LHEAD) $(LINT.s) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(SRC)/common/util/amd64/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) diff --git a/usr/src/uts/intel/amd64/krtld/kobj_boot.c b/usr/src/uts/intel/amd64/krtld/kobj_boot.c index fb97b0b126..bdd6779d01 100644 --- a/usr/src/uts/intel/amd64/krtld/kobj_boot.c +++ b/usr/src/uts/intel/amd64/krtld/kobj_boot.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,48 +34,20 @@ #include <sys/link.h> #include <sys/auxv.h> #include <sys/kobj.h> -#include <sys/elf.h> #include <sys/bootsvcs.h> #include <sys/kobj_impl.h> - -#if !defined(__GNUC__) - -/* - * We don't use the global offset table, but - * ld may throw in an UNDEFINED reference in - * our symbol table. - */ -#if !defined(_KERNEL) -#pragma weak _GLOBAL_OFFSET_TABLE_ -#endif - -#else +#include <vm/kboot_mmu.h> /* - * We -do- use the global offset table, but only by - * accident -- when you tell gcc to emit PIC code, - * it -always- generates a reference to the GOT in - * a register, even if the compilation unit never - * uses it. - * - * Rumoured to be fixed in a later version of gcc.. + * the kernel's entry point (from locore.s) */ - -long _GLOBAL_OFFSET_TABLE_[1]; - -#endif - -#define roundup ALIGN - -#define MAXSECT 64 /* max # of sects. */ - -#define HIBITS 0xffffffff80000000 /* upper 32 bits */ +extern void _locore_start(); /* - * Boot transfers control here. At this point, - * we haven't relocated our own symbols, so the - * world (as we know it) is pretty small right now. + * fakebop and dboot don't create the boot auxillary vector information. + * Do that here before calling krtld initialization. */ +/*ARGSUSED3*/ void _kobj_boot( struct boot_syscalls *syscallp, @@ -83,337 +55,18 @@ _kobj_boot( struct bootops *bootops, Boot *ebp) { - Shdr *section[MAXSECT]; /* cache */ val_t bootaux[BA_NUM]; - struct bootops *bop; - Phdr *phdr; - auxv_t *auxv = NULL; - Shdr *sh; - Half sh_num; - ulong_t end, edata = 0; int i; - bop = (dvec) ? *(struct bootops **)bootops : bootops; - for (i = 0; i < BA_NUM; i++) bootaux[i].ba_val = NULL; - /* - * Check the bootstrap vector. - */ - for (; ebp->eb_tag != EB_NULL; ebp++) { - switch (ebp->eb_tag) { - case EB_AUXV: - auxv = (auxv_t *)ebp->eb_un.eb_ptr; - break; - case EB_DYNAMIC: - bootaux[BA_DYNAMIC].ba_ptr = (void *)ebp->eb_un.eb_ptr; - break; - default: - break; - } - } - - if (auxv == NULL) - return; - - /* - * Now the aux vector. - */ - for (; auxv->a_type != AT_NULL; auxv++) { - switch (auxv->a_type) { - case AT_PHDR: - bootaux[BA_PHDR].ba_ptr = auxv->a_un.a_ptr; - break; - case AT_PHENT: - bootaux[BA_PHENT].ba_val = auxv->a_un.a_val; - break; - case AT_PHNUM: - bootaux[BA_PHNUM].ba_val = auxv->a_un.a_val; - break; - case AT_PAGESZ: - bootaux[BA_PAGESZ].ba_val = auxv->a_un.a_val; - break; - case AT_SUN_LDELF: - bootaux[BA_LDELF].ba_ptr = auxv->a_un.a_ptr; - break; - case AT_SUN_LDSHDR: - bootaux[BA_LDSHDR].ba_ptr = auxv->a_un.a_ptr; - break; - case AT_SUN_LDNAME: - bootaux[BA_LDNAME].ba_ptr = auxv->a_un.a_ptr; - break; - case AT_SUN_LPAGESZ: - bootaux[BA_LPAGESZ].ba_val = auxv->a_un.a_val; - break; - case AT_SUN_CPU: - bootaux[BA_CPU].ba_ptr = auxv->a_un.a_ptr; - break; - case AT_SUN_MMU: - bootaux[BA_MMU].ba_ptr = auxv->a_un.a_ptr; - break; - case AT_ENTRY: - bootaux[BA_ENTRY].ba_ptr = auxv->a_un.a_ptr; - break; - default: - break; - } - } - - - sh = (Shdr *)bootaux[BA_LDSHDR].ba_ptr; - sh_num = ((Ehdr *)bootaux[BA_LDELF].ba_ptr)->e_shnum; - /* - * Make sure we won't overflow stack allocated cache - */ - if (sh_num >= MAXSECT) - return; - - /* - * Build cache table for section addresses. - */ - for (i = 0; i < sh_num; i++) { - section[i] = sh++; - } - - /* - * Find the end of data - * (to allocate bss) - */ - phdr = (Phdr *)bootaux[BA_PHDR].ba_ptr; - - for (i = 0; i < bootaux[BA_PHNUM].ba_val; i++) { - if (phdr->p_type == PT_LOAD && - (phdr->p_flags & PF_W) && (phdr->p_flags & PF_X)) { - edata = end = phdr->p_vaddr + phdr->p_memsz; - break; - } - phdr = (Phdr *)((ulong_t)phdr + bootaux[BA_PHENT].ba_val); - } - if (edata == NULL) - return; - - /* - * Find the symbol table, and then loop - * through the symbols adjusting their - * values to reflect where the sections - * were loaded. - */ - for (i = 1; i < sh_num; i++) { - Shdr *shp; - Sym *sp; - ulong_t off; - - shp = section[i]; - if (shp->sh_type != SHT_SYMTAB) - continue; - - for (off = 0; off < shp->sh_size; off += shp->sh_entsize) { - sp = (Sym *)(shp->sh_addr + off); - - if (sp->st_shndx == SHN_ABS || - sp->st_shndx == SHN_UNDEF) - continue; - - /* - * Assign the addresses for COMMON - * symbols even though we haven't - * actually allocated bss yet. - */ - if (sp->st_shndx == SHN_COMMON) { - end = ALIGN(end, sp->st_value); - sp->st_value = end; - /* - * Squirrel it away for later. - */ - if (bootaux[BA_BSS].ba_val == 0) - bootaux[BA_BSS].ba_val = end; - end += sp->st_size; - continue; - } else if (sp->st_shndx > (Half)sh_num) { - BSVC_PUTCHAR(syscallp, '>'); - return; - } - - /* - * Symbol's new address. - */ - sp->st_value += section[sp->st_shndx]->sh_addr; - } - } - - /* - * Allocate bss for COMMON, if any. - */ - if (end > edata) { - unsigned long va, bva; - unsigned long asize; - unsigned long align; - - if (bootaux[BA_LPAGESZ].ba_val) { - asize = bootaux[BA_LPAGESZ].ba_val; - align = bootaux[BA_LPAGESZ].ba_val; - } else { - asize = bootaux[BA_PAGESZ].ba_val; - align = BO_NO_ALIGN; - } - va = roundup(edata, asize); - bva = roundup(end, asize); - - if (bva > va) { - bva = (unsigned long)BOP_ALLOC(bop, (caddr_t)va, - bva - va, align); - if (bva == NULL) - return; - } - /* - * Zero it. - */ - for (va = edata; va < end; va++) - *(char *)va = 0; - /* - * Update the size of data. - */ - phdr->p_memsz += (end - edata); - } - - /* - * Relocate our own symbols. We'll handle the - * undefined symbols later. - */ - for (i = 1; i < sh_num; i++) { - Shdr *rshp, *shp, *ssp; - unsigned long baseaddr, reladdr, rend; - long relocsize; - - rshp = section[i]; - - if (rshp->sh_type != SHT_RELA) - continue; - /* - * Get the section being relocated - * and the symbol table. - */ - shp = section[rshp->sh_info]; - ssp = section[rshp->sh_link]; - - /* - * Only perform relocations against allocatable - * sections. - */ - if ((shp->sh_flags & SHF_ALLOC) == 0) - continue; - - reladdr = rshp->sh_addr; - baseaddr = shp->sh_addr; - rend = reladdr + rshp->sh_size; - relocsize = rshp->sh_entsize; - /* - * Loop through relocations. - */ - - while (reladdr < rend) { - Sym *symref; - Rela *reloc; - unsigned long stndx; - unsigned long off, *offptr; - long addend, value; - unsigned long symoff, symsize; - int rtype; - - reloc = (Rela *)reladdr; - off = reloc->r_offset; - addend = (long)reloc->r_addend; - rtype = ELF_R_TYPE(reloc->r_info); - stndx = ELF_R_SYM(reloc->r_info); - - reladdr += relocsize; - - if (rtype == R_AMD64_NONE) - continue; - - off += baseaddr; - - symsize = ssp->sh_entsize; - symoff = stndx * symsize; - - /* - * Check for bad symbol index. - */ - if (symoff > ssp->sh_size) - return; - - symref = (Sym *)(ssp->sh_addr + symoff); - - - /* - * Just bind our own symbols at this point. - */ - if (symref->st_shndx == SHN_UNDEF) - continue; - - value = symref->st_value; - - if ((rtype == R_AMD64_PC32) || - (rtype == R_AMD64_PLT32)) - /* - * If PC-relative, subtract ref addr. - */ - value -= off; - else if (rtype == R_AMD64_32) { - /* - * It's illegal to have any HIBITS - * set for R_AMD64_32 reloc. - */ - if (value & HIBITS) { - BSVC_PUTCHAR(syscallp, 'h'); - return; - } - } else if (rtype == R_AMD64_32S) { - /* - * All HIBITS for R_AMD64_32S - * *must* be set. - */ - if ((value & HIBITS) != HIBITS) { - BSVC_PUTCHAR(syscallp, 'H'); - return; - } - } - - offptr = (unsigned long *)off; - /* - * insert value calculated at reference point - * 2 cases - normal byte order aligned, normal byte - * order unaligned. - */ - switch (rtype) { - case R_AMD64_64: - *(unsigned long *)offptr = value + addend; - break; - case R_AMD64_PC32: - case R_AMD64_32S: - case R_AMD64_PLT32: - *(uint_t *)offptr = (uint_t)(value + addend); - break; - case R_AMD64_GOT32: - BSVC_PUTCHAR(syscallp, 'G'); - return; - case R_AMD64_32: - return; - default: - BSVC_PUTCHAR(syscallp, 'R'); - return; - } - /* - * We only need to do it once. - */ - reloc->r_info = ELF_R_INFO(stndx, R_AMD64_NONE); - } /* while */ - } + bootaux[BA_ENTRY].ba_ptr = (void *)_locore_start; + bootaux[BA_PAGESZ].ba_val = PAGESIZE; + bootaux[BA_LPAGESZ].ba_val = kbm_nucleus_size; /* - * Done relocating all of our *defined* - * symbols, so we hand off. + * Off to krtld initialization. */ kobj_init(syscallp, dvec, bootops, bootaux); } diff --git a/usr/src/uts/intel/amd64/krtld/kobj_crt.s b/usr/src/uts/intel/amd64/krtld/kobj_crt.s index 072a012c0c..16f90bd897 100644 --- a/usr/src/uts/intel/amd64/krtld/kobj_crt.s +++ b/usr/src/uts/intel/amd64/krtld/kobj_crt.s @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -64,14 +63,7 @@ exitto(caddr_t entrypoint) movq $ops, %rax movq (%rax), %rdx - movq boothowto, %rax - andq $RB_DEBUGENTER, %rax - jz 1f - - / Enter the debugger - int $T_DBGENTR - -1: / Call destination + / Call destination call *%r11 SET_SIZE(exitto) diff --git a/usr/src/uts/intel/amd64/ml/amd64.il b/usr/src/uts/intel/amd64/ml/amd64.il index 2648db8a13..e6b56fe7dd 100644 --- a/usr/src/uts/intel/amd64/ml/amd64.il +++ b/usr/src/uts/intel/amd64/ml/amd64.il @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -60,35 +59,6 @@ .end / -/ return value of cr3 register -/ - .inline getcr3,0 - movq %cr3, %rax - .end - -/ -/ reload cr3 register with its current value -/ - .inline reload_cr3,0 - movq %cr3, %rdi - movq %rdi, %cr3 - .end - -/ -/ return value of cr8 register -/ - .inline getcr8,0 - movq %cr8, %rax - .end - -/ -/ set cr8 register -/ - .inline setcr8,0 - movq %rdi, %cr8 - .end - -/ / convert ipl to spl. This is the identity function for i86 / .inline ipltospl,0 @@ -96,20 +66,6 @@ .end / -/ enable interrupts -/ - .inline sti,0 - sti - .end - -/ -/ disable interrupts -/ - .inline cli,0 - cli - .end - -/ / find the low order bit in a word / .inline lowbit,4 @@ -119,77 +75,6 @@ .end / -/ disable interrupts and return value describing if interrupts were enabled -/ - /* XX64 These don't work correctly with SOS9 build 13.0 yet - .inline clear_int_flag,0 - pushfq - cli - popq %rax - .end - - .inline intr_clear,0 - pushfq - cli - popq %rax - .end - */ - -/ -/ restore interrupt enable flag to value returned from 'clear_int_flag' above -/ - /* XX64 These don't work correctly with SOS9 build 13.0 yet - .inline restore_int_flag,4 - pushq %rdi - popfq - .end - - .inline intr_restore,4 - pushq %rdi - popfq - .end - */ - -/ -/ in and out -/ - .inline inb,4 - movq %rdi, %rdx - xorq %rax, %rax - inb (%dx) - .end - - .inline inw,4 - movq %rdi, %rdx - xorq %rax, %rax - inw (%dx) - .end - - .inline inl,4 - movq %rdi, %rdx - xorq %rax, %rax - inl (%dx) - .end - - .inline outb,8 - movq %rdi, %rdx - movq %rsi, %rax - outb (%dx) - .end - - .inline outw,8 - movq %rdi, %rdx - movq %rsi, %rax - outw (%dx) - .end - - .inline outl,8 - movq %rdi, %rdx - movq %rsi, %rax - outl (%dx) - .end - -/ / Networking byte order functions (too bad, Intel has the wrong byte order) / @@ -274,22 +159,6 @@ .end /* - * Read Time Stamp Counter - * uint64_t tsc_read(); - * - * usage: - * uint64_t cycles = tsc_read(); - * - * PPro & PII take no less than 34 cycles to execute rdtsc + stores. - * Pentium takes about 16 cycles. - */ - .inline tsc_read, 0 - rdtsc / %edx:%eax = RDTSC - shlq $32, %rdx - orq %rdx, %rax - .end - -/* * Call the pause instruction. To the Pentium 4 Xeon processor, it acts as * a hint that the code sequence is a busy spin-wait loop. Without a pause * instruction in these loops, the P4 Xeon processor may suffer a severe @@ -303,14 +172,28 @@ .end /* - * Call the halt instruction. This will put the CPU to sleep until - * it is again awoken via an interrupt. - * This function should be called with interrupts already disabled - * for the CPU. - * Note that "sti" will only enable interrupts at the end of the - * subsequent instruction...in this case: "hlt". + * inlines for update_sregs(). */ - .inline i86_halt,0 - sti - hlt + .inline __set_ds, 0 + movw %di, %ds + .end + + .inline __set_es, 0 + movw %di, %es + .end + + .inline __set_fs, 0 + movw %di, %fs + .end + + .inline __set_gs, 0 + movw %di, %gs + .end + + /* + * OPTERON_ERRATUM_88 requires mfence + */ + .inline __swapgs, 0 + mfence + swapgs .end diff --git a/usr/src/uts/intel/amd64/ml/mach_offsets.in b/usr/src/uts/intel/amd64/ml/mach_offsets.in index 2685e9ae1a..0e41e5c098 100644 --- a/usr/src/uts/intel/amd64/ml/mach_offsets.in +++ b/usr/src/uts/intel/amd64/ml/mach_offsets.in @@ -1,13 +1,12 @@ \ -\ Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. \ Use is subject to license terms. \ \ CDDL HEADER START \ \ The contents of this file are subject to the terms of the -\ Common Development and Distribution License, Version 1.0 only -\ (the "License"). You may not use this file except in compliance -\ with the License. +\ Common Development and Distribution License (the "License"). +\ You may not use this file except in compliance with the License. \ \ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE \ or http://www.opensolaris.org/os/licensing. @@ -78,8 +77,6 @@ regs REGSIZE r_r13 REGOFF_R13 r_r14 REGOFF_R14 r_r15 REGOFF_R15 - r_fsbase REGOFF_FSBASE - r_gsbase REGOFF_GSBASE r_ds REGOFF_DS r_es REGOFF_ES r_fs REGOFF_FS diff --git a/usr/src/uts/intel/amd64/sys/Makefile b/usr/src/uts/intel/amd64/sys/Makefile index 4856f12a86..6662f96476 100644 --- a/usr/src/uts/intel/amd64/sys/Makefile +++ b/usr/src/uts/intel/amd64/sys/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -31,6 +30,7 @@ include ../../../../Makefile.master HDRS= \ + kdi_regs.h \ privregs.h ROOTINCISA= $(ROOT)/usr/include/amd64 diff --git a/usr/src/uts/intel/amd64/sys/kdi_regs.h b/usr/src/uts/intel/amd64/sys/kdi_regs.h new file mode 100644 index 0000000000..d3dc3dced1 --- /dev/null +++ b/usr/src/uts/intel/amd64/sys/kdi_regs.h @@ -0,0 +1,97 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _AMD64_SYS_KDI_REGS_H +#define _AMD64_SYS_KDI_REGS_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define KDIREG_NGREG 31 + +/* + * A modified version of struct regs layout. + */ + +#define KDIREG_SAVFP 0 +#define KDIREG_SAVPC 1 +#define KDIREG_RDI 2 +#define KDIREG_RSI 3 +#define KDIREG_RDX 4 +#define KDIREG_RCX 5 +#define KDIREG_R8 6 +#define KDIREG_R9 7 +#define KDIREG_RAX 8 +#define KDIREG_RBX 9 +#define KDIREG_RBP 10 +#define KDIREG_R10 11 +#define KDIREG_R11 12 +#define KDIREG_R12 13 +#define KDIREG_R13 14 +#define KDIREG_R14 15 +#define KDIREG_R15 16 +#define KDIREG_FSBASE 17 +#define KDIREG_GSBASE 18 +#define KDIREG_KGSBASE 19 +#define KDIREG_DS 20 +#define KDIREG_ES 21 +#define KDIREG_FS 22 +#define KDIREG_GS 23 +#define KDIREG_TRAPNO 24 +#define KDIREG_ERR 25 +#define KDIREG_RIP 26 +#define KDIREG_CS 27 +#define KDIREG_RFLAGS 28 +#define KDIREG_RSP 29 +#define KDIREG_SS 30 + +#define KDIREG_PC KDIREG_RIP +#define KDIREG_SP KDIREG_RSP +#define KDIREG_FP KDIREG_RBP + +#ifdef _ASM + +/* Patch point for MSR clearing. */ +#define KDI_MSR_PATCH \ + nop; nop; nop; nop; \ + nop; nop; nop; nop; \ + nop; nop; nop; nop; \ + nop; nop; nop; nop; \ + nop + +#endif /* _ASM */ + +#define KDI_MSR_PATCHOFF 8 /* bytes of code before patch point */ +#define KDI_MSR_PATCHSZ 17 /* bytes in KDI_MSR_PATCH, above */ + +#ifdef __cplusplus +} +#endif + +#endif /* _AMD64_SYS_KDI_REGS_H */ diff --git a/usr/src/uts/intel/amd64/sys/privregs.h b/usr/src/uts/intel/amd64/sys/privregs.h index e10b471de4..38672670fe 100644 --- a/usr/src/uts/intel/amd64/sys/privregs.h +++ b/usr/src/uts/intel/amd64/sys/privregs.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,17 +18,18 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#ifndef _AMD64_SYS_PRIVREGS_H +#ifndef _AMD64_SYS_PRIVREGS_H #define _AMD64_SYS_PRIVREGS_H #pragma ident "%Z%%M% %I% %E% SMI" -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif @@ -42,7 +42,7 @@ extern "C" { #error "non-amd64 code depends on amd64 privileged header!" #endif -#ifndef _ASM +#ifndef _ASM /* * This is NOT the structure to use for general purpose debugging; @@ -77,8 +77,16 @@ struct regs { greg_t r_r14; /* callee-saved */ greg_t r_r15; /* callee-saved */ - greg_t r_fsbase; - greg_t r_gsbase; + /* + * XX64 + * We used to sample fsbase and gsbase on every exception + * with expensive rdmsr's. Yet this was only useful at + * best for debugging during amd64 bringup. We should take + * these away but for now simply rename them to avoid any + * flag days. + */ + greg_t __r_fsbase; /* XX64 no longer used by the kernel */ + greg_t __r_gsbase; /* XX64 no longer used by the kernel */ greg_t r_ds; greg_t r_es; greg_t r_fs; /* %fs is *never* used by the kernel */ @@ -106,22 +114,19 @@ struct regs { #ifdef _KERNEL #define lwptoregs(lwp) ((struct regs *)((lwp)->lwp_regs)) -#endif /* _KERNEL */ +#endif /* _KERNEL */ #else /* !_ASM */ -#define TRAPERR_PUSH(err, trapno) \ - pushq $err; \ - pushq $trapno +#if defined(_MACHDEP) + +#include <sys/machprivregs.h> +#include <sys/pcb.h> /* * Create a struct regs on the stack suitable for an * interrupt trap. * - * The swapgs instruction is conditionalized to make sure that - * interrupts in kernel mode don't cause us to switch back to - * the user's gsbase! - * * Assumes that the trap handler has already pushed an * appropriate r_err and r_trapno */ @@ -152,44 +157,9 @@ struct regs { movw %es, %cx; \ movq %rcx, REGOFF_ES(%rsp); \ movw %ds, %cx; \ - movq %rcx, REGOFF_DS(%rsp); \ - movl $MSR_AMD_FSBASE, %ecx; \ - rdmsr; \ - movl %eax, REGOFF_FSBASE(%rsp); \ - movl %edx, REGOFF_FSBASE+4(%rsp); \ - movl $MSR_AMD_GSBASE, %ecx; \ - rdmsr; \ - movl %eax, REGOFF_GSBASE(%rsp); \ - movl %edx, REGOFF_GSBASE+4(%rsp) - -/* - * Push register state onto the stack. If we've - * interrupted userland, do a swapgs as well. - */ - -#define INTR_PUSH \ - subq $REGOFF_TRAPNO, %rsp; \ - __SAVE_REGS; \ - cmpw $KCS_SEL, REGOFF_CS(%rsp); \ - je 6f; \ - movq $0, REGOFF_SAVFP(%rsp); \ - swapgs; \ -6: - -#define TRAP_PUSH \ - subq $REGOFF_TRAPNO, %rsp; \ - __SAVE_REGS; \ - cmpw $KCS_SEL, REGOFF_CS(%rsp); \ - je 6f; \ - movq $0, REGOFF_SAVFP(%rsp); \ - swapgs; \ -6: + movq %rcx, REGOFF_DS(%rsp) -#define DFTRAP_PUSH \ - subq $REGOFF_TRAPNO, %rsp; \ - __SAVE_REGS - -#define __RESTORE_REGS \ +#define __RESTORE_REGS \ movq REGOFF_RDI(%rsp), %rdi; \ movq REGOFF_RSI(%rsp), %rsi; \ movq REGOFF_RDX(%rsp), %rdx; \ @@ -206,6 +176,19 @@ struct regs { movq REGOFF_R14(%rsp), %r14; \ movq REGOFF_R15(%rsp), %r15 +/* + * Push register state onto the stack. If we've + * interrupted userland, do a swapgs as well. + */ +#define INTR_PUSH \ + subq $REGOFF_TRAPNO, %rsp; \ + __SAVE_REGS; \ + cmpw $KCS_SEL, REGOFF_CS(%rsp); \ + je 6f; \ + movq $0, REGOFF_SAVFP(%rsp); \ + SWAPGS; \ +6: CLEAN_CS + #define INTR_POP \ leaq sys_lcall32(%rip), %r11;\ cmpq %r11, REGOFF_RIP(%rsp); \ @@ -213,12 +196,12 @@ struct regs { je 5f; \ cmpw $KCS_SEL, REGOFF_CS(%rsp);\ je 8f; \ -5: swapgs; \ +5: SWAPGS; \ 8: addq $REGOFF_RIP, %rsp #define USER_POP \ __RESTORE_REGS; \ - swapgs; \ + SWAPGS; \ addq $REGOFF_RIP, %rsp /* Adjust %rsp to prepare for iretq */ #define USER32_POP \ @@ -229,51 +212,23 @@ struct regs { movl REGOFF_RAX(%rsp), %eax; \ movl REGOFF_RBX(%rsp), %ebx; \ movl REGOFF_RBP(%rsp), %ebp; \ - swapgs; \ + SWAPGS; \ addq $REGOFF_RIP, %rsp /* Adjust %rsp to prepare for iretq */ +#define DFTRAP_PUSH \ + subq $REGOFF_TRAPNO, %rsp; \ + __SAVE_REGS + +#endif /* _MACHDEP */ /* - * Smaller versions of INTR_PUSH and INTR_POP for fast traps. - * The following registers have been pushed onto the stack by - * hardware at this point: - * - * greg_t r_rip; - * greg_t r_cs; - * greg_t r_rfl; - * greg_t r_rsp; - * greg_t r_ss; - * - * This handler is executed both by 32-bit and 64-bit applications. - * 64-bit applications allow us to treat the set (%rdi, %rsi, %rdx, - * %rcx, %r8, %r9, %r10, %r11, %rax) as volatile across function calls. - * However, 32-bit applications only expect (%eax, %edx, %ecx) to be volatile - * across a function call -- in particular, %esi and %edi MUST be saved! - * - * We could do this differently by making a FAST_INTR_PUSH32 for 32-bit - * programs, and FAST_INTR_PUSH for 64-bit programs, but it doesn't seem - * particularly worth it. + * Used to set rflags to known values at the head of an + * interrupt gate handler, i.e. interrupts are -already- disabled. */ -#define FAST_INTR_PUSH \ - subq $REGOFF_RIP, %rsp; \ - movq %rsi, REGOFF_RSI(%rsp); \ - movq %rdi, REGOFF_RDI(%rsp); \ - swapgs - -#define FAST_INTR_POP \ - swapgs; \ - movq REGOFF_RSI(%rsp), %rsi; \ - movq REGOFF_RDI(%rsp), %rdi; \ - addq $REGOFF_RIP, %rsp - -#define DISABLE_INTR_FLAGS \ +#define INTGATE_INIT_KERNEL_FLAGS \ pushq $F_OFF; \ popfq -#define ENABLE_INTR_FLAGS \ - pushq $F_ON; \ - popfq - #endif /* !_ASM */ #include <sys/controlregs.h> @@ -322,7 +277,7 @@ extern void setcr8(ulong_t); #define CREG_KGSBASE 0x58 #define CREG_EFER 0x60 -#if !defined(_ASM) +#if !defined(_ASM) && defined(_INT64_TYPE) typedef uint64_t creg64_t; typedef upad128_t creg128_t; @@ -345,10 +300,10 @@ struct cregs { extern void getcregs(struct cregs *); #endif /* _KERNEL */ -#endif /* _ASM */ +#endif /* !_ASM && _INT64_TYPE */ -#ifdef __cplusplus +#ifdef __cplusplus } #endif -#endif /* _AMD64_SYS_PRIVREGS_H */ +#endif /* !_AMD64_SYS_PRIVREGS_H */ diff --git a/usr/src/uts/i86pc/amd64_gart/Makefile b/usr/src/uts/intel/amd64_gart/Makefile index 6fd4b8253c..f2a2200b0e 100644 --- a/usr/src/uts/i86pc/amd64_gart/Makefile +++ b/usr/src/uts/intel/amd64_gart/Makefile @@ -1,8 +1,8 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# uts/i86pc/amd64_gart/Makefile +# uts/intel/amd64_gart/Makefile # # #ident "%Z%%M% %I% %E% SMI" @@ -21,12 +21,12 @@ UTSBASE = ../.. MODULE = amd64_gart OBJECTS = $(AMD64GART_OBJS:%=$(OBJS_DIR)/%) LINTS = $(AMD64GART_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -59,4 +59,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/ata/Makefile b/usr/src/uts/intel/ata/Makefile index d84a07337b..bbeff258b6 100644 --- a/usr/src/uts/i86pc/ata/Makefile +++ b/usr/src/uts/intel/ata/Makefile @@ -18,9 +18,9 @@ # # CDDL HEADER END # -# uts/i86pc/ata/Makefile +# uts/intel/ata/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -28,7 +28,7 @@ # This makefile drives the production of the ata "drv" # kernel module. # -# i86pc implementation architecture dependent +# intel architecture dependent # # @@ -42,13 +42,13 @@ UTSBASE = ../.. MODULE = ata OBJECTS = $(ATA_OBJS:%=$(OBJS_DIR)/%) LINTS = $(ATA_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) CONF_SRCDIR = $(UTSBASE)/intel/io/dktp/controller/ata # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -98,4 +98,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/audio810/Makefile b/usr/src/uts/intel/audio810/Makefile index 13bb6fdaa6..f358574423 100644 --- a/usr/src/uts/i86pc/audio810/Makefile +++ b/usr/src/uts/intel/audio810/Makefile @@ -19,10 +19,10 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# uts/i86pc/audio810/Makefile +# uts/intel/audio810/Makefile # # # ident "%Z%%M% %I% %E% SMI" @@ -50,7 +50,7 @@ WLCMD_DIR = $(UTSBASE)/common/io/warlock # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Overrides, lint pass one enforcement @@ -104,7 +104,7 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ # # Defines for local commands. diff --git a/usr/src/uts/i86pc/audiohd/Makefile b/usr/src/uts/intel/audiohd/Makefile index 303f226006..902427571d 100644 --- a/usr/src/uts/i86pc/audiohd/Makefile +++ b/usr/src/uts/intel/audiohd/Makefile @@ -19,10 +19,10 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# uts/i86pc/audiohd/Makefile +# uts/intel/audiohd/Makefile # # # ident "%Z%%M% %I% %E% SMI" @@ -50,7 +50,7 @@ WLCMD_DIR = $(UTSBASE)/common/io/warlock # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Overrides, lint pass one enforcement @@ -105,7 +105,7 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ # # Defines for local commands. diff --git a/usr/src/uts/i86pc/audioixp/Makefile b/usr/src/uts/intel/audioixp/Makefile index e9ebba4c81..1f52255abb 100644 --- a/usr/src/uts/i86pc/audioixp/Makefile +++ b/usr/src/uts/intel/audioixp/Makefile @@ -19,10 +19,10 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# uts/i86pc/audioixp/Makefile +# uts/intel/audioixp/Makefile # # #ident "%Z%%M% %I% %E% SMI" @@ -50,7 +50,7 @@ WLCMD_DIR = $(UTSBASE)/common/io/warlock # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Overrides, lint pass one enforcement @@ -104,7 +104,7 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ # # Defines for local commands. diff --git a/usr/src/uts/i86pc/bootdev/Makefile b/usr/src/uts/intel/bootdev/Makefile index 62989fce66..18705fe8f1 100644 --- a/usr/src/uts/i86pc/bootdev/Makefile +++ b/usr/src/uts/intel/bootdev/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,8 +19,8 @@ # CDDL HEADER END # # -# uts/i86pc/bootdev/Makefile -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# uts/intel/bootdev/Makefile +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -29,7 +28,7 @@ # This makefile drives the production of the bootdev driver # kernel module. # -# i86pc architecture dependent +# intel architecture dependent # # @@ -43,12 +42,12 @@ UTSBASE = ../.. MODULE = bootdev OBJECTS = $(BOOTDEV_OBJS:%=$(OBJS_DIR)/%) LINTS = $(BOOTDEV_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_MISC_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE) # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -81,4 +80,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/intel/ctf/Makefile b/usr/src/uts/intel/ctf/Makefile index 57a944ef02..ecd389f7a6 100644 --- a/usr/src/uts/intel/ctf/Makefile +++ b/usr/src/uts/intel/ctf/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -38,7 +38,7 @@ LINT_TARGET = $(MODULE).lint INSTALL_TARGET = $(BINARY) $(ROOTMODULE) CPPFLAGS += -I$(SRC)/common/ctf -DCTF_OLD_VERSIONS -LDFLAGS += -Breduce -M$(UTSBASE)/common/ctf/mapfile -dy -Nmisc/zmod +LDFLAGS += -Breduce -M$(UTSBASE)/common/ctf/mapfile -dy # # For now, disable these lint checks; maintainers should endeavor diff --git a/usr/src/uts/i86pc/dnet/Makefile b/usr/src/uts/intel/dnet/Makefile index 55ad49a0e9..14e60e5c40 100644 --- a/usr/src/uts/i86pc/dnet/Makefile +++ b/usr/src/uts/intel/dnet/Makefile @@ -19,9 +19,9 @@ # CDDL HEADER END # # -# uts/i86pc/dnet/Makefile +# uts/intel/dnet/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -29,7 +29,7 @@ # This makefile drives the production of the dnet # network driver kernel module. # -# i86pc architecture dependent +# intel architecture dependent # # @@ -44,12 +44,12 @@ MODULE = dnet OBJECTS = $(DNET_OBJS:%=$(OBJS_DIR)/%) LINTS = $(DNET_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/i86pc/io +CONF_SRCDIR = $(UTSBASE)/intel/io # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -102,4 +102,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/drm/Makefile b/usr/src/uts/intel/drm/Makefile index 34f70fe829..0af49425f9 100644 --- a/usr/src/uts/i86pc/drm/Makefile +++ b/usr/src/uts/intel/drm/Makefile @@ -18,9 +18,9 @@ # # CDDL HEADER END # -# uts/i86pc/drm/Makefile +# uts/intel/drm/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -38,7 +38,7 @@ UTSBASE = ../.. MODULE = drm OBJECTS = $(DRM_OBJS:%=$(OBJS_DIR)/%) LINTS = $(DRM_OBJS:%.o=$(LINTS_DIR)/%.ln) -DRM_SRC = $(UTSBASE)/i86pc/io/drm +DRM_SRC = $(UTSBASE)/intel/io/drm ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE) INC_PATH += -I$(DRM_SRC) CMN_DRM_SRC = $(UTSBASE)/common/io/drm @@ -47,7 +47,7 @@ CONF_SRCDIR = $(UTSBASE)/common/io/drm # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -88,4 +88,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/intel/dtrace/dtrace_isa.c b/usr/src/uts/intel/dtrace/dtrace_isa.c index 3d7144350e..2b40fd40cb 100644 --- a/usr/src/uts/intel/dtrace/dtrace_isa.c +++ b/usr/src/uts/intel/dtrace/dtrace_isa.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,17 +33,6 @@ #include <sys/privregs.h> #include <sys/sysmacros.h> -/* - * This is gross knowledge to have to encode here... - */ -extern void _interrupt(); -extern void _cmntrap(); -extern void _allsyscalls(); - -extern size_t _interrupt_size; -extern size_t _cmntrap_size; -extern size_t _allsyscalls_size; - extern uintptr_t kernelbase; void diff --git a/usr/src/uts/intel/dtrace/fasttrap_isa.c b/usr/src/uts/intel/dtrace/fasttrap_isa.c index c8f222e429..99301192e7 100644 --- a/usr/src/uts/intel/dtrace/fasttrap_isa.c +++ b/usr/src/uts/intel/dtrace/fasttrap_isa.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +34,7 @@ #include <sys/regset.h> #include <sys/privregs.h> #include <sys/segments.h> +#include <sys/x86_archext.h> #include <sys/sysmacros.h> #include <sys/trap.h> #include <sys/archsystm.h> @@ -1711,8 +1712,8 @@ fasttrap_getreg(struct regs *rp, uint_t reg) case REG_GS: return (rp->r_gs); case REG_DS: return (rp->r_ds); case REG_ES: return (rp->r_es); - case REG_FSBASE: return (rp->r_fsbase); - case REG_GSBASE: return (rp->r_gsbase); + case REG_FSBASE: return (rdmsr(MSR_AMD_FSBASE)); + case REG_GSBASE: return (rdmsr(MSR_AMD_GSBASE)); } panic("dtrace: illegal register constant"); diff --git a/usr/src/uts/intel/dtrace/fbt.c b/usr/src/uts/intel/dtrace/fbt.c index 5594958f47..78374511a2 100644 --- a/usr/src/uts/intel/dtrace/fbt.c +++ b/usr/src/uts/intel/dtrace/fbt.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -607,22 +607,26 @@ fbt_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc) * If we have a parent container, we must manually import it. */ if ((parent = ctf_parent_name(fp)) != NULL) { - struct modctl *mod; + struct modctl *mp = &modules; + struct modctl *mod = NULL; /* * We must iterate over all modules to find the module that * is our parent. */ - for (mod = &modules; mod != NULL; mod = mod->mod_next) { - if (strcmp(mod->mod_filename, parent) == 0) + do { + if (strcmp(mp->mod_modname, parent) == 0) { + mod = mp; break; - } + } + } while ((mp = mp->mod_next) != &modules); if (mod == NULL) goto err; - if ((pfp = ctf_modopen(mod->mod_mp, &error)) == NULL) + if ((pfp = ctf_modopen(mod->mod_mp, &error)) == NULL) { goto err; + } if (ctf_import(fp, pfp) != 0) { ctf_close(pfp); diff --git a/usr/src/uts/i86pc/fd/Makefile b/usr/src/uts/intel/fd/Makefile index eb39f9158b..675cc9740a 100644 --- a/usr/src/uts/i86pc/fd/Makefile +++ b/usr/src/uts/intel/fd/Makefile @@ -19,16 +19,16 @@ # CDDL HEADER END # # -# uts/i86pc/fd/Makefile +# uts/intel/fd/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" # # This makefile drives the production of the floppy driver # -# i86pc implementation architecture dependent +# intel architecture dependent # # @@ -42,13 +42,13 @@ UTSBASE = ../.. MODULE = fd OBJECTS = $(FD_OBJS:%=$(OBJS_DIR)/%) LINTS = $(FD_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/i86pc/io +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) +CONF_SRCDIR = $(UTSBASE)/intel/io # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -94,4 +94,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/fdc/Makefile b/usr/src/uts/intel/fdc/Makefile index 091cbd4a00..2ea0866fa5 100644 --- a/usr/src/uts/i86pc/fdc/Makefile +++ b/usr/src/uts/intel/fdc/Makefile @@ -19,16 +19,16 @@ # CDDL HEADER END # # -# uts/i86pc/fdc/Makefile +# uts/intel/fdc/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" # # This makefile drives the production of the floppy controller dirver # -# i86pc implementation architecture dependent +# intel architecture dependent # # @@ -42,13 +42,13 @@ UTSBASE = ../.. MODULE = fdc OBJECTS = $(FDC_OBJS:%=$(OBJS_DIR)/%) LINTS = $(FDC_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) CONF_SRCDIR = $(UTSBASE)/common/io # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -93,4 +93,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/intel/fs/proc/prmachdep.c b/usr/src/uts/intel/fs/proc/prmachdep.c index 12f0a52da4..f9a9fc3247 100644 --- a/usr/src/uts/intel/fs/proc/prmachdep.c +++ b/usr/src/uts/intel/fs/proc/prmachdep.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -59,8 +58,6 @@ #include <sys/debugreg.h> #include <sys/copyops.h> -#include <sys/mmu.h> -#include <sys/pte.h> #include <sys/vmem.h> #include <sys/mman.h> #include <sys/vmparam.h> diff --git a/usr/src/uts/intel/genunix/Makefile b/usr/src/uts/intel/genunix/Makefile index 90b6fd56fb..d4286bbfe3 100644 --- a/usr/src/uts/intel/genunix/Makefile +++ b/usr/src/uts/intel/genunix/Makefile @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -118,7 +118,15 @@ modlintlib: $(MODLINTLIB_DEPS) clean.lint: $(CLEAN_LINT_DEPS) +# +# if test is an ugly hack for race where genunix +# doesn't install sometimes +# install: $(INSTALL_DEPS) + if [ ! -f "$(ROOT_KERN_DIR)/$(MODULE)" -o \ + ! -f "$(ROOT_KERN_DIR)/amd64/$(MODULE)" ]; then \ + $(MAKE) install; \ + fi; $(LIBGEN): $(GENUNIX) $(LIBSTUBS) $(BUILD.SO) $(GENUNIX) $(LIBSTUBS) diff --git a/usr/src/uts/i86pc/i915/Makefile b/usr/src/uts/intel/i915/Makefile index a40f16cfe6..4118f40dd3 100644 --- a/usr/src/uts/i86pc/i915/Makefile +++ b/usr/src/uts/intel/i915/Makefile @@ -20,18 +20,18 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # -# uts/i86pc/drm_i915/Makefile +# uts/intel/drm_i915/Makefile # # This makefile drives the production of i915 graphics device driver, # which supports the DRI (Direct Rendering Infrastructure), with the help # of drm common misc module. # -# i86pc platform dependent +# intel platform dependent # # Path to the base of the uts directory tree (usually /usr/src/uts). # @@ -43,7 +43,7 @@ UTSBASE = ../.. MODULE = i915 OBJECTS = $(I915_OBJS:%=$(OBJS_DIR)/%) LINTS = $(I915_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) I915_DRV_O = $(OBJS_DIR)/i915_drv.o I915_DRV_C = $(PSM_DRM_SRC)/i915_drv.c DRM_PCIIDS_H = $(CMN_DRM_SRC)/drm_pciids.h @@ -51,12 +51,12 @@ DRM_PCIIDS_TXT = $(CMN_DRM_SRC)/drm_pciids.txt CREATE_SUNOS_PCI_LISTS_SH = $(CMN_DRM_SRC)/create_sunos_pci_lists.sh # i915 driver depends on drm, agpmaster and gfx_private misc modules -INC_PATH += -I$(UTSBASE)/i86pc/io/drm \ +INC_PATH += -I$(UTSBASE)/intel/io/drm \ -I$(UTSBASE)/common/io/drm \ - -I$(UTSBASE)/i86pc/io/agpmaster \ + -I$(UTSBASE)/intel/io/agpmaster \ -I$(UTSBASE)/i86pc/io/gfx_private -PSM_DRM_SRC = $(UTSBASE)/i86pc/io/drm +PSM_DRM_SRC = $(UTSBASE)/intel/io/drm CMN_DRM_SRC = $(UTSBASE)/common/io/drm # @@ -67,7 +67,7 @@ LDFLAGS += -dy -Nmisc/drm -Nmisc/agpmaster -Nmisc/gfx_private \ # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Re-define targets to add drm_pciids.h dependency @@ -119,4 +119,4 @@ $(DRM_PCIIDS_H): $(DRM_PCIIDS_TXT) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/intel/ia32/Makefile.rules b/usr/src/uts/intel/ia32/Makefile.rules deleted file mode 100644 index d8b526458e..0000000000 --- a/usr/src/uts/intel/ia32/Makefile.rules +++ /dev/null @@ -1,66 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# uts/intel/ia32/Makefile.rules -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# This Makefile defines all file modules and build rules for the -# i386-specific sources sources. These are the source files -# which are specific to the processors whose kernels use the i386 ABI. -# -# The following two-level ordering must be maintained in this file. -# Lines are sorted first in order of decreasing specificity based on -# the first directory component. That is, sun4u rules come before -# sparc rules come before common rules. -# -# Lines whose initial directory components are equal are sorted -# alphabetically by the remaining components. - -# -# Section 1a: C object build rules -# -$(OBJS_DIR)/%.o: $(UTSBASE)/intel/ia32/krtld/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/intel/ia32/krtld/%.s - $(COMPILE.s) -o $@ $< - -$(OBJS_DIR)/%.o: $(SRC)/common/util/ia32/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -# -# Section 1b: Lint `object' build rules. -# -$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/ia32/krtld/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/ia32/krtld/%.s - @($(LHEAD) $(LINT.s) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(SRC)/common/util/ia32/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) diff --git a/usr/src/uts/intel/ia32/krtld/kobj_boot.c b/usr/src/uts/intel/ia32/krtld/kobj_boot.c index 3e52f347d1..a65721d82c 100644 --- a/usr/src/uts/intel/ia32/krtld/kobj_boot.c +++ b/usr/src/uts/intel/ia32/krtld/kobj_boot.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,46 +34,22 @@ #include <sys/link.h> #include <sys/auxv.h> #include <sys/kobj.h> -#include <sys/elf.h> #include <sys/bootsvcs.h> #include <sys/kobj_impl.h> - -#if !defined(__GNUC__) +#include <vm/kboot_mmu.h> /* - * We don't use the global offset table, but - * ld may throw in an UNDEFINED reference in - * our symbol table. + * the kernel's entry point (from locore.s) */ - -#pragma weak _GLOBAL_OFFSET_TABLE_ - -#else +extern void _locore_start(); /* - * We -do- use the global offset table, but only by - * accident -- when you tell gcc to emit PIC code, - * it -always- generates a reference to the GOT in - * a register, even if the compilation unit never - * uses it. + * fakebop transfers control here. * - * Rumoured to be fixed in a later version of gcc.. - */ - -long _GLOBAL_OFFSET_TABLE_[1]; - -#endif - -#define MASK(n) ((1<<(n))-1) -#define IN_RANGE(v, n) ((-(1<<((n)-1))) <= (v) && (v) < (1<<((n)-1))) - -#define roundup ALIGN - -/* - * Boot transfers control here. At this point, - * we haven't relocated our own symbols, so the - * world (as we know it) is pretty small right now. + * fakebop and dboot don't construct any boot vector or aux vector information. + * We figure all this out for ourself instead. */ +/*ARGSUSED3*/ void _kobj_boot( struct boot_syscalls *syscallp, @@ -81,317 +57,18 @@ _kobj_boot( struct bootops *bootops, Boot *ebp) { - Shdr *section[24]; /* cache */ val_t bootaux[BA_NUM]; - struct bootops *bop; - Phdr *phdr; - auxv_t *auxv = NULL; - Shdr *sh; - Half sh_num; - uint_t end, edata = 0; int i; - bop = (dvec) ? *(struct bootops **)bootops : bootops; - for (i = 0; i < BA_NUM; i++) bootaux[i].ba_val = NULL; - /* - * Check the bootstrap vector. - */ - for (; ebp->eb_tag != EB_NULL; ebp++) { - switch (ebp->eb_tag) { - case EB_AUXV: - auxv = (auxv_t *)ebp->eb_un.eb_ptr; - break; - case EB_DYNAMIC: - bootaux[BA_DYNAMIC].ba_ptr = (void *)ebp->eb_un.eb_ptr; - break; - default: - break; - } - } - - if (auxv == NULL) - return; - - /* - * Now the aux vector. - */ - for (; auxv->a_type != AT_NULL; auxv++) { - switch (auxv->a_type) { - case AT_PHDR: - bootaux[BA_PHDR].ba_ptr = auxv->a_un.a_ptr; - break; - case AT_PHENT: - bootaux[BA_PHENT].ba_val = auxv->a_un.a_val; - break; - case AT_PHNUM: - bootaux[BA_PHNUM].ba_val = auxv->a_un.a_val; - break; - case AT_PAGESZ: - bootaux[BA_PAGESZ].ba_val = auxv->a_un.a_val; - break; - case AT_SUN_LDELF: - bootaux[BA_LDELF].ba_ptr = auxv->a_un.a_ptr; - break; - case AT_SUN_LDSHDR: - bootaux[BA_LDSHDR].ba_ptr = auxv->a_un.a_ptr; - break; - case AT_SUN_LDNAME: - bootaux[BA_LDNAME].ba_ptr = auxv->a_un.a_ptr; - break; - case AT_SUN_LPAGESZ: - bootaux[BA_LPAGESZ].ba_val = auxv->a_un.a_val; - break; - case AT_SUN_CPU: - bootaux[BA_CPU].ba_ptr = auxv->a_un.a_ptr; - break; - case AT_SUN_MMU: - bootaux[BA_MMU].ba_ptr = auxv->a_un.a_ptr; - break; - case AT_ENTRY: - bootaux[BA_ENTRY].ba_ptr = auxv->a_un.a_ptr; - break; - default: - break; - } - } - - sh = (Shdr *)bootaux[BA_LDSHDR].ba_ptr; - sh_num = ((Ehdr *)bootaux[BA_LDELF].ba_ptr)->e_shnum; - /* - * Build cache table for section addresses. - */ - for (i = 0; i < sh_num; i++) { - section[i] = sh++; - } - - /* - * Find the end of data - * (to allocate bss) - */ - phdr = (Phdr *)bootaux[BA_PHDR].ba_ptr; - for (i = 0; i < bootaux[BA_PHNUM].ba_val; i++) { - if (phdr->p_type == PT_LOAD && - (phdr->p_flags & PF_W) && (phdr->p_flags & PF_X)) { - edata = end = phdr->p_vaddr + phdr->p_memsz; - break; - } - phdr = (Phdr *)((ulong_t)phdr + bootaux[BA_PHENT].ba_val); - } - if (edata == NULL) - return; - - /* - * Find the symbol table, and then loop - * through the symbols adjusting their - * values to reflect where the sections - * were loaded. - */ - for (i = 1; i < sh_num; i++) { - Shdr *shp; - Sym *sp; - uint_t off; - - shp = section[i]; - if (shp->sh_type != SHT_SYMTAB) - continue; - - for (off = 0; off < shp->sh_size; off += shp->sh_entsize) { - sp = (Sym *)(shp->sh_addr + off); - - if (sp->st_shndx == SHN_ABS || - sp->st_shndx == SHN_UNDEF) - continue; - /* - * Assign the addresses for COMMON - * symbols even though we haven't - * actually allocated bss yet. - */ - if (sp->st_shndx == SHN_COMMON) { - end = ALIGN(end, sp->st_value); - sp->st_value = end; - /* - * Squirrel it away for later. - */ - if (bootaux[BA_BSS].ba_val == 0) - bootaux[BA_BSS].ba_val = end; - end += sp->st_size; - continue; - } else if (sp->st_shndx > (Half)sh_num) { - BSVC_PUTCHAR(syscallp, '>'); - return; - } - - /* - * Symbol's new address. - */ - sp->st_value += section[sp->st_shndx]->sh_addr; - } - } - - /* - * Allocate bss for COMMON, if any. - */ - if (end > edata) { - unsigned long va, bva; - unsigned long asize; - unsigned long align; - - if (bootaux[BA_LPAGESZ].ba_val) { - asize = bootaux[BA_LPAGESZ].ba_val; - align = bootaux[BA_LPAGESZ].ba_val; - } else { - asize = bootaux[BA_PAGESZ].ba_val; - align = BO_NO_ALIGN; - } - va = roundup(edata, asize); - bva = roundup(end, asize); - - if (bva > va) { - bva = (unsigned long)BOP_ALLOC(bop, (caddr_t)va, - bva - va, align); - if (bva == NULL) - return; - } - /* - * Zero it. - */ - for (va = edata; va < end; va++) - *(char *)va = 0; - /* - * Update the size of data. - */ - phdr->p_memsz += (end - edata); - } - - /* - * Relocate our own symbols. We'll handle the - * undefined symbols later. - */ - for (i = 1; i < sh_num; i++) { - Shdr *rshp, *shp, *ssp; - unsigned long baseaddr, reladdr, rend; - int relocsize; - - rshp = section[i]; - - if (rshp->sh_type != SHT_REL) - continue; - /* - * Get the section being relocated - * and the symbol table. - */ - shp = section[rshp->sh_info]; - ssp = section[rshp->sh_link]; - - reladdr = rshp->sh_addr; - baseaddr = shp->sh_addr; - rend = reladdr + rshp->sh_size; - relocsize = rshp->sh_entsize; - /* - * Loop through relocations. - */ - while (reladdr < rend) { - Sym *symref; - Rel *reloc; - unsigned long stndx; - unsigned long off, *offptr; - long value; - int rtype; - - reloc = (Rel *)reladdr; - off = reloc->r_offset; - rtype = ELF32_R_TYPE(reloc->r_info); - stndx = ELF32_R_SYM(reloc->r_info); - - reladdr += relocsize; - - if (rtype == R_386_NONE) { - continue; - } - off += baseaddr; - - if (rtype == R_386_RELATIVE) { - /* - * add base addr to reloc location - */ - value = baseaddr; - } else { - unsigned int symoff, symsize; - - symsize = ssp->sh_entsize; - - for (symoff = 0; stndx; stndx--) - symoff += symsize; - symref = (Sym *)(ssp->sh_addr + symoff); - - /* - * Check for bad symbol index. - */ - if (symoff > ssp->sh_size) - return; - - /* - * Just bind our own symbols at this point. - */ - if (symref->st_shndx == SHN_UNDEF) { - continue; - } - - value = symref->st_value; - if (ELF32_ST_BIND(symref->st_info) != - STB_LOCAL) { - /* - * If PC-relative, subtract ref addr. - */ - if (rtype == R_386_PC32 || - rtype == R_386_PLT32 || - rtype == R_386_GOTPC) - value -= off; - } - } - offptr = (unsigned long *)off; - /* - * insert value calculated at reference point - * 2 cases - normal byte order aligned, normal byte - * order unaligned. - */ - switch (rtype) { - case R_386_PC32: - case R_386_32: - case R_386_PLT32: - case R_386_RELATIVE: - *offptr += value; - break; - - /* - * For now, ignore GOT references ... - */ - - case R_386_GOTPC: -#if defined(DEBUG) && !defined(__GNUC__) - BSVC_PUTCHAR(syscallp, 'p'); -#endif - break; - case R_386_GOTOFF: - BSVC_PUTCHAR(syscallp, 'g'); - break; - default: - BSVC_PUTCHAR(syscallp, 'r'); - return; - } - /* - * We only need to do it once. - */ - reloc->r_info = ELF32_R_INFO(stndx, R_386_NONE); - } /* while */ - } + bootaux[BA_ENTRY].ba_ptr = (void *)_locore_start; + bootaux[BA_PAGESZ].ba_val = MMU_PAGESIZE; + bootaux[BA_LPAGESZ].ba_val = kbm_nucleus_size; /* - * Done relocating all of our *defined* - * symbols, so we hand off. + * Initialize krtld. */ kobj_init(syscallp, dvec, bootops, bootaux); } diff --git a/usr/src/uts/intel/ia32/krtld/kobj_crt.s b/usr/src/uts/intel/ia32/krtld/kobj_crt.s index 531924c730..fee3a73953 100644 --- a/usr/src/uts/intel/ia32/krtld/kobj_crt.s +++ b/usr/src/uts/intel/ia32/krtld/kobj_crt.s @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -61,14 +60,6 @@ save_esp2: movl %esp, %eax movl %eax, save_esp2 - movl boothowto, %eax - andl $RB_DEBUGENTER, %eax - jz 1f - - /* enter the debugger */ - int $T_DBGENTR - -1: /holds address of array of pointers to functions movl $romp, %eax movl (%eax), %ecx diff --git a/usr/src/uts/intel/ia32/ml/copy.s b/usr/src/uts/intel/ia32/ml/copy.s index f30b864a46..c04aa8c88b 100644 --- a/usr/src/uts/intel/ia32/ml/copy.s +++ b/usr/src/uts/intel/ia32/ml/copy.s @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -68,6 +68,7 @@ kcopy(const void *from, void *to, size_t count) #else /* __lint */ .globl kernelbase + .globl postbootkernelbase #if defined(__amd64) @@ -75,10 +76,9 @@ kcopy(const void *from, void *to, size_t count) pushq %rbp movq %rsp, %rbp #ifdef DEBUG - movq kernelbase(%rip), %rax - cmpq %rax, %rdi /* %rdi = from */ + cmpq postbootkernelbase(%rip), %rdi /* %rdi = from */ jb 0f - cmpq %rax, %rsi /* %rsi = to */ + cmpq postbootkernelbase(%rip), %rsi /* %rsi = to */ jnb 1f 0: leaq .kcopy_panic_msg(%rip), %rdi xorl %eax, %eax @@ -127,7 +127,7 @@ _kcopy_copyerr: #ifdef DEBUG pushl %ebp movl %esp, %ebp - movl kernelbase, %eax + movl postbootkernelbase, %eax cmpl %eax, ARG_FROM(%ebp) jb 0f cmpl %eax, ARG_TO(%ebp) @@ -216,10 +216,9 @@ kcopy_nta(const void *from, void *to, size_t count, int copy_cached) pushq %rbp movq %rsp, %rbp #ifdef DEBUG - movq kernelbase(%rip), %rax - cmpq %rax, %rdi /* %rdi = from */ + cmpq postbootkernelbase(%rip), %rdi /* %rdi = from */ jb 0f - cmpq %rax, %rsi /* %rsi = to */ + cmpq postbootkernelbase(%rip), %rsi /* %rsi = to */ jnb 1f 0: leaq .kcopy_panic_msg(%rip), %rdi xorl %eax, %eax @@ -359,10 +358,9 @@ bcopy(const void *from, void *to, size_t count) #ifdef DEBUG orq %rdx, %rdx /* %rdx = count */ jz 1f - movq kernelbase(%rip), %rax - cmpq %rax, %rdi /* %rdi = from */ + cmpq postbootkernelbase(%rip), %rdi /* %rdi = from */ jb 0f - cmpq %rax, %rsi /* %rsi = to */ + cmpq postbootkernelbase(%rip), %rsi /* %rsi = to */ jnb 1f 0: leaq .bcopy_panic_msg(%rip), %rdi jmp call_panic /* setup stack and call panic */ @@ -410,7 +408,7 @@ call_panic: movl ARG_COUNT(%esp), %eax orl %eax, %eax jz 1f - movl kernelbase, %eax + movl postbootkernelbase, %eax cmpl %eax, ARG_FROM(%esp) jb 0f cmpl %eax, ARG_TO(%esp) @@ -467,7 +465,7 @@ kzero(void *addr, size_t count) ENTRY(kzero) #ifdef DEBUG - cmpq kernelbase(%rip), %rdi /* %rdi = addr */ + cmpq postbootkernelbase(%rip), %rdi /* %rdi = addr */ jnb 0f leaq .kzero_panic_msg(%rip), %rdi jmp call_panic /* setup stack and call panic */ @@ -512,7 +510,7 @@ _kzeroerr: #ifdef DEBUG pushl %ebp movl %esp, %ebp - movl kernelbase, %eax + movl postbootkernelbase, %eax cmpl %eax, ARG_ADDR(%ebp) jnb 0f pushl $.kzero_panic_msg @@ -578,7 +576,7 @@ bzero(void *addr, size_t count) ENTRY(bzero) #ifdef DEBUG - cmpq kernelbase(%rip), %rdi /* %rdi = addr */ + cmpq postbootkernelbase(%rip), %rdi /* %rdi = addr */ jnb 0f leaq .bzero_panic_msg(%rip), %rdi jmp call_panic /* setup stack and call panic */ @@ -605,7 +603,7 @@ do_zero: ENTRY(bzero) #ifdef DEBUG - movl kernelbase, %eax + movl postbootkernelbase, %eax cmpl %eax, ARG_ADDR(%esp) jnb 0f pushl %ebp diff --git a/usr/src/uts/intel/ia32/ml/desctbls_asm.s b/usr/src/uts/intel/ia32/ml/desctbls_asm.s index c9428ec997..b55b4ccdc2 100644 --- a/usr/src/uts/intel/ia32/ml/desctbls_asm.s +++ b/usr/src/uts/intel/ia32/ml/desctbls_asm.s @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,6 +32,7 @@ #include <sys/ontrap.h> #include <sys/privregs.h> #include <sys/segments.h> +#include <sys/trap.h> #if defined(__lint) #include <sys/types.h> @@ -45,19 +46,16 @@ #include "assym.h" #endif /* __lint */ -#if !defined(__lint) - DGDEF3(gdt0, MMU_STD_PAGESIZE, MMU_STD_PAGESIZE) - .zero MMU_STD_PAGESIZE -#endif /* __lint */ - #if defined(__lint) /*ARGSUSED*/ -void rd_idtr(desctbr_t *idtr) +void +rd_idtr(desctbr_t *idtr) {} /*ARGSUSED*/ -void wr_idtr(desctbr_t *idtr) +void +wr_idtr(desctbr_t *idtr) {} #else /* __lint */ @@ -100,11 +98,13 @@ void wr_idtr(desctbr_t *idtr) #if defined(__lint) /*ARGSUSED*/ -void rd_gdtr(desctbr_t *gdtr) +void +rd_gdtr(desctbr_t *gdtr) {} /*ARGSUSED*/ -void wr_gdtr(desctbr_t *gdtr) +void +wr_gdtr(desctbr_t *gdtr) {} #else /* __lint */ @@ -112,34 +112,22 @@ void wr_gdtr(desctbr_t *gdtr) #if defined(__amd64) ENTRY_NP(rd_gdtr) + pushq %rbp + movq %rsp, %rbp sgdt (%rdi) + leave ret SET_SIZE(rd_gdtr) ENTRY_NP(wr_gdtr) + pushq %rbp + movq %rsp, %rbp lgdt (%rdi) jmp 1f nop 1: - movl $KDS_SEL, %eax - movw %ax, %ss - /* - * zero %ds and %es - they're ignored anyway - */ - xorl %eax, %eax - movw %ax, %ds - movw %ax, %es - /* - * set %fs and %gs (probably to zero also) - */ - movl $KFS_SEL, %eax - movw %ax, %fs - movl $KGS_SEL, %eax - movw %ax, %gs - popq %rax - pushq $KCS_SEL - pushq %rax - lretq + leave + ret SET_SIZE(wr_gdtr) #elif defined(__i386) @@ -158,17 +146,9 @@ void wr_gdtr(desctbr_t *gdtr) movl %esp, %ebp movl 8(%ebp), %edx lgdt (%edx) + jmp 1f nop - ljmp $KCS_SEL, $.next -.next: - movl $KDS_SEL, %eax - movw %ax, %ds - movw %ax, %es - movw %ax, %ss - movl $KFS_SEL, %eax - movw %ax, %fs - movl $KGS_SEL, %eax - movw %ax, %gs +1: leave ret SET_SIZE(wr_gdtr) @@ -176,17 +156,96 @@ void wr_gdtr(desctbr_t *gdtr) #endif /* __i386 */ #endif /* __lint */ +#if defined(__amd64) +#if defined(__lint) + +/*ARGSUSED*/ +void +load_segment_registers(selector_t cs, selector_t fs, selector_t gs, + selector_t ss) +{} + +#else /* __lint */ + + /* + * loads zero selector for ds and es. + */ + ENTRY_NP(load_segment_registers) + pushq %rbp + movq %rsp, %rbp + pushq %rdi + pushq $.newcs + lretq +.newcs: + /* + * zero %ds and %es - they're ignored anyway + */ + xorl %eax, %eax + movw %ax, %ds + movw %ax, %es + movl %esi, %eax + movw %ax, %fs + movl %edx, %eax + movw %ax, %gs + movl %ecx, %eax + movw %ax, %ss + leave + ret + SET_SIZE(load_segment_registers) + +#endif /* __lint */ +#elif defined(__i386) + +#if defined(__lint) + +/*ARGSUSED*/ +void +load_segment_registers( + selector_t cs, selector_t ds, selector_t es, + selector_t fs, selector_t gs, selector_t ss) +{} + +#else /* __lint */ + + ENTRY_NP(load_segment_registers) + pushl %ebp + movl %esp, %ebp + + pushl 0x8(%ebp) + pushl $.newcs + lret +.newcs: + movw 0xc(%ebp), %ax + movw %ax, %ds + movw 0x10(%ebp), %ax + movw %ax, %es + movw 0x14(%ebp), %ax + movw %ax, %fs + movw 0x18(%ebp), %ax + movw %ax, %gs + movw 0x1c(%ebp), %ax + movw %ax, %ss + leave + ret + SET_SIZE(load_segment_registers) + +#endif /* __lint */ +#endif /* __i386 */ + #if defined(__lint) /*ARGSUSED*/ -void wr_ldtr(selector_t ldtsel) +void +wr_ldtr(selector_t ldtsel) {} -selector_t rd_ldtr(void) +selector_t +rd_ldtr(void) { return (0); } #if defined(__amd64) -void clr_ldt_sregs(void) +void +clr_ldt_sregs(void) {} #endif @@ -264,7 +323,8 @@ void clr_ldt_sregs(void) #if defined(__lint) /*ARGSUSED*/ -void wr_tsr(selector_t tsssel) +void +wr_tsr(selector_t tsssel) {} #else /* __lint */ diff --git a/usr/src/uts/intel/ia32/ml/exception.s b/usr/src/uts/intel/ia32/ml/exception.s index 11d38dc542..08817134a9 100644 --- a/usr/src/uts/intel/ia32/ml/exception.s +++ b/usr/src/uts/intel/ia32/ml/exception.s @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -48,6 +48,7 @@ #include <sys/regset.h> #include <sys/privregs.h> #include <sys/dtrace.h> +#include <sys/x86_archext.h> #include <sys/traptrace.h> #include <sys/machparam.h> @@ -71,10 +72,13 @@ ndptrap_frstor(void) * of the kernel can expect a consistent stack * from from any exception. */ + #define TRAP_NOERR(trapno) \ push $0; \ push $trapno +#define NPTRAP_NOERR(trapno) TRAP_NOERR(trapno) + /* * error code already pushed by hw * onto stack. @@ -82,6 +86,7 @@ ndptrap_frstor(void) #define TRAP_ERR(trapno) \ push $trapno + /* * #DE */ @@ -90,10 +95,17 @@ ndptrap_frstor(void) jmp cmntrap SET_SIZE(div0trap) -#if defined(__amd64) /* * #DB * + * Fetch %dr6 and clear it, handing off the value to the + * cmntrap code in %r15/%esi + */ + ENTRY_NP(dbgtrap) + TRAP_NOERR(T_SGLSTP) /* $1 */ + +#if defined(__amd64) + /* * If we get here as a result of single-stepping a sysenter * instruction, we suddenly find ourselves taking a #db * in kernel mode -before- we've swapgs'ed. So before we can @@ -104,36 +116,38 @@ ndptrap_frstor(void) * Nobody said that the design of sysenter was particularly * elegant, did they? */ - ENTRY_NP(dbgtrap) pushq %r11 leaq sys_sysenter(%rip), %r11 cmpq %r11, 8(%rsp) jne 1f - swapgs + SWAPGS 1: popq %r11 - TRAP_NOERR(T_SGLSTP) /* $1 */ - jmp cmntrap - SET_SIZE(dbgtrap) + + INTR_PUSH + movq %db6, %r15 + xorl %eax, %eax + movq %rax, %db6 #elif defined(__i386) - /* - * #DB - */ - ENTRY_NP(dbgtrap) - TRAP_NOERR(T_SGLSTP) /* $1 */ - jmp cmntrap + + INTR_PUSH + movl %db6, %esi + xorl %eax, %eax + movl %eax, %db6 +#endif /* __i386 */ + + jmp cmntrap_pushed SET_SIZE(dbgtrap) -#endif #if defined(__amd64) /* * Macro to set the gsbase or kgsbase to the address of the struct cpu - * for this processor. If we came from userland, set kgsbase else clear - * gs and set gsbase. We find the proper cpu struct by looping through + * for this processor. If we came from userland, set kgsbase else + * set gsbase. We find the proper cpu struct by looping through * the cpu structs for all processors till we find a match for the gdt * of the trapping processor. The stack is expected to be pointing at - * The standard regs pushed by hardware on a trap (plus error code and trapno). + * the standard regs pushed by hardware on a trap (plus error code and trapno). */ #define SET_CPU_GSBASE \ subq $REGOFF_TRAPNO, %rsp; /* save regs */ \ @@ -176,13 +190,9 @@ ndptrap_frstor(void) movq %rbp, %rsp; \ movq REGOFF_RBP(%rsp), %rbp; \ addq $REGOFF_TRAPNO, %rsp /* pop stack */ + #endif /* __amd64 */ - - - - - .globl nmivect - .globl idt0_default_r + #if defined(__amd64) @@ -199,11 +209,9 @@ ndptrap_frstor(void) * with kernel selectors. */ INTR_PUSH - - DISABLE_INTR_FLAGS /* and set the kernel flags */ + INTGATE_INIT_KERNEL_FLAGS TRACE_PTR(%r12, %rax, %eax, %rdx, $TT_TRAP) - TRACE_REGS(%r12, %rsp, %rax, %rbx) TRACE_STAMP(%r12) @@ -213,7 +221,8 @@ ndptrap_frstor(void) call av_dispatch_nmivect INTR_POP - iretq + IRET + /*NOTREACHED*/ SET_SIZE(nmiint) #elif defined(__i386) @@ -229,30 +238,20 @@ ndptrap_frstor(void) * with kernel selectors. */ INTR_PUSH + INTGATE_INIT_KERNEL_FLAGS + + TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_TRAP) + TRACE_REGS(%edi, %esp, %ebx, %ecx) + TRACE_STAMP(%edi) - /* - * setup pointer to reg struct as 2nd argument. - */ movl %esp, %ebp + pushl %ebp - - DISABLE_INTR_FLAGS - - movl nmivect, %esi /* get autovect structure */ -loop1: - cmpl $0, %esi /* if pointer is null */ - je .intr_ret /* we're done */ - movl AV_VECTOR(%esi), %edx /* get the interrupt routine */ - pushl AV_INTARG1(%esi) /* get argument to interrupt routine */ - call *%edx /* call interrupt routine with arg */ + call av_dispatch_nmivect addl $4, %esp - movl AV_LINK(%esi), %esi /* get next routine on list */ - jmp loop1 /* keep looping until end of list */ -.intr_ret: - addl $4, %esp /* 'pop' %ebp */ INTR_POP_USER - iret + IRET SET_SIZE(nmiint) #endif /* __i386 */ @@ -261,16 +260,11 @@ loop1: * #BP */ ENTRY_NP(brktrap) + #if defined(__amd64) cmpw $KCS_SEL, 8(%rsp) - je bp_jmpud -#endif - - TRAP_NOERR(T_BPTFLT) /* $3 */ - jmp dtrace_trap + jne bp_user -#if defined(__amd64) -bp_jmpud: /* * This is a breakpoint in the kernel -- it is very likely that this * is DTrace-induced. To unify DTrace handling, we spoof this as an @@ -282,8 +276,13 @@ bp_jmpud: decq (%rsp) push $1 /* error code -- non-zero for #BP */ jmp ud_kernel -#endif - + +bp_user: +#endif /* __amd64 */ + + NPTRAP_NOERR(T_BPTFLT) /* $3 */ + jmp dtrace_trap + SET_SIZE(brktrap) /* @@ -305,13 +304,14 @@ bp_jmpud: #if defined(__amd64) ENTRY_NP(invoptrap) + cmpw $KCS_SEL, 8(%rsp) jne ud_user push $0 /* error code -- zero for #UD */ ud_kernel: push $0xdddd /* a dummy trap number */ - TRAP_PUSH + INTR_PUSH movq REGOFF_RIP(%rsp), %rdi movq REGOFF_RSP(%rsp), %rsi movq REGOFF_RAX(%rsp), %rdx @@ -353,7 +353,8 @@ ud_push: movq 32(%rsp), %rax /* reload calling RSP */ movq %rbp, (%rax) /* store %rbp there */ popq %rax /* pop off temp */ - iretq /* return from interrupt */ + IRET /* return from interrupt */ + /*NOTREACHED*/ ud_leave: /* @@ -373,7 +374,8 @@ ud_leave: movq %rbp, 32(%rsp) /* store new %rsp */ movq %rax, %rbp /* set new %rbp */ popq %rax /* pop off temp */ - iretq /* return from interrupt */ + IRET /* return from interrupt */ + /*NOTREACHED*/ ud_nop: /* @@ -382,7 +384,8 @@ ud_nop: */ INTR_POP incq (%rsp) - iretq + IRET + /*NOTREACHED*/ ud_ret: INTR_POP @@ -392,7 +395,8 @@ ud_ret: movq %rax, 8(%rsp) /* store calling RIP */ addq $8, 32(%rsp) /* adjust new %rsp */ popq %rax /* pop off temp */ - iretq /* return from interrupt */ + IRET /* return from interrupt */ + /*NOTREACHED*/ ud_trap: /* @@ -405,13 +409,13 @@ ud_trap: je ud_ud incq REGOFF_RIP(%rsp) addq $REGOFF_RIP, %rsp - TRAP_NOERR(T_BPTFLT) /* $3 */ + NPTRAP_NOERR(T_BPTFLT) /* $3 */ jmp cmntrap ud_ud: addq $REGOFF_RIP, %rsp ud_user: - TRAP_NOERR(T_ILLINST) + NPTRAP_NOERR(T_ILLINST) jmp cmntrap SET_SIZE(invoptrap) @@ -428,6 +432,7 @@ ud_user: pushl %gs cmpw $KGS_SEL, (%esp) jne 8f + addl $4, %esp pusha pushl %eax /* push %eax -- may be return value */ @@ -446,7 +451,6 @@ ud_user: cmpl $DTRACE_INVOP_NOP, %eax je 4f jmp 7f - 1: /* * We must emulate a "pushl %ebp". To do this, we pull the stack @@ -464,8 +468,7 @@ ud_user: movl %eax, 12(%esp) /* store calling EFLAGS */ movl %ebp, 16(%esp) /* push %ebp */ popl %eax /* pop off temp */ - iret /* return from interrupt */ - + jmp _emul_done 2: /* * We must emulate a "popl %ebp". To do this, we do the opposite of @@ -484,8 +487,7 @@ ud_user: movl %eax, 8(%esp) /* store calling EIP */ popl %eax /* pop off temp */ addl $4, %esp /* adjust stack pointer */ - iret /* return from interrupt */ - + jmp _emul_done 3: /* * We must emulate a "leave", which is the same as a "movl %ebp, %esp" @@ -510,8 +512,7 @@ ud_user: popl %eax /* pop off temp */ movl -12(%esp), %esp /* set stack pointer */ subl $8, %esp /* adjust for three pushes, one pop */ - iret /* return from interrupt */ - + jmp _emul_done 4: /* * We must emulate a "nop". This is obviously not hard: we need only @@ -519,8 +520,8 @@ ud_user: */ popa incl (%esp) - iret - +_emul_done: + IRET /* return from interrupt */ 7: popa pushl $0 @@ -553,9 +554,9 @@ ud_user: LOADCPU(%rbx) /* if yes, don't swapgs */ jmp 2f 1: - swapgs /* if from user, need swapgs */ + SWAPGS /* if from user, need swapgs */ LOADCPU(%rbx) - swapgs + SWAPGS 2: cmpl $0, fpu_exists(%rip) je .handle_in_trap /* let trap handle no fp case */ @@ -582,7 +583,8 @@ ud_user: fxrstor (%rax) popq %rbx popq %rax - iretq + IRET + /*NOTREACHED*/ .handle_in_trap: popq %rbx @@ -608,46 +610,45 @@ ud_user: movw %bx, %ds movl $KGS_SEL, %eax movw %ax, %gs - LOADCPU(%ebx) + LOADCPU(%eax) cmpl $0, fpu_exists je .handle_in_trap /* let trap handle no fp case */ - movl CPU_THREAD(%ebx), %eax /* %eax = curthread */ - movl $FPU_EN, %ebx - movl T_LWP(%eax), %eax /* %eax = lwp */ - testl %eax, %eax + movl CPU_THREAD(%eax), %ebx /* %ebx = curthread */ + movl $FPU_EN, %eax + movl T_LWP(%ebx), %ebx /* %ebx = lwp */ + testl %ebx, %ebx jz .handle_in_trap /* should not happen? */ #if LWP_PCB_FPU != 0 - addl $LWP_PCB_FPU, %eax /* &lwp->lwp_pcb.pcb_fpu */ + addl $LWP_PCB_FPU, %ebx /* &lwp->lwp_pcb.pcb_fpu */ #endif - testl %ebx, PCB_FPU_FLAGS(%eax) + testl %eax, PCB_FPU_FLAGS(%ebx) jz .handle_in_trap /* must be the first fault */ - clts - andl $_BITNOT(FPU_VALID), PCB_FPU_FLAGS(%eax) + CLTS + andl $_BITNOT(FPU_VALID), PCB_FPU_FLAGS(%ebx) #if FPU_CTX_FPU_REGS != 0 - addl $FPU_CTX_FPU_REGS, %eax + addl $FPU_CTX_FPU_REGS, %ebx #endif /* * the label below is used in trap.c to detect FP faults in kernel * due to user fault. */ ALTENTRY(ndptrap_frstor) - .globl _patch_fxrstor_eax -_patch_fxrstor_eax: - frstor (%eax) /* may be patched to fxrstor */ + .globl _patch_fxrstor_ebx +_patch_fxrstor_ebx: + frstor (%ebx) /* may be patched to fxrstor */ nop /* (including this byte) */ popl %gs popl %ds popl %ebx popl %eax - iret + IRET .handle_in_trap: popl %gs popl %ds popl %ebx popl %eax - pushl $0 - pushl $T_NOEXTFLT /* $7 */ + TRAP_NOERR(T_NOEXTFLT) /* $7 */ jmp cmninttrap SET_SIZE(ndptrap_frstor) SET_SIZE(ndptrap) @@ -880,11 +881,21 @@ make_frame: */ ENTRY_NP(pftrap) TRAP_ERR(T_PGFLT) /* $14 already have error code on stack */ - jmp cmntrap + INTR_PUSH + +#if defined(__amd64) + movq %cr2, %r15 +#elif defined(__i386) + movl %cr2, %esi +#endif /* __i386 */ + + jmp cmntrap_pushed SET_SIZE(pftrap) #if !defined(__amd64) + .globl idt0_default_r + /* * #PF pentium bug workaround */ @@ -950,14 +961,16 @@ check_for_user_address: ENTRY_NP(mcetrap) TRAP_NOERR(T_MCE) /* $18 */ + SET_CPU_GSBASE + INTR_PUSH + INTGATE_INIT_KERNEL_FLAGS TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_TRAP) TRACE_REGS(%rdi, %rsp, %rbx, %rcx) TRACE_STAMP(%rdi) - DISABLE_INTR_FLAGS movq %rsp, %rbp movq %rsp, %rdi /* arg0 = struct regs *rp */ @@ -970,9 +983,14 @@ check_for_user_address: ENTRY_NP(mcetrap) TRAP_NOERR(T_MCE) /* $18 */ + INTR_PUSH + INTGATE_INIT_KERNEL_FLAGS + + TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_TRAP) + TRACE_REGS(%edi, %esp, %ebx, %ecx) + TRACE_STAMP(%edi) - DISABLE_INTR_FLAGS movl %esp, %ebp movl %esp, %ecx @@ -1065,14 +1083,15 @@ check_for_user_address: */ ENTRY_NP(fast_null) orq $PS_C, 24(%rsp) /* set carry bit in user flags */ - iretq + IRET + /*NOTREACHED*/ SET_SIZE(fast_null) #elif defined(__i386) ENTRY_NP(fast_null) orw $PS_C, 8(%esp) /* set carry bit in user flags */ - iret + IRET SET_SIZE(fast_null) #endif /* __i386 */ diff --git a/usr/src/uts/intel/ia32/ml/float.s b/usr/src/uts/intel/ia32/ml/float.s index 79ee9b8d92..81dc8dc3f4 100644 --- a/usr/src/uts/intel/ia32/ml/float.s +++ b/usr/src/uts/intel/ia32/ml/float.s @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +34,7 @@ #pragma ident "%Z%%M% %I% %E% SMI" #include <sys/asm_linkage.h> +#include <sys/asm_misc.h> #include <sys/regset.h> #include <sys/privregs.h> #include <sys/x86_archext.h> @@ -46,380 +47,127 @@ #endif #if defined(__lint) - -int fpu_exists = 1; -int fp_kind = FP_387; -int fpu_ignored = 0; - -int use_sse_pagecopy = 0; -int use_sse_pagezero = 0; -int use_sse_copy = 0; - -#if defined(__i386) - -int fpu_pentium_fdivbug = 0; - -#endif + +uint_t +fpu_initial_probe(void) +{ return (0); } #else /* __lint */ /* - * If fpu_exists is non-zero, fpu_probe will attempt to use any - * hardware FPU (subject to other constraints, see below). If - * fpu_exists is zero, fpu_probe will report that there is no - * FPU even if there is one. + * Returns zero if x87 "chip" is present(!) */ - DGDEF3(fpu_exists, 4, 4) - .long 1 - - DGDEF3(fp_kind, 4, 4) - .long FP_387 /* FP_NO, FP_287, FP_387, etc. */ - - /* - * The variable fpu_ignored is provided to allow other code to - * determine whether emulation is being done because there is - * no FPU or because of an override requested via /etc/system. - */ - DGDEF3(fpu_ignored, 4, 4) - .long 0 - - /* - * Used by ppcopy, ppzero, and xcopyin to determine whether or not - * to use the SSE-based routines - */ - DGDEF3(use_sse_pagecopy, 4, 4) - .long 0 - - DGDEF3(use_sse_pagezero, 4, 4) - .long 0 - - DGDEF3(use_sse_copy, 4, 4) - .long 0 - -#if defined(__i386) - - /* - * The variable fpu_pentium_fdivbug is provided to allow other code to - * determine whether the system contains a Pentium with the FDIV - * problem. - */ - DGDEF3(fpu_pentium_fdivbug, 4, 4) - .long 0 - - /* - * The following constants are used for detecting the Pentium - * divide bug. - */ - .align 4 -num1: .4byte 0xbce4217d /* 4.999999 */ - .4byte 0x4013ffff -num2: .4byte 0x0 /* 15.0 */ - .4byte 0x402e0000 -num3: .4byte 0xde7210bf /* 14.999999 */ - .4byte 0x402dffff + ENTRY_NP(fpu_initial_probe) + CLTS + fninit + fnstsw %ax + movzbl %al, %eax + ret + SET_SIZE(fpu_initial_probe) -#endif /* __i386 */ #endif /* __lint */ -/* - * FPU probe - check if we have any FP chip present by trying to do a reset. - * If that succeeds, differentiate via cr0. Called from autoconf. - */ - #if defined(__lint) - + /*ARGSUSED*/ void -fpu_probe(void) +fxsave_insn(struct fxsave_state *fx) {} #else /* __lint */ #if defined(__amd64) - ENTRY_NP(fpu_probe) - pushq %rbp - movq %rsp, %rbp - clts /* clear task switched bit in CR0 */ - fninit /* initialize chip */ - fnstsw %ax /* get status */ - orb %al, %al /* status zero? 0 = chip present */ - jnz no_fpu_hw - - /* - * Ignore the FPU if fp_exists == 0 - */ - cmpl $0, fpu_exists(%rip) - je ignore_fpu - - /* - * we have a chip of some sort; use cr0 to differentiate - */ - movq %cr0, %rdx /* check for fpu present flag */ - testl $CR0_ET, %edx - jz no_fpu_hw /* z -> fpu not present */ - testl $X86_SSE, x86_feature(%rip) - je no_fpu_hw /* SSE is utterly required */ - testl $X86_SSE2, x86_feature(%rip) - je no_fpu_hw /* SSE2 too .. */ - movl $__FP_SSE, fp_kind(%rip) + ENTRY_NP(fxsave_insn) + fxsave (%rdi) + ret + SET_SIZE(fxsave_insn) - /* - * Tell the processor what we're doing via %cr4 - */ - movq %cr4, %rax - orq $_CONST(CR4_OSFXSR | CR4_OSXMMEXCPT), %rax - movq %rax, %cr4 +#elif defined(__i386) - /* - * make other CPUs share the same cr4 settings - */ - orq $_CONST(CR4_OSFXSR | CR4_OSXMMEXCPT), cr4_value(%rip) + ENTRY_NP(fxsave_insn) + movl 4(%esp), %eax + fxsave (%eax) + ret + SET_SIZE(fxsave_insn) - /* - * extract the MXCSR_MASK field from our first fxsave - */ - subq $FXSAVE_STATE_SIZE, %rsp - movl $0, FXSAVE_STATE_MXCSR_MASK(%rsp) - fxsave (%rsp) - movl FXSAVE_STATE_MXCSR_MASK(%rsp), %eax - cmpl $0, %eax - je 1f /* default mask value set in fpu.c */ - movl %eax, sse_mxcsr_mask(%rip) /* override mask set here */ -1: - movq %cr0, %rax - andq $_BITNOT(CR0_TS|CR0_EM), %rdx /* clear emulate math bit */ - orq $_CONST(CR0_MP|CR0_NE), %rdx +#endif - /* - * We have SSE and SSE2 so enable the extensions for - * non-temporal copies and stores. - */ - movl $1, use_sse_pagecopy - movl $1, use_sse_pagezero - movl $1, use_sse_copy +#endif /* __lint */ - jmp done +#if defined(__i386) - /* - * Do not use the FPU at all - */ -ignore_fpu: - movl $1, fpu_ignored(%rip) +/* + * If (num1/num2 > num1/num3) the FPU has the FDIV bug. + */ - /* - * No FPU hardware present - */ -no_fpu_hw: - andq $_BITNOT(CR0_MP), %rdx /* clear math chip present */ - orq $CR0_EM, %rdx /* set emulate math bit */ - movl $FP_NO, fp_kind(%rip) /* signify that there is no FPU */ - movl $0, fpu_exists(%rip) /* no FPU present */ - /* - * Disable the XMM-related gorp too, in case the BIOS set them - */ - movq %cr4, %rax - andq $_BITNOT(CR4_OSFXSR | CR4_OSXMMEXCPT), %rax - movq %rax, %cr4 - andq $_BITNOT(CR4_OSFXSR | CR4_OSXMMEXCPT), cr4_value(%rip) +#if defined(__lint) -done: - movq %rdx, %cr0 /* set machine status word */ - leave - ret - SET_SIZE(fpu_probe) +int +fpu_probe_pentium_fdivbug(void) +{ return (0); } -#elif defined(__i386) +#else /* __lint */ - ENTRY_NP(fpu_probe) - clts / clear task switched bit in CR0 - fninit / initialize chip - fnstsw %ax / get status - orb %al, %al / status zero? 0 = chip present - jnz no_fpu_hw / no, use emulator -/ -/ If there is an FP, look for the Pentium FDIV problem even if we -/ do not plan to use it. Set fpu_pentium_fdivbug is a bad FPU is -/ detected. Subsequent code can report the result if desired. -/ -/ If (num1/num2 > num1/num3) the FPU has the FDIV bug. -/ - fldl num1 - fldl num2 + ENTRY_NP(fpu_probe_pentium_fdivbug) + fldl .num1 + fldl .num2 fdivr %st(1), %st fxch %st(1) - fdivl num3 + fdivl .num3 fcompp fstsw %ax sahf - jae no_bug - movl $1, fpu_pentium_fdivbug -no_bug: -/ -/ Repeat the earlier initialization sequence so that the FPU is left in -/ the expected state. -/ - fninit - fnstsw %ax -/ -/ Ignore the FPU if fpu_exists == 0 -/ - cmpl $0, fpu_exists - je ignore_fpu -/ -/ Ignore the FPU if it has the Pentium bug -/ - cmpl $0, fpu_pentium_fdivbug - jne ignore_fpu -/ -/ at this point we know we have a chip of some sort; -/ use cr0 to differentiate. -/ - movl %cr0, %edx / check for 387 present flag - testl $CR0_ET, %edx / ... - jz is287 / z -> 387 not present - movl $FP_387, fp_kind / we have a 387 or later chip -/ -/ clear the "XMM supported" bits in %cr4 in case the BIOS set them -/ erroneously -- see 4965674 -/ - movl %cr4, %eax - andl $_BITNOT(CR4_OSFXSR | CR4_OSXMMEXCPT), %eax - movl %eax, %cr4 - andl $_BITNOT(CR4_OSFXSR | CR4_OSXMMEXCPT), cr4_value - - testl $X86_SSE, x86_feature / can we do SSE? - je mathchip -/ -/ aha .. we have an SSE-capable chip -/ -/ - set fpsave_begin to fpxsave_begin -/ - hot patch performance critical code to use fxsave/fxrstor directly, -/ and hot patch membar_producer() to use sfence instead of lock -/ - tell the processor what we're doing via %cr4 -/ - allow fully fledged #XM exceptions to be generated by SSE/SSE2 -/ (the default mask set in fpinit() disables them) -/ - determine the mxcsr_mask so we can avoid setting reserved bits -/ - movl $__FP_SSE, fp_kind - movl $fpxsave_begin, %eax - movl %eax, fpsave_begin - call patch_sse - mov %cr4, %eax - orl $_CONST(CR4_OSFXSR | CR4_OSXMMEXCPT), %eax - mov %eax, %cr4 -/ -/ make other CPUs share the same cr4 settings -/ - orl $_CONST(CR4_OSFXSR | CR4_OSXMMEXCPT), cr4_value -/ -/ extract the MXCSR_MASK field from our first fxsave -/ - subl $FXSAVE_STATE_SIZE + XMM_ALIGN, %esp - movl %esp, %eax - addl $XMM_ALIGN, %eax - andl $_BITNOT(XMM_ALIGN-1), %eax /* 16-byte alignment */ - movl $0, FXSAVE_STATE_MXCSR_MASK(%eax) - fxsave (%eax) - movl FXSAVE_STATE_MXCSR_MASK(%eax), %eax - addl $FXSAVE_STATE_SIZE + XMM_ALIGN, %esp - cmpl $0, %eax - je 1f / default mask value set in fpu.c - movl %eax, sse_mxcsr_mask / override mask set here -1: testl $X86_SSE2, x86_feature / can we do SSE2? - je mathchip -/ -/ aha .. we have an SSE2-capable chip -/ -/ - enable pagezero and pagecopy using non-temporal instructions -/ - hot patch membar_consumer() to use lfence instead of lock -/ - movl $1, use_sse_pagecopy / will now call hwblkpagecopy - movl $1, use_sse_pagezero / will now call hwblkclr - movl $1, use_sse_copy - call patch_sse2 - jmp mathchip -/ -/ No 387; we must have an 80287. -/ -is287: -#if !defined(__GNUC_AS__) - fsetpm / set the 80287 into protected mode - movl $FP_287, fp_kind / we have a 287 chip -#else - movl $FP_NO, fp_kind / maybe just explode here instead? -#endif -/ -/ We have either a 287, 387, 486 or P5. -/ Setup cr0 to reflect the FPU hw type. -/ -mathchip: - movl %cr0, %edx - andl $_BITNOT(CR0_TS|CR0_EM), %edx /* clear emulate math bit */ - orl $_CONST(CR0_MP|CR0_NE), %edx - jmp cont - -/ Do not use the FPU -ignore_fpu: - movl $1, fpu_ignored -/ No FP hw present. -no_fpu_hw: - movl %cr0, %edx - andl $_BITNOT(CR0_MP), %edx /* clear math chip present */ - movl $FP_NO, fp_kind / signify that there is no FPU - movl $0, fpu_exists / no FPU present -cont: - movl %edx, %cr0 / set machine status word + jae 0f + movl $1, %eax ret - SET_SIZE(fpu_probe) - -#define HOT_PATCH(srcaddr, dstaddr, size) \ - movl $srcaddr, %esi; \ - movl $dstaddr, %edi; \ - movl $size, %ebx; \ -0: pushl $1; \ - movzbl (%esi), %eax; \ - pushl %eax; \ - pushl %edi; \ - call hot_patch_kernel_text; \ - addl $12, %esp; \ - inc %edi; \ - inc %esi; \ - dec %ebx; \ - test %ebx, %ebx; \ - jne 0b - /* - * To cope with processors that do not implement fxsave/fxrstor - * instructions, patch hot paths in the kernel to use them only - * when that feature has been detected. - */ +0: xorl %eax, %eax + ret + + .align 4 +.num1: .4byte 0xbce4217d /* 4.999999 */ + .4byte 0x4013ffff +.num2: .4byte 0x0 /* 15.0 */ + .4byte 0x402e0000 +.num3: .4byte 0xde7210bf /* 14.999999 */ + .4byte 0x402dffff + SET_SIZE(fpu_probe_pentium_fdivbug) + +#endif /* __lint */ + +/* + * To cope with processors that do not implement fxsave/fxrstor + * instructions, patch hot paths in the kernel to use them only + * when that feature has been detected. + */ + +#if defined(__lint) + +void +patch_sse(void) +{} + +void +patch_sse2(void) +{} + +#else /* __lint */ + ENTRY_NP(patch_sse) - push %ebp - mov %esp, %ebp - push %ebx - push %esi - push %edi - / - / frstor (%eax); nop -> fxrstor (%eax) - / - HOT_PATCH(_fxrstor_eax_insn, _patch_fxrstor_eax, 3) + _HOT_PATCH_PROLOG / - / nop; nop; nop -> ldmxcsr (%ebx) + / frstor (%ebx); nop -> fxrstor (%ebx) / - HOT_PATCH(_ldmxcsr_ebx_insn, _patch_ldmxcsr_ebx, 3) + _HOT_PATCH(_fxrstor_ebx_insn, _patch_fxrstor_ebx, 3) / / lock; xorl $0, (%esp) -> sfence; ret / - HOT_PATCH(_sfence_ret_insn, _patch_sfence_ret, 4) - pop %edi - pop %esi - pop %ebx - mov %ebp, %esp - pop %ebp + _HOT_PATCH(_sfence_ret_insn, _patch_sfence_ret, 4) + _HOT_PATCH_EPILOG ret -_fxrstor_eax_insn: / see ndptrap_frstor() - fxrstor (%eax) +_fxrstor_ebx_insn: / see ndptrap_frstor() + fxrstor (%ebx) _ldmxcsr_ebx_insn: / see resume_from_zombie() ldmxcsr (%ebx) _sfence_ret_insn: / see membar_producer() @@ -427,103 +175,116 @@ _sfence_ret_insn: / see membar_producer() ret SET_SIZE(patch_sse) - /* - * Ditto, but this time for functions that depend upon SSE2 extensions - */ ENTRY_NP(patch_sse2) - push %ebp - mov %esp, %ebp - push %ebx - push %esi - push %edi + _HOT_PATCH_PROLOG / / lock; xorl $0, (%esp) -> lfence; ret / - HOT_PATCH(_lfence_ret_insn, _patch_lfence_ret, 4) - pop %edi - pop %esi - pop %ebx - mov %ebp, %esp - pop %ebp + _HOT_PATCH(_lfence_ret_insn, _patch_lfence_ret, 4) + _HOT_PATCH_EPILOG ret _lfence_ret_insn: / see membar_consumer() .byte 0xf, 0xae, 0xe8 / [lfence instruction] ret SET_SIZE(patch_sse2) -#endif /* __i386 */ #endif /* __lint */ +#endif /* __i386 */ /* * One of these routines is called from any lwp with floating - * point context as part of the prolog of a context switch; the - * routine starts the floating point state save operation. - * The completion of the save is forced by an fwait just before - * we truly switch contexts.. + * point context as part of the prolog of a context switch. */ #if defined(__lint) /*ARGSUSED*/ void -fpnsave_begin(void *arg) +fpxsave_ctxt(void *arg) {} /*ARGSUSED*/ void -fpxsave_begin(void *arg) +fpnsave_ctxt(void *arg) {} #else /* __lint */ #if defined(__amd64) - ENTRY_NP(fpxsave_begin) - movl FPU_CTX_FPU_FLAGS(%rdi), %edx - cmpl $FPU_EN, %edx + ENTRY_NP(fpxsave_ctxt) + cmpl $FPU_EN, FPU_CTX_FPU_FLAGS(%rdi) jne 1f -#if FPU_CTX_FPU_REGS != 0 - addq FPU_CTX_FPU_REGS, %rdi -#endif - fxsave (%rdi) - fnclex /* clear pending x87 exceptions */ + + movl $_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%rdi) + fxsave FPU_CTX_FPU_REGS(%rdi) + /* + * On certain AMD processors, the "exception pointers" i.e. the last + * instruction pointer, last data pointer, and last opcode + * are saved by the fxsave instruction ONLY if the exception summary + * bit is set. + * + * To ensure that we don't leak these values into the next context + * on the cpu, we could just issue an fninit here, but that's + * rather slow and so we issue an instruction sequence that + * clears them more quickly, if a little obscurely. + */ + btw $7, FXSAVE_STATE_FSW(%rdi) /* Test saved ES bit */ + jnc 0f /* jump if ES = 0 */ + fnclex /* clear pending x87 exceptions */ +0: ffree %st(7) /* clear tag bit to remove possible stack overflow */ + fildl .fpzero_const(%rip) + /* dummy load changes all exception pointers */ + STTS(%rsi) /* trap on next fpu touch */ 1: rep; ret /* use 2 byte return instruction when branch target */ /* AMD Software Optimization Guide - Section 6.2 */ - SET_SIZE(fpxsave_begin) + SET_SIZE(fpxsave_ctxt) #elif defined(__i386) - ENTRY_NP(fpnsave_begin) - mov 4(%esp), %eax / a struct fpu_ctx * - mov FPU_CTX_FPU_FLAGS(%eax), %edx - cmpl $FPU_EN, %edx + ENTRY_NP(fpnsave_ctxt) + movl 4(%esp), %eax /* a struct fpu_ctx */ + cmpl $FPU_EN, FPU_CTX_FPU_FLAGS(%eax) jne 1f -#if FPU_CTX_FPU_REGS != 0 - addl FPU_CTX_FPU_REGS, %eax -#endif - fnsave (%eax) + + movl $_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%eax) + fnsave FPU_CTX_FPU_REGS(%eax) + /* (fnsave also reinitializes x87 state) */ + STTS(%edx) /* trap on next fpu touch */ 1: rep; ret /* use 2 byte return instruction when branch target */ /* AMD Software Optimization Guide - Section 6.2 */ - SET_SIZE(fpnsave_begin) + SET_SIZE(fpnsave_ctxt) - ENTRY_NP(fpxsave_begin) - mov 4(%esp), %eax / a struct fpu_ctx * - mov FPU_CTX_FPU_FLAGS(%eax), %edx - cmpl $FPU_EN, %edx + ENTRY_NP(fpxsave_ctxt) + movl 4(%esp), %eax /* a struct fpu_ctx */ + cmpl $FPU_EN, FPU_CTX_FPU_FLAGS(%eax) jne 1f -#if FPU_CTX_FPU_REGS != 0 - addl FPU_CTX_FPU_REGS, %eax -#endif - fxsave (%eax) - fnclex / Clear pending x87 exceptions + + movl $_CONST(FPU_VALID|FPU_EN), FPU_CTX_FPU_FLAGS(%eax) + fxsave FPU_CTX_FPU_REGS(%eax) + /* (see notes above about "exception pointers") */ + btw $7, FXSAVE_STATE_FSW(%eax) /* Test saved ES bit */ + jnc 0f /* jump if ES = 0 */ + fnclex /* clear pending x87 exceptions */ +0: ffree %st(7) /* clear tag bit to remove possible stack overflow */ + fildl .fpzero_const + /* dummy load changes all exception pointers */ + STTS(%edx) /* trap on next fpu touch */ 1: rep; ret /* use 2 byte return instruction when branch target */ /* AMD Software Optimization Guide - Section 6.2 */ - SET_SIZE(fpxsave_begin) + SET_SIZE(fpxsave_ctxt) #endif /* __i386 */ + + .align 8 +.fpzero_const: + .4byte 0x0 + .4byte 0x0 + #endif /* __lint */ + #if defined(__lint) /*ARGSUSED*/ @@ -541,40 +302,29 @@ fpxsave(struct fxsave_state *f) #if defined(__amd64) ENTRY_NP(fpxsave) - clts /* clear TS bit in CR0 */ + CLTS fxsave (%rdi) - fnclex /* clear pending x87 exceptions */ - fwait /* wait for completion */ - fninit /* emulate fnsave: init x87 tags */ - movq %cr0, %rax - orq $CR0_TS, %rax - movq %rax, %cr0 /* set TS bit in CR0 (disable FPU) */ + fninit /* clear exceptions, init x87 tags */ + STTS(%rdi) /* set TS bit in %cr0 (disable FPU) */ ret SET_SIZE(fpxsave) #elif defined(__i386) ENTRY_NP(fpsave) - clts / clear TS bit in CR0 - movl 4(%esp), %eax / load save address + CLTS + movl 4(%esp), %eax fnsave (%eax) - fwait / wait for completion - movl %cr0, %eax - orl $CR0_TS, %eax - movl %eax, %cr0 / set TS bit in CR0 (disable FPU) + STTS(%eax) /* set TS bit in %cr0 (disable FPU) */ ret SET_SIZE(fpsave) ENTRY_NP(fpxsave) - clts / clear TS bit in CR0 - movl 4(%esp), %eax / save address + CLTS + movl 4(%esp), %eax fxsave (%eax) - fnclex / Clear pending x87 exceptions - fwait / wait for completion - fninit / emulate fnsave: init x87 tag words - mov %cr0, %eax - orl $CR0_TS, %eax - movl %eax, %cr0 / set TS bit in CR0 (disable FPU) + fninit /* clear exceptions, init x87 tags */ + STTS(%eax) /* set TS bit in %cr0 (disable FPU) */ ret SET_SIZE(fpxsave) @@ -598,7 +348,7 @@ fpxrestore(struct fxsave_state *f) #if defined(__amd64) ENTRY_NP(fpxrestore) - clts /* clear TS bit in CR0 */ + CLTS fxrstor (%rdi) ret SET_SIZE(fpxrestore) @@ -606,15 +356,15 @@ fpxrestore(struct fxsave_state *f) #elif defined(__i386) ENTRY_NP(fprestore) - clts / clear TS bit in CR0 - movl 4(%esp), %eax / load restore address + CLTS + movl 4(%esp), %eax frstor (%eax) ret SET_SIZE(fprestore) ENTRY_NP(fpxrestore) - clts / clear TS bit in CR0 - movl 4(%esp), %eax / load restore address + CLTS + movl 4(%esp), %eax fxrstor (%eax) ret SET_SIZE(fpxrestore) @@ -637,18 +387,14 @@ fpdisable(void) #if defined(__amd64) ENTRY_NP(fpdisable) - movq %cr0, %rax - orq $CR0_TS, %rax - movq %rax, %cr0 /* set TS bit in CR0 (disable FPU) */ + STTS(%rdi) /* set TS bit in %cr0 (disable FPU) */ ret SET_SIZE(fpdisable) #elif defined(__i386) ENTRY_NP(fpdisable) - movl %cr0, %eax - orl $CR0_TS, %eax - movl %eax, %cr0 / set TS bit in CR0 (disable FPU) + STTS(%eax) ret SET_SIZE(fpdisable) @@ -670,7 +416,7 @@ fpinit(void) #if defined(__amd64) ENTRY_NP(fpinit) - clts /* clear TS bit in CR0 */ + CLTS leaq sse_initial(%rip), %rax fxrstor (%rax) /* load clean initial state */ ret @@ -679,17 +425,17 @@ fpinit(void) #elif defined(__i386) ENTRY_NP(fpinit) - clts / clear TS bit in CR0 + CLTS cmpl $__FP_SSE, fp_kind je 1f - fninit / initialize the chip + fninit movl $x87_initial, %eax - frstor (%eax) / load clean initial state + frstor (%eax) /* load clean initial state */ ret 1: movl $sse_initial, %eax - fxrstor (%eax) / load clean initial state + fxrstor (%eax) /* load clean initial state */ ret SET_SIZE(fpinit) @@ -705,25 +451,21 @@ fpinit(void) uint32_t fperr_reset(void) -{ - return (0); -} +{ return (0); } uint32_t fpxerr_reset(void) -{ - return (0); -} +{ return (0); } #else /* __lint */ #if defined(__amd64) ENTRY_NP(fperr_reset) + CLTS xorl %eax, %eax - clts /* clear TS bit in CR0 */ - fnstsw %ax /* get status */ - fnclex /* clear processor exceptions */ + fnstsw %ax + fnclex ret SET_SIZE(fperr_reset) @@ -731,8 +473,8 @@ fpxerr_reset(void) pushq %rbp movq %rsp, %rbp subq $0x10, %rsp /* make some temporary space */ - clts /* clear TS bit in CR0 */ - stmxcsr (%rsp) /* get status */ + CLTS + stmxcsr (%rsp) movl (%rsp), %eax andl $_BITNOT(SSE_MXCSR_EFLAGS), (%rsp) ldmxcsr (%rsp) /* clear processor exceptions */ @@ -743,20 +485,20 @@ fpxerr_reset(void) #elif defined(__i386) ENTRY_NP(fperr_reset) + CLTS xorl %eax, %eax - clts / clear TS bit in CR0 - fnstsw %ax / get status - fnclex / clear processor exceptions + fnstsw %ax + fnclex ret SET_SIZE(fperr_reset) ENTRY_NP(fpxerr_reset) - clts / clear TS bit in CR0 - subl $4, %esp / make some temporary space - stmxcsr (%esp) / get status + CLTS + subl $4, %esp /* make some temporary space */ + stmxcsr (%esp) movl (%esp), %eax andl $_BITNOT(SSE_MXCSR_EFLAGS), (%esp) - ldmxcsr (%esp) / clear processor exceptions + ldmxcsr (%esp) /* clear processor exceptions */ addl $4, %esp ret SET_SIZE(fpxerr_reset) @@ -780,7 +522,7 @@ fpgetcwsw(void) pushq %rbp movq %rsp, %rbp subq $0x10, %rsp /* make some temporary space */ - clts /* clear TS bit in CR0 */ + CLTS fnstsw (%rsp) /* store the status word */ fnstcw 2(%rsp) /* store the control word */ movl (%rsp), %eax /* put both in %eax */ @@ -791,7 +533,7 @@ fpgetcwsw(void) #elif defined(__i386) ENTRY_NP(fpgetcwsw) - clts /* clear TS bit in CR0 */ + CLTS subl $4, %esp /* make some temporary space */ fnstsw (%esp) /* store the status word */ fnstcw 2(%esp) /* store the control word */ @@ -822,9 +564,9 @@ fpgetmxcsr(void) ENTRY_NP(fpgetmxcsr) pushq %rbp movq %rsp, %rbp - subq $0x10, %rsp /* make some temporary space */ - clts /* clear TS bit in CR0 */ - stmxcsr (%rsp) /* get status */ + subq $0x10, %rsp /* make some temporary space */ + CLTS + stmxcsr (%rsp) movl (%rsp), %eax leave ret @@ -833,9 +575,9 @@ fpgetmxcsr(void) #elif defined(__i386) ENTRY_NP(fpgetmxcsr) - clts /* clear TS bit in CR0 */ - subl $4, %esp /* make some temporary space */ - stmxcsr (%esp) /* get status */ + CLTS + subl $4, %esp /* make some temporary space */ + stmxcsr (%esp) movl (%esp), %eax addl $4, %esp ret diff --git a/usr/src/uts/intel/ia32/ml/i86_subr.s b/usr/src/uts/intel/ia32/ml/i86_subr.s index 7aa35afbef..18a06ebdf1 100644 --- a/usr/src/uts/intel/ia32/ml/i86_subr.s +++ b/usr/src/uts/intel/ia32/ml/i86_subr.s @@ -18,6 +18,7 @@ * * CDDL HEADER END */ + /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -515,19 +516,19 @@ setcr8(ulong_t val) ret SET_SIZE(setcr0) - ENTRY(getcr2) - movq %cr2, %rax - ret + ENTRY(getcr2) + movq %cr2, %rax + ret SET_SIZE(getcr2) ENTRY(getcr3) - movq %cr3, %rax + movq %cr3, %rax ret SET_SIZE(getcr3) - ENTRY(setcr3) - movq %rdi, %cr3 - ret + ENTRY(setcr3) + movq %rdi, %cr3 + ret SET_SIZE(setcr3) ENTRY(reload_cr3) @@ -662,6 +663,28 @@ __cpuid_insn(struct cpuid_regs *regs) #endif /* __i386 */ #endif /* __lint */ + +#if defined(__lint) + +hrtime_t +tsc_read(void) +{ + return (0); +} + +#else /* __lint */ + + ENTRY_NP(tsc_read) + rdtsc +#if defined(__amd64) + shlq $32, %rdx + orq %rdx, %rax +#endif + ret + SET_SIZE(tsc_read) + +#endif /* __lint */ + /* * Insert entryp after predp in a doubly linked list. */ @@ -776,7 +799,7 @@ strlen(const char *str) ENTRY(strlen) #ifdef DEBUG - movq kernelbase(%rip), %rax + movq postbootkernelbase(%rip), %rax cmpq %rax, %rdi jae str_valid pushq %rbp @@ -804,7 +827,7 @@ str_valid: ENTRY(strlen) #ifdef DEBUG - movl kernelbase, %eax + movl postbootkernelbase, %eax cmpl %eax, 4(%esp) jae str_valid pushl %ebp @@ -900,73 +923,36 @@ int splhigh(void) { return (0); } int splhi(void) { return (0); } int splzs(void) { return (0); } -#else /* __lint */ - -/* reg = cpu->cpu_m.cpu_pri; */ -#define GETIPL_NOGS(reg, cpup) \ - movl CPU_PRI(cpup), reg; - -/* cpu->cpu_m.cpu_pri; */ -#define SETIPL_NOGS(val, cpup) \ - movl val, CPU_PRI(cpup); - -/* reg = cpu->cpu_m.cpu_pri; */ -#define GETIPL(reg) \ - movl %gs:CPU_PRI, reg; +/* ARGSUSED */ +void +splx(int level) +{} -/* cpu->cpu_m.cpu_pri; */ -#define SETIPL(val) \ - movl val, %gs:CPU_PRI; +#else /* __lint */ -/* - * Macro to raise processor priority level. - * Avoid dropping processor priority if already at high level. - * Also avoid going below CPU->cpu_base_spl, which could've just been set by - * a higher-level interrupt thread that just blocked. - */ #if defined(__amd64) -#define RAISE(level) \ - cli; \ - LOADCPU(%rcx); \ - movl $/**/level, %edi;\ - GETIPL_NOGS(%eax, %rcx);\ - cmpl %eax, %edi; \ - jg spl; \ - jmp setsplhisti - -#elif defined(__i386) +#define SETPRI(level) \ + movl $/**/level, %edi; /* new priority */ \ + jmp do_splx /* redirect to do_splx */ #define RAISE(level) \ - cli; \ - LOADCPU(%ecx); \ - movl $/**/level, %edx;\ - GETIPL_NOGS(%eax, %ecx);\ - cmpl %eax, %edx; \ - jg spl; \ - jmp setsplhisti - -#endif /* __i386 */ + movl $/**/level, %edi; /* new priority */ \ + jmp splr /* redirect to splr */ -/* - * Macro to set the priority to a specified level. - * Avoid dropping the priority below CPU->cpu_base_spl. - */ -#if defined(__amd64) +#elif defined(__i386) #define SETPRI(level) \ - cli; \ - LOADCPU(%rcx); \ - movl $/**/level, %edi; \ - jmp spl - -#elif defined(__i386) + pushl $/**/level; /* new priority */ \ + call do_splx; /* invoke common splx code */ \ + addl $4, %esp; /* unstack arg */ \ + ret -#define SETPRI(level) \ - cli; \ - LOADCPU(%ecx); \ - movl $/**/level, %edx; \ - jmp spl +#define RAISE(level) \ + pushl $/**/level; /* new priority */ \ + call splr; /* invoke common splr code */ \ + addl $4, %esp; /* unstack args */ \ + ret #endif /* __i386 */ @@ -985,413 +971,29 @@ int splzs(void) { return (0); } SETPRI(12) /* Can't be a RAISE, as it's used to lower us */ SET_SIZE(splzs) - /* - * should lock out clocks and all interrupts, - * as you can see, there are exceptions - */ - -#if defined(__amd64) - - .align 16 ENTRY(splhi) ALTENTRY(splhigh) ALTENTRY(spl6) ALTENTRY(i_ddi_splhigh) - cli - LOADCPU(%rcx) - movl $DISP_LEVEL, %edi - movl CPU_PRI(%rcx), %eax - cmpl %eax, %edi - jle setsplhisti - SETIPL_NOGS(%edi, %rcx) - /* - * If we aren't using cr8 to control ipl then we patch this - * with a jump to slow_setsplhi - */ - ALTENTRY(setsplhi_patch) - movq CPU_PRI_DATA(%rcx), %r11 /* get pri data ptr */ - movzb (%r11, %rdi, 1), %rdx /* get apic mask for this ipl */ - movq %rdx, %cr8 /* set new apic priority */ - /* - * enable interrupts - */ -setsplhisti: - nop /* patch this to a sti when a proper setspl routine appears */ - ret - ALTENTRY(slow_setsplhi) - pushq %rbp - movq %rsp, %rbp - subq $16, %rsp - movl %eax, -4(%rbp) /* save old ipl */ - call *setspl(%rip) - movl -4(%rbp), %eax /* return old ipl */ - leave - jmp setsplhisti + RAISE(DISP_LEVEL) SET_SIZE(i_ddi_splhigh) SET_SIZE(spl6) SET_SIZE(splhigh) SET_SIZE(splhi) -#elif defined(__i386) - - .align 16 - ENTRY(splhi) - ALTENTRY(splhigh) - ALTENTRY(spl6) - ALTENTRY(i_ddi_splhigh) - cli - LOADCPU(%ecx) - movl $DISP_LEVEL, %edx - movl CPU_PRI(%ecx), %eax - cmpl %eax, %edx - jle setsplhisti - SETIPL_NOGS(%edx, %ecx) /* set new ipl */ - - pushl %eax /* save old ipl */ - pushl %edx /* pass new ipl */ - call *setspl - popl %ecx /* dummy pop */ - popl %eax /* return old ipl */ - /* - * enable interrupts - * - * (we patch this to an sti once a proper setspl routine - * is installed) - */ -setsplhisti: - nop /* patch this to a sti when a proper setspl routine appears */ - ret - SET_SIZE(i_ddi_splhigh) - SET_SIZE(spl6) - SET_SIZE(splhigh) - SET_SIZE(splhi) - -#endif /* __i386 */ - /* allow all interrupts */ ENTRY(spl0) SETPRI(0) SET_SIZE(spl0) -#endif /* __lint */ - -/* - * splr is like splx but will only raise the priority and never drop it - */ -#if defined(__lint) - -/* ARGSUSED */ -int -splr(int level) -{ return (0); } - -#else /* __lint */ - -#if defined(__amd64) - - ENTRY(splr) - cli - LOADCPU(%rcx) - GETIPL_NOGS(%eax, %rcx) - cmpl %eax, %edi /* if new level > current level */ - jg spl /* then set ipl to new level */ -splr_setsti: - nop /* patch this to a sti when a proper setspl routine appears */ - ret /* else return the current level */ - SET_SIZE(splr) - -#elif defined(__i386) - - ENTRY(splr) - cli - LOADCPU(%ecx) - movl 4(%esp), %edx /* get new spl level */ - GETIPL_NOGS(%eax, %ecx) - cmpl %eax, %edx /* if new level > current level */ - jg spl /* then set ipl to new level */ -splr_setsti: - nop /* patch this to a sti when a proper setspl routine appears */ - ret /* else return the current level */ - SET_SIZE(splr) - -#endif /* __i386 */ -#endif /* __lint */ - - - -/* - * splx - set PIL back to that indicated by the level passed as an argument, - * or to the CPU's base priority, whichever is higher. - * Needs to be fall through to spl to save cycles. - * Algorithm for spl: - * - * turn off interrupts - * - * if (CPU->cpu_base_spl > newipl) - * newipl = CPU->cpu_base_spl; - * oldipl = CPU->cpu_pridata->c_ipl; - * CPU->cpu_pridata->c_ipl = newipl; - * - * /indirectly call function to set spl values (usually setpicmasks) - * setspl(); // load new masks into pics - * - * Be careful not to set priority lower than CPU->cpu_base_pri, - * even though it seems we're raising the priority, it could be set - * higher at any time by an interrupt routine, so we must block interrupts - * and look at CPU->cpu_base_pri - */ -#if defined(__lint) - -/* ARGSUSED */ -void -splx(int level) -{} - -#else /* __lint */ - -#if defined(__amd64) + /* splx implentation */ ENTRY(splx) - ALTENTRY(i_ddi_splx) - cli /* disable interrupts */ - LOADCPU(%rcx) - /*FALLTHRU*/ - .align 4 -spl: - /* - * New priority level is in %edi, cpu struct pointer is in %rcx - */ - GETIPL_NOGS(%eax, %rcx) /* get current ipl */ - cmpl %edi, CPU_BASE_SPL(%rcx) /* if (base spl > new ipl) */ - ja set_to_base_spl /* then use base_spl */ - -setprilev: - SETIPL_NOGS(%edi, %rcx) /* set new ipl */ - /* - * If we aren't using cr8 to control ipl then we patch this - * with a jump to slow_spl - */ - ALTENTRY(spl_patch) - movq CPU_PRI_DATA(%rcx), %r11 /* get pri data ptr */ - movzb (%r11, %rdi, 1), %rdx /* get apic mask for this ipl */ - movq %rdx, %cr8 /* set new apic priority */ - xorl %edx, %edx - bsrl CPU_SOFTINFO(%rcx), %edx /* fls(cpu->cpu_softinfo.st_pending) */ - cmpl %edi, %edx /* new ipl vs. st_pending */ - jle setsplsti - - pushq %rbp - movq %rsp, %rbp - /* stack now 16-byte aligned */ - pushq %rax /* save old spl */ - pushq %rdi /* save new ipl too */ - jmp fakesoftint - -setsplsti: - nop /* patch this to a sti when a proper setspl routine appears */ - ret - - ALTENTRY(slow_spl) - pushq %rbp - movq %rsp, %rbp - /* stack now 16-byte aligned */ - - pushq %rax /* save old spl */ - pushq %rdi /* save new ipl too */ - - call *setspl(%rip) - - LOADCPU(%rcx) - movl CPU_SOFTINFO(%rcx), %eax - orl %eax, %eax - jz slow_setsplsti - - bsrl %eax, %edx /* fls(cpu->cpu_softinfo.st_pending) */ - cmpl 0(%rsp), %edx /* new ipl vs. st_pending */ - jg fakesoftint - - ALTENTRY(fakesoftint_return) - /* - * enable interrupts - */ -slow_setsplsti: - nop /* patch this to a sti when a proper setspl routine appears */ - popq %rdi - popq %rax /* return old ipl */ - leave - ret - SET_SIZE(fakesoftint_return) - -set_to_base_spl: - movl CPU_BASE_SPL(%rcx), %edi - jmp setprilev - SET_SIZE(spl) - SET_SIZE(i_ddi_splx) + jmp do_splx /* redirect to common splx code */ SET_SIZE(splx) -#elif defined(__i386) - - ENTRY(splx) - ALTENTRY(i_ddi_splx) - cli /* disable interrupts */ - LOADCPU(%ecx) - movl 4(%esp), %edx /* get new spl level */ - /*FALLTHRU*/ - - .align 4 - ALTENTRY(spl) - /* - * New priority level is in %edx - * (doing this early to avoid an AGI in the next instruction) - */ - GETIPL_NOGS(%eax, %ecx) /* get current ipl */ - cmpl %edx, CPU_BASE_SPL(%ecx) /* if ( base spl > new ipl) */ - ja set_to_base_spl /* then use base_spl */ - -setprilev: - SETIPL_NOGS(%edx, %ecx) /* set new ipl */ - - pushl %eax /* save old ipl */ - pushl %edx /* pass new ipl */ - call *setspl - - LOADCPU(%ecx) - movl CPU_SOFTINFO(%ecx), %eax - orl %eax, %eax - jz setsplsti - - /* - * Before dashing off, check that setsplsti has been patched. - */ - cmpl $NOP_INSTR, setsplsti - je setsplsti - - bsrl %eax, %edx - cmpl 0(%esp), %edx - jg fakesoftint - - ALTENTRY(fakesoftint_return) - /* - * enable interrupts - */ -setsplsti: - nop /* patch this to a sti when a proper setspl routine appears */ - popl %eax - popl %eax / return old ipl - ret - SET_SIZE(fakesoftint_return) - -set_to_base_spl: - movl CPU_BASE_SPL(%ecx), %edx - jmp setprilev - SET_SIZE(spl) - SET_SIZE(i_ddi_splx) - SET_SIZE(splx) - -#endif /* __i386 */ -#endif /* __lint */ - -#if defined(__lint) - -void -install_spl(void) -{} - -#else /* __lint */ - -#if defined(__amd64) - - ENTRY_NP(install_spl) - movq %cr0, %rax - movq %rax, %rdx - movl $_BITNOT(CR0_WP), %ecx - movslq %ecx, %rcx - andq %rcx, %rax /* we don't want to take a fault */ - movq %rax, %cr0 - jmp 1f -1: movb $STI_INSTR, setsplsti(%rip) - movb $STI_INSTR, slow_setsplsti(%rip) - movb $STI_INSTR, setsplhisti(%rip) - movb $STI_INSTR, splr_setsti(%rip) - testl $1, intpri_use_cr8(%rip) /* are using %cr8 ? */ - jz 2f /* no, go patch more */ - movq %rdx, %cr0 - ret -2: - /* - * Patch spl functions to use slow spl method - */ - leaq setsplhi_patch(%rip), %rdi /* get patch point addr */ - leaq slow_setsplhi(%rip), %rax /* jmp target */ - subq %rdi, %rax /* calculate jmp distance */ - subq $2, %rax /* minus size of jmp instr */ - shlq $8, %rax /* construct jmp instr */ - addq $JMP_INSTR, %rax - movw %ax, setsplhi_patch(%rip) /* patch in the jmp */ - leaq spl_patch(%rip), %rdi /* get patch point addr */ - leaq slow_spl(%rip), %rax /* jmp target */ - subq %rdi, %rax /* calculate jmp distance */ - subq $2, %rax /* minus size of jmp instr */ - shlq $8, %rax /* construct jmp instr */ - addq $JMP_INSTR, %rax - movw %ax, spl_patch(%rip) /* patch in the jmp */ - /* - * Ensure %cr8 is zero since we aren't using it - */ - xorl %eax, %eax - movq %rax, %cr8 - movq %rdx, %cr0 - ret - SET_SIZE(install_spl) - -#elif defined(__i386) - - ENTRY_NP(install_spl) - movl %cr0, %eax - movl %eax, %edx - andl $_BITNOT(CR0_WP), %eax /* we don't want to take a fault */ - movl %eax, %cr0 - jmp 1f -1: movb $STI_INSTR, setsplsti - movb $STI_INSTR, setsplhisti - movb $STI_INSTR, splr_setsti - movl %edx, %cr0 - ret - SET_SIZE(install_spl) - -#endif /* __i386 */ -#endif /* __lint */ - - -/* - * Get current processor interrupt level - */ - -#if defined(__lint) - -int -getpil(void) -{ return (0); } - -#else /* __lint */ - -#if defined(__amd64) - - ENTRY(getpil) - GETIPL(%eax) /* priority level into %eax */ - ret - SET_SIZE(getpil) - -#elif defined(__i386) - - ENTRY(getpil) - GETIPL(%eax) /* priority level into %eax */ - ret - SET_SIZE(getpil) - -#endif /* __i386 */ #endif /* __lint */ #if defined(__i386) @@ -2117,13 +1719,13 @@ scanc(size_t size, uchar_t *cp, uchar_t *table, uchar_t mask) #if defined(__lint) -int +ulong_t intr_clear(void) -{ return 0; } +{ return (0); } -int +ulong_t clear_int_flag(void) -{ return 0; } +{ return (0); } #else /* __lint */ @@ -2132,8 +1734,8 @@ clear_int_flag(void) ENTRY(intr_clear) ENTRY(clear_int_flag) pushfq - cli popq %rax + CLI(%rdi) ret SET_SIZE(clear_int_flag) SET_SIZE(intr_clear) @@ -2143,8 +1745,8 @@ clear_int_flag(void) ENTRY(intr_clear) ENTRY(clear_int_flag) pushfl - cli popl %eax + CLI(%edx) ret SET_SIZE(clear_int_flag) SET_SIZE(intr_clear) @@ -2261,12 +1863,12 @@ ntohs(uint16_t i) /* ARGSUSED */ void -intr_restore(uint_t i) +intr_restore(ulong_t i) { return; } /* ARGSUSED */ void -restore_int_flag(int i) +restore_int_flag(ulong_t i) { return; } #else /* __lint */ @@ -2285,7 +1887,8 @@ restore_int_flag(int i) ENTRY(intr_restore) ENTRY(restore_int_flag) - pushl 4(%esp) + movl 4(%esp), %eax + pushl %eax popfl ret SET_SIZE(restore_int_flag) @@ -2300,13 +1903,26 @@ void sti(void) {} +void +cli(void) +{} + #else /* __lint */ ENTRY(sti) - sti + STI ret SET_SIZE(sti) + ENTRY(cli) +#if defined(__amd64) + CLI(%rax) +#elif defined(__i386) + CLI(%eax) +#endif /* __i386 */ + ret + SET_SIZE(cli) + #endif /* __lint */ #if defined(__lint) @@ -2322,7 +1938,7 @@ dtrace_interrupt_disable(void) ENTRY(dtrace_interrupt_disable) pushfq popq %rax - cli + CLI(%rdx) ret SET_SIZE(dtrace_interrupt_disable) @@ -2331,7 +1947,7 @@ dtrace_interrupt_disable(void) ENTRY(dtrace_interrupt_disable) pushfl popl %eax - cli + CLI(%edx) ret SET_SIZE(dtrace_interrupt_disable) @@ -2458,7 +2074,7 @@ ip_ocsum( pushq %rbp movq %rsp, %rbp #ifdef DEBUG - movq kernelbase(%rip), %rax + movq postbootkernelbase(%rip), %rax cmpq %rax, %rdi jnb 1f xorl %eax, %eax @@ -2878,6 +2494,7 @@ invalidate_cache(void) #define XMSR_ACCESS_VAL $0x9c5a203a #if defined(__amd64) + ENTRY(rdmsr) movl %edi, %ecx rdmsr @@ -2896,21 +2513,27 @@ invalidate_cache(void) SET_SIZE(wrmsr) ENTRY(xrdmsr) + pushq %rbp + movq %rsp, %rbp movl %edi, %ecx movl XMSR_ACCESS_VAL, %edi /* this value is needed to access MSR */ rdmsr shlq $32, %rdx orq %rdx, %rax + leave ret SET_SIZE(xrdmsr) ENTRY(xwrmsr) + pushq %rbp + movq %rsp, %rbp movl %edi, %ecx movl XMSR_ACCESS_VAL, %edi /* this value is needed to access MSR */ movq %rsi, %rdx shrq $32, %rdx movl %esi, %eax wrmsr + leave ret SET_SIZE(xwrmsr) @@ -2931,18 +2554,28 @@ invalidate_cache(void) SET_SIZE(wrmsr) ENTRY(xrdmsr) - movl 4(%esp), %ecx + pushl %ebp + movl %esp, %ebp + movl 8(%esp), %ecx + pushl %edi movl XMSR_ACCESS_VAL, %edi /* this value is needed to access MSR */ rdmsr + popl %edi + leave ret SET_SIZE(xrdmsr) ENTRY(xwrmsr) - movl 4(%esp), %ecx - movl 8(%esp), %eax - movl 12(%esp), %edx + pushl %ebp + movl %esp, %ebp + movl 8(%esp), %ecx + movl 12(%esp), %eax + movl 16(%esp), %edx + pushl %edi movl XMSR_ACCESS_VAL, %edi /* this value is needed to access MSR */ wrmsr + popl %edi + leave ret SET_SIZE(xwrmsr) @@ -2958,20 +2591,22 @@ invalidate_cache(void) #if defined(__lint) /*ARGSUSED*/ -void getcregs(struct cregs *crp) +void +getcregs(struct cregs *crp) {} #else /* __lint */ #if defined(__amd64) + ENTRY_NP(getcregs) + #define GETMSR(r, off, d) \ movl $r, %ecx; \ rdmsr; \ movl %eax, off(d); \ movl %edx, off+4(d) - ENTRY_NP(getcregs) xorl %eax, %eax movq %rax, CREG_GDT+8(%rdi) sgdt CREG_GDT(%rdi) /* 10 bytes */ @@ -2988,11 +2623,12 @@ void getcregs(struct cregs *crp) movq %cr3, %rax movq %rax, CREG_CR3(%rdi) /* cr3 */ movq %cr4, %rax - movq %rax, CREG_CR8(%rdi) /* cr4 */ + movq %rax, CREG_CR4(%rdi) /* cr4 */ movq %cr8, %rax movq %rax, CREG_CR8(%rdi) /* cr8 */ GETMSR(MSR_AMD_KGSBASE, CREG_KGSBASE, %rdi) GETMSR(MSR_AMD_EFER, CREG_EFER, %rdi) + ret SET_SIZE(getcregs) #undef GETMSR @@ -3021,8 +2657,7 @@ void getcregs(struct cregs *crp) .nocr4: movl $0, CREG_CR4(%edx) .skip: - rep; ret /* use 2 byte return instruction when branch target */ - /* AMD Software Optimization Guide - Section 6.2 */ + ret SET_SIZE(getcregs) #endif /* __i386 */ @@ -3214,16 +2849,6 @@ vpanic_common: movq %r14, REGOFF_R14(%rsp) movq %r15, REGOFF_R15(%rsp) - movl $MSR_AMD_FSBASE, %ecx - rdmsr - movl %eax, REGOFF_FSBASE(%rsp) - movl %edx, REGOFF_FSBASE+4(%rsp) - - movl $MSR_AMD_GSBASE, %ecx - rdmsr - movl %eax, REGOFF_GSBASE(%rsp) - movl %edx, REGOFF_GSBASE+4(%rsp) - xorl %ecx, %ecx movw %ds, %cx movq %rcx, REGOFF_DS(%rsp) @@ -3442,7 +3067,6 @@ hrtime_t hres_last_tick; timestruc_t hrestime; int64_t hrestime_adj; volatile int hres_lock; -uint_t nsec_scale; hrtime_t hrtime_base; #else /* __lint */ @@ -3788,7 +3412,7 @@ bcmp(const void *s1, const void *s2, size_t count) pushq %rbp movq %rsp, %rbp #ifdef DEBUG - movq kernelbase(%rip), %r11 + movq postbootkernelbase(%rip), %r11 cmpq %r11, %rdi jb 0f cmpq %r11, %rsi @@ -3816,7 +3440,7 @@ bcmp(const void *s1, const void *s2, size_t count) pushl %ebp movl %esp, %ebp / create new stack frame #ifdef DEBUG - movl kernelbase, %eax + movl postbootkernelbase, %eax cmpl %eax, ARG_S1(%ebp) jb 0f cmpl %eax, ARG_S2(%ebp) @@ -3881,3 +3505,206 @@ bcmp(const void *s1, const void *s2, size_t count) #endif /* DEBUG */ #endif /* __lint */ + +#if defined(__lint) + +uint_t +bsrw_insn(uint16_t mask) +{ + uint_t index = sizeof (mask) * NBBY - 1; + + while ((mask & (1 << index)) == 0) + index--; + return (index); +} + +#else /* __lint */ + +#if defined(__amd64) + + ENTRY_NP(bsrw_insn) + xorl %eax, %eax + bsrw %di, %ax + ret + SET_SIZE(bsrw_insn) + +#elif defined(__i386) + + ENTRY_NP(bsrw_insn) + movw 4(%esp), %cx + xorl %eax, %eax + bsrw %cx, %ax + ret + SET_SIZE(bsrw_insn) + +#endif /* __i386 */ +#endif /* __lint */ + +#if defined(__lint) + +uint_t +atomic_btr32(uint32_t *pending, uint_t pil) +{ + return (*pending &= ~(1 << pil)); +} + +#else /* __lint */ + +#if defined(__i386) + + ENTRY_NP(atomic_btr32) + movl 4(%esp), %ecx + movl 8(%esp), %edx + xorl %eax, %eax + lock + btrl %edx, (%ecx) + setc %al + ret + SET_SIZE(atomic_btr32) + +#endif /* __i386 */ +#endif /* __lint */ + +#if defined(__lint) + +/*ARGSUSED*/ +void +switch_sp_and_call(void *newsp, void (*func)(uint_t, uint_t), uint_t arg1, + uint_t arg2) +{} + +#else /* __lint */ + +#if defined(__amd64) + + ENTRY_NP(switch_sp_and_call) + pushq %rbp + movq %rsp, %rbp /* set up stack frame */ + movq %rdi, %rsp /* switch stack pointer */ + movq %rdx, %rdi /* pass func arg 1 */ + movq %rsi, %r11 /* save function to call */ + movq %rcx, %rsi /* pass func arg 2 */ + call *%r11 /* call function */ + leave /* restore stack */ + ret + SET_SIZE(switch_sp_and_call) + +#elif defined(__i386) + + ENTRY_NP(switch_sp_and_call) + pushl %ebp + mov %esp, %ebp /* set up stack frame */ + movl 8(%ebp), %esp /* switch stack pointer */ + pushl 20(%ebp) /* push func arg 2 */ + pushl 16(%ebp) /* push func arg 1 */ + call *12(%ebp) /* call function */ + addl $8, %esp /* pop arguments */ + leave /* restore stack */ + ret + SET_SIZE(switch_sp_and_call) + +#endif /* __i386 */ +#endif /* __lint */ + +#if defined(__lint) + +void +kmdb_enter(void) +{} + +#else /* __lint */ + +#if defined(__amd64) + + ENTRY_NP(kmdb_enter) + pushq %rbp + movq %rsp, %rbp + + /* + * Save flags, do a 'cli' then return the saved flags + */ + call intr_clear + + int $T_DBGENTR + + /* + * Restore the saved flags + */ + movq %rax, %rdi + call intr_restore + + leave + ret + SET_SIZE(kmdb_enter) + +#elif defined(__i386) + + ENTRY_NP(kmdb_enter) + pushl %ebp + movl %esp, %ebp + + /* + * Save flags, do a 'cli' then return the saved flags + */ + call intr_clear + + int $T_DBGENTR + + /* + * Restore the saved flags + */ + pushl %eax + call intr_restore + addl $4, %esp + + leave + ret + SET_SIZE(kmdb_enter) + +#endif /* __i386 */ +#endif /* __lint */ + +#if defined(__lint) + +void +return_instr(void) +{} + +#else /* __lint */ + + ENTRY_NP(return_instr) + rep; ret /* use 2 byte instruction when branch target */ + /* AMD Software Optimization Guide - Section 6.2 */ + SET_SIZE(return_instr) + +#endif /* __lint */ + +#if defined(__lint) + +ulong_t +getflags(void) +{ + return (0); +} + +#else /* __lint */ + +#if defined(__amd64) + + ENTRY(getflags) + pushfq + popq %rax + ret + SET_SIZE(getflags) + +#elif defined(__i386) + + ENTRY(getflags) + pushfl + popl %eax + ret + SET_SIZE(getflags) + +#endif /* __i386 */ + +#endif /* __lint */ diff --git a/usr/src/uts/intel/ia32/ml/ia32.il b/usr/src/uts/intel/ia32/ml/ia32.il index 7cf9902f52..f3fd44170d 100644 --- a/usr/src/uts/intel/ia32/ml/ia32.il +++ b/usr/src/uts/intel/ia32/ml/ia32.il @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,15 +18,17 @@ * * CDDL HEADER END */ + /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" / -/ In-line functions for i86 kernels. +/ Inline functions for i386 kernels. +/ Shared between all x86 platform variants. / / @@ -60,37 +61,6 @@ .end / -/ return value of cr3 register -/ - .inline getcr3,0 - movl %cr3, %eax - .end - -/ -/ reload cr3 register with its current value -/ - .inline reload_cr3,0 - movl %cr3, %eax - movl %eax, %cr3 - .end - -/* - * Put a new value into cr3 (page table base register - * void setcr3(void *value) - */ - .inline setcr3,4 - movl (%esp), %eax - movl %eax, %cr3 - .end - -/ -/ invalidate and flush cache. -/ - .inline cache_bug,0 - wbinvd - .end - -/ / convert ipl to spl. This is the identity function for i86 / .inline ipltospl,0 @@ -98,20 +68,6 @@ .end / -/ enable interrupts -/ - .inline sti,0 - sti - .end - -/ -/ disable interrupts -/ - .inline cli,0 - cli - .end - -/ / find the low order bit in a word / .inline lowbit,4 @@ -119,6 +75,7 @@ bsfl (%esp), %eax incl %eax .end + / / find the high order bit in a word / @@ -129,76 +86,8 @@ .end / -/ disable interrupts and return value describing if interrupts were enabled -/ - .inline clear_int_flag,0 - pushfl - cli - popl %eax - .end - - .inline intr_clear,0 - pushfl - cli - popl %eax - .end - -/ -/ restore interrupt enable flag to value returned from 'clear_int_flag' above -/ - .inline restore_int_flag,4 - pushl (%esp) - popfl - .end - - .inline intr_restore,4 - pushl (%esp) - popfl - .end - -/ -/ in and out -/ - .inline inb,4 - movl (%esp), %edx - xorl %eax, %eax - inb (%dx) - .end - - .inline inw,4 - movl (%esp), %edx - xorl %eax, %eax - inw (%dx) - .end - - .inline inl,4 - movl (%esp), %edx - xorl %eax, %eax - inl (%dx) - .end - - .inline outb,8 - movl (%esp), %edx - movl 4(%esp), %eax - outb (%dx) - .end - - .inline outw,8 - movl (%esp), %edx - movl 4(%esp), %eax - outw (%dx) - .end - - .inline outl,8 - movl (%esp), %edx - movl 4(%esp), %eax - outl (%dx) - .end - -/ / Networking byte order functions (too bad, Intel has the wrong byte order) / - .inline htonl,4 movl (%esp), %eax bswap %eax @@ -222,7 +111,7 @@ .end /* - * multiply two long numbers and yield a u_lonlong_t result + * multiply two long numbers and yield a u_longlong_t result * Provided to manipulate hrtime_t values. */ .inline mul32, 8 @@ -253,7 +142,6 @@ andb %dl,(%eax) .end - /* * atomic inc/dec operations. * void atomic_inc16(uint16_t *addr) { ++*addr; } @@ -272,44 +160,6 @@ .end /* - * Invalidate TLB translation to 1 page. - * void mmu_tlbflush_entry(void *addr) - */ - .inline mmu_tlbflush_entry,4 - movl (%esp), %eax - invlpg (%eax) - .end - -/* - * Read Time Stamp Counter - * uint64_t tsc_read(); - * - * usage: - * uint64_t cycles = tsc_read(); - * - * PPro & PII take no less than 34 cycles to execute rdtsc + stores. - * Pentium takes about 16 cycles. - */ - .inline tsc_read, 0 - rdtsc / %edx:%eax = RDTSC - .end - -/* - * void tsc_clear(register) - * Clear the local Time Stamp Counter via write-MSR instruction. - * Note that while this is a 64-bit write, the top 32-bits are - * ignored, so it isn't massively useful to write anything other - * than zero. - */ - .inline tsc_reset, 4 - movl (%esp), %ecx - xorl %eax, %eax - movl %eax, %edx - wrmsr - ret - .end - -/* * Call the pause instruction. To the Pentium 4 Xeon processor, it acts as * a hint that the code sequence is a busy spin-wait loop. Without a pause * instruction in these loops, the P4 Xeon processor may suffer a severe @@ -322,16 +172,3 @@ rep / our compiler doesn't support "pause" yet, nop / so we're using "F3 90" opcode directly .end - -/* - * Call the halt instruction. This will put the CPU to sleep until - * it is again awoken via an interrupt. - * This function should be called with interrupts already disabled - * for the CPU. - * Note that "sti" will only enable interrupts at the end of the - * subsequent instruction...in this case: "hlt". - */ - .inline i86_halt,0 - sti - hlt - .end diff --git a/usr/src/uts/intel/ia32/ml/lock_prim.s b/usr/src/uts/intel/ia32/ml/lock_prim.s index a6bd761aeb..2d74137565 100644 --- a/usr/src/uts/intel/ia32/ml/lock_prim.s +++ b/usr/src/uts/intel/ia32/ml/lock_prim.s @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -466,31 +466,24 @@ lock_clear_splx(lock_t *lp, int s) jmp lockstat_wrapper SET_SIZE(lock_clear_splx) -#if defined(__GNUC_AS__) -#define LOCK_CLEAR_SPLX_LOCKSTAT_PATCH_VAL \ - (.lock_clear_splx_lockstat - .lock_clear_splx_lockstat_patch_point - 2) - -#define LOCK_CLEAR_SPLX_LOCKSTAT_PATCH_POINT \ - (.lock_clear_splx_lockstat_patch_point + 1) -#else -#define LOCK_CLEAR_SPLX_LOCKSTAT_PATCH_VAL \ - [.lock_clear_splx_lockstat - .lock_clear_splx_lockstat_patch_point - 2] - -#define LOCK_CLEAR_SPLX_LOCKSTAT_PATCH_POINT \ - [.lock_clear_splx_lockstat_patch_point + 1] -#endif - #else ENTRY(lock_clear_splx) - LOADCPU(%ecx) /* ecx = cpu pointer */ movl 4(%esp), %eax /* eax = lock addr */ - movl 8(%esp), %edx /* edx = desired pil */ movb $0, (%eax) /* clear lock */ - cli /* disable interrupts */ - call spl /* magic calling sequence */ .lock_clear_splx_lockstat_patch_point: - ret + jmp 0f +0: + movl 8(%esp), %edx /* edx = desired pil */ + movl %edx, 4(%esp) /* set spl arg up for splx */ + jmp splx /* let splx do it's thing */ +.lock_clear_splx_lockstat: + movl 8(%esp), %edx /* edx = desired pil */ + pushl %ebp /* set up stack frame */ + movl %esp, %ebp + pushl %edx + call splx + leave /* unwind stack */ movl 4(%esp), %ecx /* ecx = lock pointer */ movl %gs:CPU_THREAD, %edx /* edx = thread addr */ movl $LS_LOCK_CLEAR_SPLX_RELEASE, %eax @@ -499,6 +492,20 @@ lock_clear_splx(lock_t *lp, int s) #endif /* !__amd64 */ +#if defined(__GNUC_AS__) +#define LOCK_CLEAR_SPLX_LOCKSTAT_PATCH_VAL \ + (.lock_clear_splx_lockstat - .lock_clear_splx_lockstat_patch_point - 2) + +#define LOCK_CLEAR_SPLX_LOCKSTAT_PATCH_POINT \ + (.lock_clear_splx_lockstat_patch_point + 1) +#else +#define LOCK_CLEAR_SPLX_LOCKSTAT_PATCH_VAL \ + [.lock_clear_splx_lockstat - .lock_clear_splx_lockstat_patch_point - 2] + +#define LOCK_CLEAR_SPLX_LOCKSTAT_PATCH_POINT \ + [.lock_clear_splx_lockstat_patch_point + 1] +#endif + #endif /* __lint */ /* @@ -1255,15 +1262,9 @@ lockstat_hot_patch(void) HOT_PATCH(.lock_set_spl_lockstat_patch_point, LS_LOCK_SET_SPL_ACQUIRE, NOP_INSTR, RET_INSTR, 1) -#if defined(__amd64) HOT_PATCH(LOCK_CLEAR_SPLX_LOCKSTAT_PATCH_POINT, LS_LOCK_CLEAR_SPLX_RELEASE, LOCK_CLEAR_SPLX_LOCKSTAT_PATCH_VAL, 0, 1); -#else - HOT_PATCH(.lock_clear_splx_lockstat_patch_point, - LS_LOCK_CLEAR_SPLX_RELEASE, NOP_INSTR, RET_INSTR, 1) -#endif /* !__amd64 */ - #if defined(__amd64) leave /* unwind stack */ #endif /* __amd64 */ diff --git a/usr/src/uts/intel/ia32/ml/sseblk.s b/usr/src/uts/intel/ia32/ml/sseblk.s index 6daa8caa8f..092b3e52fd 100644 --- a/usr/src/uts/intel/ia32/ml/sseblk.s +++ b/usr/src/uts/intel/ia32/ml/sseblk.s @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -377,46 +376,133 @@ hwblkpagecopy(const void *src, void *dst) #endif /* __i386 */ #endif /* __lint */ - #if defined(__lint) +/* + * Version of hwblkclr which doesn't use XMM registers. + * Note that it requires aligned dst and len. + * + * XXPV This needs to be performance tuned at some point. + * Is 4 the best number of iterations to unroll? + */ /*ARGSUSED*/ void -hat_pte_zero(void *dst, size_t len) +block_zero_no_xmm(void *dst, int len) {} -#else +#else /* __lint */ #if defined(__amd64) - ENTRY(hat_pte_zero) + ENTRY(block_zero_no_xmm) + pushq %rbp + movq %rsp, %rbp xorl %eax, %eax + addq %rsi, %rdi + negq %rsi 1: - movnti %rax, (%rdi) - addq $8, %rdi - subq $8, %rsi + movnti %rax, (%rdi, %rsi) + movnti %rax, 8(%rdi, %rsi) + movnti %rax, 16(%rdi, %rsi) + movnti %rax, 24(%rdi, %rsi) + addq $32, %rsi jnz 1b mfence + leave ret - SET_SIZE(hat_pte_zero) + SET_SIZE(block_zero_no_xmm) #elif defined(__i386) - ENTRY(hat_pte_zero) + ENTRY(block_zero_no_xmm) + pushl %ebp + movl %esp, %ebp xorl %eax, %eax - movl 4(%esp), %edx - movl 8(%esp), %ecx + movl 8(%ebp), %edx + movl 12(%ebp), %ecx + addl %ecx, %edx + negl %ecx 1: - movnti %eax, (%edx) - addl $4, %edx - subl $4, %ecx + movnti %eax, (%edx, %ecx) + movnti %eax, 4(%edx, %ecx) + movnti %eax, 8(%edx, %ecx) + movnti %eax, 12(%edx, %ecx) + addl $16, %ecx jnz 1b mfence + leave ret - SET_SIZE(hat_pte_zero) + SET_SIZE(block_zero_no_xmm) #endif /* __i386 */ +#endif /* __lint */ + + +#if defined(__lint) + +/* + * Version of page copy which doesn't use XMM registers. + * + * XXPV This needs to be performance tuned at some point. + * Is 4 the right number of iterations to unroll? + * Is the load/store order optimal? Should it use prefetch? + */ +/*ARGSUSED*/ +void +page_copy_no_xmm(void *dst, void *src) +{} + +#else /* __lint */ +#if defined(__amd64) + + ENTRY(page_copy_no_xmm) + movq $MMU_STD_PAGESIZE, %rcx + addq %rcx, %rdi + addq %rcx, %rsi + negq %rcx +1: + movq (%rsi, %rcx), %rax + movnti %rax, (%rdi, %rcx) + movq 8(%rsi, %rcx), %rax + movnti %rax, 8(%rdi, %rcx) + movq 16(%rsi, %rcx), %rax + movnti %rax, 16(%rdi, %rcx) + movq 24(%rsi, %rcx), %rax + movnti %rax, 24(%rdi, %rcx) + addq $32, %rcx + jnz 1b + mfence + ret + SET_SIZE(page_copy_no_xmm) + +#elif defined(__i386) + + ENTRY(page_copy_no_xmm) + pushl %esi + movl $MMU_STD_PAGESIZE, %ecx + movl 8(%esp), %edx + movl 12(%esp), %esi + addl %ecx, %edx + addl %ecx, %esi + negl %ecx +1: + movl (%esi, %ecx), %eax + movnti %eax, (%edx, %ecx) + movl 4(%esi, %ecx), %eax + movnti %eax, 4(%edx, %ecx) + movl 8(%esi, %ecx), %eax + movnti %eax, 8(%edx, %ecx) + movl 12(%esi, %ecx), %eax + movnti %eax, 12(%edx, %ecx) + addl $16, %ecx + jnz 1b + mfence + popl %esi + ret + SET_SIZE(page_copy_no_xmm) + +#endif /* __i386 */ #endif /* __lint */ #if defined(DEBUG) && !defined(__lint) diff --git a/usr/src/uts/intel/ia32/ml/swtch.s b/usr/src/uts/intel/ia32/ml/swtch.s index 48103f954f..118c70ce89 100644 --- a/usr/src/uts/intel/ia32/ml/swtch.s +++ b/usr/src/uts/intel/ia32/ml/swtch.s @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -214,8 +213,8 @@ resume(kthread_t *t) movq %r13, %rdi /* arg = thread pointer */ call savectx /* call ctx ops */ - .nosavectx: + /* * Call savepctx if process has installed context ops. */ @@ -245,14 +244,6 @@ resume(kthread_t *t) GET_THREAD_HATP(%rdi, %r12, %r11) call hat_switch - movq T_LWP(%r13), %r14 - testq %r14, %r14 - jz .disabled_fpu2 - - cmpl $FPU_EN, PCB_FPU_FLAGS(%r14) - je .wait_for_fpusave - -.disabled_fpu2: /* * Clear and unlock previous thread's t_lock * to allow it to be dispatched by another processor. @@ -384,16 +375,6 @@ resume_return: */ addq $CLONGSIZE, %rsp ret - -.wait_for_fpusave: - /* mark copy in pcb as valid */ - movq %cr0, %rax - movl $_CONST(FPU_VALID|FPU_EN), PCB_FPU_FLAGS(%r14) - orl $CR0_TS, %eax /* set to trap on next switch */ - fwait /* ensure save is done before we unlock */ - finit /* (ensure x87 tags cleared for fxsave case) */ - movq %rax, %cr0 - jmp .disabled_fpu2 SET_SIZE(_resume_from_idle) SET_SIZE(resume) @@ -414,6 +395,9 @@ resume_return: LOADCPU(%ebx) /* %ebx = CPU */ movl CPU_THREAD(%ebx), %esi /* %esi = curthread */ +#ifdef DEBUG + call assert_ints_enabled /* panics if we are cli'd */ +#endif /* * Call savectx if thread has installed context ops. * @@ -428,8 +412,8 @@ resume_return: pushl %esi /* arg = thread pointer */ call savectx /* call ctx ops */ addl $4, %esp /* restore stack pointer */ - .nosavectx: + /* * Call savepctx if process has installed context ops. */ @@ -439,7 +423,7 @@ resume_return: pushl %eax /* arg = proc pointer */ call savepctx /* call ctx ops */ addl $4, %esp -.nosavepctx: +.nosavepctx: /* * Temporarily switch to the idle thread's stack @@ -451,8 +435,6 @@ resume_return: */ movl T_SP(%eax), %esp /* It is safe to set esp */ movl %eax, CPU_THREAD(%ebx) - movl T_LWP(%esi), %ecx /* load pointer to pcb_fpu */ - movl %ecx, %ebx /* save pcb_fpu pointer in %ebx */ /* switch in the hat context for the new thread */ GET_THREAD_HATP(%ecx, %edi, %ecx) @@ -460,17 +442,11 @@ resume_return: call hat_switch addl $4, %esp - xorl %ecx, %ecx - testl %ebx, %ebx /* check pcb_fpu pointer */ - jz .disabled_fpu2 - cmpl $FPU_EN, PCB_FPU_FLAGS(%ebx) /* is PCB_FPU_FLAGS FPU_EN? */ - je .wait_for_fpusave -.disabled_fpu2: /* * Clear and unlock previous thread's t_lock * to allow it to be dispatched by another processor. */ - movb %cl, T_LOCK(%esi) + movb $0, T_LOCK(%esi) /* * IMPORTANT: Registers at this point must be: @@ -586,18 +562,6 @@ resume_return: addl $CLONGSIZE, %esp ret -.wait_for_fpusave: - mov %cr0, %eax - - /* mark copy in pcb as valid */ - movl $_CONST(FPU_VALID|FPU_EN), PCB_FPU_FLAGS(%ebx) - - orl $CR0_TS, %eax /* set to trap on next switch */ - fwait /* ensure save is done before we unlock */ - finit /* (ensure x87 tags cleared for fxsave case) */ - movl %eax, %cr0 - jmp .disabled_fpu2 - .L4_2: pause cmpb $0, T_LOCK(%edi) @@ -647,15 +611,6 @@ resume_from_zombie(kthread_t *t) testq $CR0_TS, %rax jnz .zfpu_disabled /* if TS already set, nothing to do */ fninit /* init fpu & discard pending error */ - - /* - * Store a zero word into the mxcsr register to disable any sse - * floating point exceptions - */ - pushq $0 - movq %rsp, %rdi - ldmxcsr (%rdi) - addq $CLONGSIZE, %rsp orq $CR0_TS, %rax movq %rax, %cr0 .zfpu_disabled: @@ -715,28 +670,21 @@ resume_from_zombie_return: */ SAVE_REGS(%eax, %ecx) +#ifdef DEBUG + call assert_ints_enabled /* panics if we are cli'd */ +#endif movl %gs:CPU_THREAD, %esi /* %esi = curthread */ /* clean up the fp unit. It might be left enabled */ + movl %cr0, %eax testl $CR0_TS, %eax jnz .zfpu_disabled /* if TS already set, nothing to do */ fninit /* init fpu & discard pending error */ - - /* - * If this machine supports fxsave/fxrstor, the next string of - * nops may be patched to store a zero word off the stack into - * the mxcsr register to disable any sse floating point exceptions - */ - pushl $0 - mov %esp, %ebx - .globl _patch_ldmxcsr_ebx -_patch_ldmxcsr_ebx: - nop; nop; nop /* ldmxcsr (%ebx) */ - addl $4, %esp orl $CR0_TS, %eax movl %eax, %cr0 .zfpu_disabled: + /* * Temporarily switch to the idle thread's stack so that the zombie * thread's stack can be reclaimed by the reaper. @@ -749,11 +697,14 @@ _patch_ldmxcsr_ebx: */ movl %eax, %gs:CPU_THREAD - /* switch in the hat context for the new thread */ + /* + * switch in the hat context for the new thread + */ GET_THREAD_HATP(%ecx, %edi, %ecx) pushl %ecx call hat_switch addl $4, %esp + /* * Put the zombie on death-row. */ @@ -872,6 +823,9 @@ resume_from_intr_return: */ SAVE_REGS(%eax, %ecx) +#ifdef DEBUG + call assert_ints_enabled /* panics if we are cli'd */ +#endif movl %gs:CPU_THREAD, %esi /* %esi = curthread */ movl %edi, %gs:CPU_THREAD /* set CPU's thread pointer */ movl T_SP(%edi), %esp /* restore resuming thread's sp */ diff --git a/usr/src/uts/intel/ia32/os/archdep.c b/usr/src/uts/intel/ia32/os/archdep.c index c3f0688965..317cd9b77d 100644 --- a/usr/src/uts/intel/ia32/os/archdep.c +++ b/usr/src/uts/intel/ia32/os/archdep.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -295,17 +295,6 @@ setfpregs(klwp_t *lwp, fpregset_t *fp) #endif fpu->fpu_regs.kfpu_status = fp->fp_reg_set.fpchip_state.status; fpu->fpu_flags |= FPU_VALID; - - /* - * If we are changing the fpu_flags in the current context, - * disable floating point (turn on CR0_TS bit) to track - * FPU_VALID after clearing any errors (frstor chokes - * otherwise) - */ - if (lwp == ttolwp(curthread)) { - (void) fperr_reset(); - fpdisable(); - } } else { /* * If we are trying to change the FPU state of a thread which @@ -934,6 +923,11 @@ bind_hwcap(void) * 32-bit lwp ... */ auxv_hwcap &= ~AV_386_SEP; +#else + /* + * 32-bit processes can -always- use the lahf/sahf instructions + */ + auxv_hwcap |= AV_386_AHF; #endif if (auxv_hwcap_include || auxv_hwcap_exclude) @@ -953,6 +947,11 @@ bind_hwcap(void) */ if (!cpuid_syscall32_insn(NULL)) auxv_hwcap32 &= ~AV_386_AMD_SYSC; + + /* + * 32-bit processes can -always- use the lahf/sahf instructions + */ + auxv_hwcap32 |= AV_386_AHF; #endif if (auxv_hwcap32_include || auxv_hwcap32_exclude) @@ -1016,8 +1015,8 @@ panic_saveregs(panic_data_t *pdp, struct regs *rp) PANICNVADD(pnv, "r13", rp->r_r13); PANICNVADD(pnv, "r14", rp->r_r14); PANICNVADD(pnv, "r15", rp->r_r15); - PANICNVADD(pnv, "fsbase", rp->r_fsbase); - PANICNVADD(pnv, "gsbase", rp->r_gsbase); + PANICNVADD(pnv, "fsbase", rdmsr(MSR_AMD_FSBASE)); + PANICNVADD(pnv, "gsbase", rdmsr(MSR_AMD_GSBASE)); PANICNVADD(pnv, "ds", rp->r_ds); PANICNVADD(pnv, "es", rp->r_es); PANICNVADD(pnv, "fs", rp->r_fs); diff --git a/usr/src/uts/intel/ia32/os/cpc_subr.c b/usr/src/uts/intel/ia32/os/cpc_subr.c index 4ab36ece98..34753229f5 100644 --- a/usr/src/uts/intel/ia32/os/cpc_subr.c +++ b/usr/src/uts/intel/ia32/os/cpc_subr.c @@ -44,7 +44,7 @@ #include <sys/cmn_err.h> #include <sys/cmt.h> #include <sys/spl.h> -#include <io/pcplusmp/apic.h> +#include <sys/apic.h> static const uint64_t allstopped = 0; static kcpc_ctx_t *(*overflow_intr_handler)(caddr_t); @@ -111,7 +111,7 @@ static int setup_registered; void kcpc_hw_init(cpu_t *cp) { - kthread_t *t = cp->cpu_idle_thread; + kthread_t *t = cp->cpu_idle_thread; if (x86_feature & X86_HTT) { mutex_enter(&cpu_setup_lock); @@ -133,6 +133,14 @@ kcpc_hw_init(cpu_t *cp) NULL, NULL, NULL, NULL); } +void +kcpc_hw_fini(cpu_t *cp) +{ + ASSERT(cp->cpu_idle_thread == NULL); + + mutex_destroy(&cp->cpu_cpc_ctxlock); +} + #define BITS(v, u, l) \ (((v) >> (l)) & ((1 << (1 + (u) - (l))) - 1)) diff --git a/usr/src/uts/intel/ia32/os/desctbls.c b/usr/src/uts/intel/ia32/os/desctbls.c index ed31db4a2d..166953e30b 100644 --- a/usr/src/uts/intel/ia32/os/desctbls.c +++ b/usr/src/uts/intel/ia32/os/desctbls.c @@ -1,5 +1,26 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -45,30 +66,37 @@ */ #include <sys/types.h> +#include <sys/sysmacros.h> #include <sys/tss.h> #include <sys/segments.h> #include <sys/trap.h> #include <sys/cpuvar.h> +#include <sys/bootconf.h> #include <sys/x86_archext.h> +#include <sys/controlregs.h> #include <sys/archsystm.h> #include <sys/machsystm.h> #include <sys/kobj.h> #include <sys/cmn_err.h> #include <sys/reboot.h> #include <sys/kdi.h> +#include <sys/mach_mmu.h> #include <sys/systm.h> -#include <sys/controlregs.h> - -extern void syscall_int(void); +#include <sys/promif.h> +#include <sys/bootinfo.h> +#include <vm/kboot_mmu.h> /* * cpu0 and default tables and structures. */ +user_desc_t *gdt0; desctbr_t gdt0_default_r; #pragma align 16(idt0) gate_desc_t idt0[NIDT]; /* interrupt descriptor table */ +#if defined(__i386) desctbr_t idt0_default_r; /* describes idt0 in IDTR format */ +#endif #pragma align 16(ktss0) struct tss ktss0; /* kernel task state structure */ @@ -248,11 +276,8 @@ set_syssegd(system_desc_t *dp, void *base, size_t size, uint_t type, #if defined(__amd64) -/* - * Note stkcpy is replaced with ist. Read the PRM for details on this. - */ void -set_gatesegd(gate_desc_t *dp, void (*func)(void), selector_t sel, uint_t ist, +set_gatesegd(gate_desc_t *dp, void (*func)(void), selector_t sel, uint_t type, uint_t dpl) { dp->sgd_looffset = (uintptr_t)func; @@ -260,7 +285,17 @@ set_gatesegd(gate_desc_t *dp, void (*func)(void), selector_t sel, uint_t ist, dp->sgd_hi64offset = (uintptr_t)func >> (16 + 16); dp->sgd_selector = (uint16_t)sel; - dp->sgd_ist = ist; + + /* + * For 64 bit native we use the IST stack mechanism + * for double faults. All other traps use the CPL = 0 + * (tss_rsp0) stack. + */ + if (type == T_DBLFLT) + dp->sgd_ist = 1; + else + dp->sgd_ist = 0; + dp->sgd_type = type; dp->sgd_dpl = dpl; dp->sgd_p = 1; @@ -270,52 +305,35 @@ set_gatesegd(gate_desc_t *dp, void (*func)(void), selector_t sel, uint_t ist, void set_gatesegd(gate_desc_t *dp, void (*func)(void), selector_t sel, - uint_t wcount, uint_t type, uint_t dpl) + uint_t type, uint_t dpl) { dp->sgd_looffset = (uintptr_t)func; dp->sgd_hioffset = (uintptr_t)func >> 16; dp->sgd_selector = (uint16_t)sel; - dp->sgd_stkcpy = wcount; + dp->sgd_stkcpy = 0; /* always zero bytes */ dp->sgd_type = type; dp->sgd_dpl = dpl; dp->sgd_p = 1; } -#endif /* __i386 */ +#endif /* __i386 */ + +#if defined(__amd64) /* * Build kernel GDT. */ -#if defined(__amd64) - static void -init_gdt(void) +init_gdt_common(user_desc_t *gdt) { - desctbr_t r_bgdt, r_gdt; - user_desc_t *bgdt; - size_t alen = 0xfffff; /* entire 32-bit address space */ - int i; - - /* - * Copy in from boot's gdt to our gdt entries 1 - 4. - * Entry 0 is the null descriptor by definition. - */ - rd_gdtr(&r_bgdt); - bgdt = (user_desc_t *)r_bgdt.dtr_base; - if (bgdt == NULL) - panic("null boot gdt"); - - gdt0[GDT_B32DATA] = bgdt[GDT_B32DATA]; - gdt0[GDT_B32CODE] = bgdt[GDT_B32CODE]; - gdt0[GDT_B64DATA] = bgdt[GDT_B64DATA]; - gdt0[GDT_B64CODE] = bgdt[GDT_B64CODE]; + int i; /* * 64-bit kernel code segment. */ - set_usegd(&gdt0[GDT_KCODE], SDP_LONG, NULL, 0, SDT_MEMERA, SEL_KPL, + set_usegd(&gdt[GDT_KCODE], SDP_LONG, NULL, 0, SDT_MEMERA, SEL_KPL, SDP_PAGES, SDP_OP32); /* @@ -328,20 +346,20 @@ init_gdt(void) * apps. For the same reason we must set the default op size of this * descriptor to 32-bit operands. */ - set_usegd(&gdt0[GDT_KDATA], SDP_LONG, NULL, alen, SDT_MEMRWA, + set_usegd(&gdt[GDT_KDATA], SDP_LONG, NULL, -1, SDT_MEMRWA, SEL_KPL, SDP_PAGES, SDP_OP32); - gdt0[GDT_KDATA].usd_def32 = 1; + gdt[GDT_KDATA].usd_def32 = 1; /* * 64-bit user code segment. */ - set_usegd(&gdt0[GDT_UCODE], SDP_LONG, NULL, 0, SDT_MEMERA, SEL_UPL, + set_usegd(&gdt[GDT_UCODE], SDP_LONG, NULL, 0, SDT_MEMERA, SEL_UPL, SDP_PAGES, SDP_OP32); /* * 32-bit user code segment. */ - set_usegd(&gdt0[GDT_U32CODE], SDP_SHORT, NULL, alen, SDT_MEMERA, + set_usegd(&gdt[GDT_U32CODE], SDP_SHORT, NULL, -1, SDT_MEMERA, SEL_UPL, SDP_PAGES, SDP_OP32); /* @@ -351,7 +369,7 @@ init_gdt(void) * as in legacy mode so they must be set correctly for a 32-bit data * segment. */ - set_usegd(&gdt0[GDT_UDATA], SDP_SHORT, NULL, alen, SDT_MEMRWA, SEL_UPL, + set_usegd(&gdt[GDT_UDATA], SDP_SHORT, NULL, -1, SDT_MEMRWA, SEL_UPL, SDP_PAGES, SDP_OP32); /* @@ -362,7 +380,7 @@ init_gdt(void) /* * Kernel TSS */ - set_syssegd((system_desc_t *)&gdt0[GDT_KTSS], &ktss0, + set_syssegd((system_desc_t *)&gdt[GDT_KTSS], &ktss0, sizeof (ktss0) - 1, SDT_SYSTSS, SEL_KPL); /* @@ -370,9 +388,9 @@ init_gdt(void) * Only attributes and limits are initialized, the effective * base address is programmed via fsbase/gsbase. */ - set_usegd(&gdt0[GDT_LWPFS], SDP_SHORT, NULL, alen, SDT_MEMRWA, + set_usegd(&gdt[GDT_LWPFS], SDP_SHORT, NULL, -1, SDT_MEMRWA, SEL_UPL, SDP_PAGES, SDP_OP32); - set_usegd(&gdt0[GDT_LWPGS], SDP_SHORT, NULL, alen, SDT_MEMRWA, + set_usegd(&gdt[GDT_LWPGS], SDP_SHORT, NULL, -1, SDT_MEMRWA, SEL_UPL, SDP_PAGES, SDP_OP32); /* @@ -380,17 +398,10 @@ init_gdt(void) * Only attributes and limits are initialized. */ for (i = GDT_BRANDMIN; i <= GDT_BRANDMAX; i++) - set_usegd(&gdt0[i], SDP_SHORT, NULL, alen, SDT_MEMRWA, + set_usegd(&gdt0[i], SDP_SHORT, NULL, -1, SDT_MEMRWA, SEL_UPL, SDP_PAGES, SDP_OP32); /* - * Install our new GDT - */ - r_gdt.dtr_limit = sizeof (gdt0) - 1; - r_gdt.dtr_base = (uintptr_t)gdt0; - wr_gdtr(&r_gdt); - - /* * Initialize convenient zero base user descriptors for clearing * lwp private %fs and %gs descriptors in GDT. See setregs() for * an example. @@ -401,28 +412,79 @@ init_gdt(void) SDP_PAGES, SDP_OP32); } -#elif defined(__i386) - -static void +static user_desc_t * init_gdt(void) { desctbr_t r_bgdt, r_gdt; user_desc_t *bgdt; - int i; +#if !defined(__lint) /* - * Copy in from boot's gdt to our gdt entries 1 - 4. - * Entry 0 is null descriptor by definition. + * Our gdt is never larger than a single page. + */ + ASSERT((sizeof (*gdt0) * NGDT) <= PAGESIZE); +#endif + gdt0 = (user_desc_t *)BOP_ALLOC(bootops, (caddr_t)GDT_VA, + PAGESIZE, PAGESIZE); + if (gdt0 == NULL) + panic("init_gdt: BOP_ALLOC failed"); + bzero(gdt0, PAGESIZE); + + init_gdt_common(gdt0); + + /* + * Copy in from boot's gdt to our gdt. + * Entry 0 is the null descriptor by definition. */ rd_gdtr(&r_bgdt); bgdt = (user_desc_t *)r_bgdt.dtr_base; if (bgdt == NULL) panic("null boot gdt"); - gdt0[GDT_BOOTFLAT] = bgdt[GDT_BOOTFLAT]; - gdt0[GDT_BOOTCODE] = bgdt[GDT_BOOTCODE]; - gdt0[GDT_BOOTCODE16] = bgdt[GDT_BOOTCODE16]; - gdt0[GDT_BOOTDATA] = bgdt[GDT_BOOTDATA]; + gdt0[GDT_B32DATA] = bgdt[GDT_B32DATA]; + gdt0[GDT_B32CODE] = bgdt[GDT_B32CODE]; + gdt0[GDT_B16CODE] = bgdt[GDT_B16CODE]; + gdt0[GDT_B16DATA] = bgdt[GDT_B16DATA]; + gdt0[GDT_B64CODE] = bgdt[GDT_B64CODE]; + + /* + * Install our new GDT + */ + r_gdt.dtr_limit = (sizeof (*gdt0) * NGDT) - 1; + r_gdt.dtr_base = (uintptr_t)gdt0; + wr_gdtr(&r_gdt); + + /* + * Reload the segment registers to use the new GDT + */ + load_segment_registers(KCS_SEL, KFS_SEL, KGS_SEL, KDS_SEL); + + /* + * setup %gs for kernel + */ + wrmsr(MSR_AMD_GSBASE, (uint64_t)&cpus[0]); + + /* + * XX64 We should never dereference off "other gsbase" or + * "fsbase". So, we should arrange to point FSBASE and + * KGSBASE somewhere truly awful e.g. point it at the last + * valid address below the hole so that any attempts to index + * off them cause an exception. + * + * For now, point it at 8G -- at least it should be unmapped + * until some 64-bit processes run. + */ + wrmsr(MSR_AMD_FSBASE, 0x200000000ul); + wrmsr(MSR_AMD_KGSBASE, 0x200000000ul); + return (gdt0); +} + +#elif defined(__i386) + +static void +init_gdt_common(user_desc_t *gdt) +{ + int i; /* * Text and data for both kernel and user span entire 32 bit @@ -432,43 +494,43 @@ init_gdt(void) /* * kernel code segment. */ - set_usegd(&gdt0[GDT_KCODE], NULL, -1, SDT_MEMERA, SEL_KPL, SDP_PAGES, + set_usegd(&gdt[GDT_KCODE], NULL, -1, SDT_MEMERA, SEL_KPL, SDP_PAGES, SDP_OP32); /* * kernel data segment. */ - set_usegd(&gdt0[GDT_KDATA], NULL, -1, SDT_MEMRWA, SEL_KPL, SDP_PAGES, + set_usegd(&gdt[GDT_KDATA], NULL, -1, SDT_MEMRWA, SEL_KPL, SDP_PAGES, SDP_OP32); /* * user code segment. */ - set_usegd(&gdt0[GDT_UCODE], NULL, -1, SDT_MEMERA, SEL_UPL, SDP_PAGES, + set_usegd(&gdt[GDT_UCODE], NULL, -1, SDT_MEMERA, SEL_UPL, SDP_PAGES, SDP_OP32); /* * user data segment. */ - set_usegd(&gdt0[GDT_UDATA], NULL, -1, SDT_MEMRWA, SEL_UPL, SDP_PAGES, + set_usegd(&gdt[GDT_UDATA], NULL, -1, SDT_MEMRWA, SEL_UPL, SDP_PAGES, SDP_OP32); /* * TSS for T_DBLFLT (double fault) handler */ - set_syssegd((system_desc_t *)&gdt0[GDT_DBFLT], &dftss0, + set_syssegd((system_desc_t *)&gdt[GDT_DBFLT], &dftss0, sizeof (dftss0) - 1, SDT_SYSTSS, SEL_KPL); /* * TSS for kernel */ - set_syssegd((system_desc_t *)&gdt0[GDT_KTSS], &ktss0, + set_syssegd((system_desc_t *)&gdt[GDT_KTSS], &ktss0, sizeof (ktss0) - 1, SDT_SYSTSS, SEL_KPL); /* * %gs selector for kernel */ - set_usegd(&gdt0[GDT_GS], &cpus[0], sizeof (struct cpu) -1, SDT_MEMRWA, + set_usegd(&gdt[GDT_GS], &cpus[0], sizeof (struct cpu) -1, SDT_MEMRWA, SEL_KPL, SDP_BYTES, SDP_OP32); /* @@ -476,9 +538,9 @@ init_gdt(void) * Only attributes and limits are initialized, the effective * base address is programmed via fsbase/gsbase. */ - set_usegd(&gdt0[GDT_LWPFS], NULL, (size_t)-1, SDT_MEMRWA, SEL_UPL, + set_usegd(&gdt[GDT_LWPFS], NULL, (size_t)-1, SDT_MEMRWA, SEL_UPL, SDP_PAGES, SDP_OP32); - set_usegd(&gdt0[GDT_LWPGS], NULL, (size_t)-1, SDT_MEMRWA, SEL_UPL, + set_usegd(&gdt[GDT_LWPGS], NULL, (size_t)-1, SDT_MEMRWA, SEL_UPL, SDP_PAGES, SDP_OP32); /* @@ -488,168 +550,153 @@ init_gdt(void) for (i = GDT_BRANDMIN; i <= GDT_BRANDMAX; i++) set_usegd(&gdt0[i], NULL, (size_t)-1, SDT_MEMRWA, SEL_UPL, SDP_PAGES, SDP_OP32); + /* + * Initialize convenient zero base user descriptor for clearing + * lwp private %fs and %gs descriptors in GDT. See setregs() for + * an example. + */ + set_usegd(&zero_udesc, NULL, -1, SDT_MEMRWA, SEL_UPL, + SDP_BYTES, SDP_OP32); +} + +static user_desc_t * +init_gdt(void) +{ + desctbr_t r_bgdt, r_gdt; + user_desc_t *bgdt; + +#if !defined(__lint) + /* + * Our gdt is never larger than a single page. + */ + ASSERT((sizeof (*gdt0) * NGDT) <= PAGESIZE); +#endif + /* + * XXX this allocation belongs in our caller, not here. + */ + gdt0 = (user_desc_t *)BOP_ALLOC(bootops, (caddr_t)GDT_VA, + PAGESIZE, PAGESIZE); + if (gdt0 == NULL) + panic("init_gdt: BOP_ALLOC failed"); + bzero(gdt0, PAGESIZE); + + init_gdt_common(gdt0); + + /* + * Copy in from boot's gdt to our gdt entries. + * Entry 0 is null descriptor by definition. + */ + rd_gdtr(&r_bgdt); + bgdt = (user_desc_t *)r_bgdt.dtr_base; + if (bgdt == NULL) + panic("null boot gdt"); + + gdt0[GDT_B32DATA] = bgdt[GDT_B32DATA]; + gdt0[GDT_B32CODE] = bgdt[GDT_B32CODE]; + gdt0[GDT_B16CODE] = bgdt[GDT_B16CODE]; + gdt0[GDT_B16DATA] = bgdt[GDT_B16DATA]; /* * Install our new GDT */ - r_gdt.dtr_limit = sizeof (gdt0) - 1; + r_gdt.dtr_limit = (sizeof (*gdt0) * NGDT) - 1; r_gdt.dtr_base = (uintptr_t)gdt0; wr_gdtr(&r_gdt); /* - * Initialize convenient zero base user descriptors for clearing - * lwp private %fs and %gs descriptors in GDT. See setregs() for - * an example. + * Reload the segment registers to use the new GDT */ - set_usegd(&zero_udesc, 0, -1, SDT_MEMRWA, SEL_UPL, SDP_PAGES, SDP_OP32); + load_segment_registers( + KCS_SEL, KDS_SEL, KDS_SEL, KFS_SEL, KGS_SEL, KDS_SEL); + + return (gdt0); } #endif /* __i386 */ -#if defined(__amd64) - /* * Build kernel IDT. * - * Note that we pretty much require every gate to be an interrupt gate; - * that's because of our dependency on using 'swapgs' every time we come - * into the kernel to find the cpu structure - if we get interrupted just - * before doing that, so that %cs is in kernel mode (so that the trap prolog - * doesn't do a swapgs), but %gsbase is really still pointing at something - * in userland, bad things ensue. + * Note that for amd64 we pretty much require every gate to be an interrupt + * gate which blocks interrupts atomically on entry; that's because of our + * dependency on using 'swapgs' every time we come into the kernel to find + * the cpu structure. If we get interrupted just before doing that, %cs could + * be in kernel mode (so that the trap prolog doesn't do a swapgs), but + * %gsbase is really still pointing at something in userland. Bad things will + * ensue. We also use interrupt gates for i386 as well even though this is not + * required for some traps. * * Perhaps they should have invented a trap gate that does an atomic swapgs? - * - * XX64 We do need to think further about the follow-on impact of this. - * Most of the kernel handlers re-enable interrupts as soon as they've - * saved register state and done the swapgs, but there may be something - * more subtle going on. */ static void -init_idt(void) +init_idt_common(gate_desc_t *idt) { - char ivctname[80]; - void (*ivctptr)(void); - int i; - - /* - * Initialize entire table with 'reserved' trap and then overwrite - * specific entries. T_EXTOVRFLT (9) is unsupported and reserved - * since it can only be generated on a 386 processor. 15 is also - * unsupported and reserved. - */ - for (i = 0; i < NIDT; i++) - set_gatesegd(&idt0[i], &resvtrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - - set_gatesegd(&idt0[T_ZERODIV], &div0trap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_SGLSTP], &dbgtrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_NMIFLT], &nmiint, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_BPTFLT], &brktrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_UPL); - set_gatesegd(&idt0[T_OVFLW], &ovflotrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_UPL); - set_gatesegd(&idt0[T_BOUNDFLT], &boundstrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_ILLINST], &invoptrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_NOEXTFLT], &ndptrap, KCS_SEL, 0, SDT_SYSIGT, + set_gatesegd(&idt[T_ZERODIV], &div0trap, KCS_SEL, SDT_SYSIGT, SEL_KPL); + set_gatesegd(&idt[T_SGLSTP], &dbgtrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); + set_gatesegd(&idt[T_NMIFLT], &nmiint, KCS_SEL, SDT_SYSIGT, SEL_KPL); + set_gatesegd(&idt[T_BPTFLT], &brktrap, KCS_SEL, SDT_SYSIGT, SEL_UPL); + set_gatesegd(&idt[T_OVFLW], &ovflotrap, KCS_SEL, SDT_SYSIGT, SEL_UPL); + set_gatesegd(&idt[T_BOUNDFLT], &boundstrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); + set_gatesegd(&idt[T_ILLINST], &invoptrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); + set_gatesegd(&idt[T_NOEXTFLT], &ndptrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); /* * double fault handler. */ - set_gatesegd(&idt0[T_DBLFLT], &syserrtrap, KCS_SEL, 1, SDT_SYSIGT, - SEL_KPL); - +#if defined(__amd64) + set_gatesegd(&idt[T_DBLFLT], &syserrtrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); +#elif defined(__i386) /* - * T_EXTOVRFLT coprocessor-segment-overrun not supported. + * task gate required. */ + set_gatesegd(&idt[T_DBLFLT], NULL, DFTSS_SEL, SDT_SYSTASKGT, SEL_KPL); - set_gatesegd(&idt0[T_TSSFLT], &invtsstrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_SEGFLT], &segnptrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_STKFLT], &stktrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_GPFLT], &gptrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_PGFLT], &pftrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); +#endif /* __i386 */ /* - * 15 reserved. + * T_EXTOVRFLT coprocessor-segment-overrun not supported. */ - set_gatesegd(&idt0[15], &resvtrap, KCS_SEL, 0, SDT_SYSIGT, SEL_KPL); - set_gatesegd(&idt0[T_EXTERRFLT], &ndperr, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_ALIGNMENT], &achktrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_MCE], &mcetrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_SIMDFPE], &xmtrap, KCS_SEL, 0, SDT_SYSIGT, + set_gatesegd(&idt[T_TSSFLT], &invtsstrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); + set_gatesegd(&idt[T_SEGFLT], &segnptrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); + set_gatesegd(&idt[T_STKFLT], &stktrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); + set_gatesegd(&idt[T_GPFLT], &gptrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); + set_gatesegd(&idt[T_PGFLT], &pftrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); + set_gatesegd(&idt[T_EXTERRFLT], &ndperr, KCS_SEL, SDT_SYSIGT, SEL_KPL); + set_gatesegd(&idt[T_ALIGNMENT], &achktrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); - - /* - * 20-31 reserved - */ - for (i = 20; i < 32; i++) - set_gatesegd(&idt0[i], &invaltrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - - /* - * interrupts 32 - 255 - */ - for (i = 32; i < 256; i++) { - (void) snprintf(ivctname, sizeof (ivctname), "ivct%d", i); - ivctptr = (void (*)(void))kobj_getsymvalue(ivctname, 0); - if (ivctptr == NULL) - panic("kobj_getsymvalue(%s) failed", ivctname); - - set_gatesegd(&idt0[i], ivctptr, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - } + set_gatesegd(&idt[T_MCE], &mcetrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); + set_gatesegd(&idt[T_SIMDFPE], &xmtrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); /* * install "int80" handler at, well, 0x80. */ - set_gatesegd(&idt0[T_INT80], &sys_int80, KCS_SEL, 0, SDT_SYSIGT, - SEL_UPL); + set_gatesegd(&idt0[T_INT80], &sys_int80, KCS_SEL, SDT_SYSIGT, SEL_UPL); /* * install fast trap handler at 210. */ - set_gatesegd(&idt0[T_FASTTRAP], &fasttrap, KCS_SEL, 0, - SDT_SYSIGT, SEL_UPL); + set_gatesegd(&idt[T_FASTTRAP], &fasttrap, KCS_SEL, SDT_SYSIGT, SEL_UPL); /* * System call handler. */ - set_gatesegd(&idt0[T_SYSCALLINT], &sys_syscall_int, KCS_SEL, 0, - SDT_SYSIGT, SEL_UPL); +#if defined(__amd64) + set_gatesegd(&idt[T_SYSCALLINT], &sys_syscall_int, KCS_SEL, SDT_SYSIGT, + SEL_UPL); + +#elif defined(__i386) + set_gatesegd(&idt[T_SYSCALLINT], &sys_call, KCS_SEL, SDT_SYSIGT, + SEL_UPL); +#endif /* __i386 */ /* * Install the DTrace interrupt handler for the pid provider. */ - set_gatesegd(&idt0[T_DTRACE_RET], &dtrace_ret, KCS_SEL, 0, + set_gatesegd(&idt[T_DTRACE_RET], &dtrace_ret, KCS_SEL, SDT_SYSIGT, SEL_UPL); - if (boothowto & RB_DEBUG) - kdi_dvec_idt_sync(idt0); - - /* - * We must maintain a description of idt0 in convenient IDTR format - * for use by T_NMIFLT and T_PGFLT (nmiint() and pentium_pftrap()) - * handlers. - */ - idt0_default_r.dtr_limit = sizeof (idt0) - 1; - idt0_default_r.dtr_base = (uintptr_t)idt0; - wr_idtr(&idt0_default_r); - /* * Prepare interposing descriptors for the branded "int80" * and syscall handlers and cache copies of the default @@ -658,23 +705,24 @@ init_idt(void) brand_tbl[0].ih_inum = T_INT80; brand_tbl[0].ih_default_desc = idt0[T_INT80]; set_gatesegd(&(brand_tbl[0].ih_interp_desc), &brand_sys_int80, KCS_SEL, - 0, SDT_SYSIGT, SEL_UPL); + SDT_SYSIGT, SEL_UPL); brand_tbl[1].ih_inum = T_SYSCALLINT; brand_tbl[1].ih_default_desc = idt0[T_SYSCALLINT]; + +#if defined(__amd64) set_gatesegd(&(brand_tbl[1].ih_interp_desc), &brand_sys_syscall_int, - KCS_SEL, 0, SDT_SYSIGT, SEL_UPL); + KCS_SEL, SDT_SYSIGT, SEL_UPL); +#elif defined(__i386) + set_gatesegd(&(brand_tbl[1].ih_interp_desc), &brand_sys_call, + KCS_SEL, SDT_SYSIGT, SEL_UPL); +#endif /* __i386 */ brand_tbl[2].ih_inum = 0; } -#elif defined(__i386) - -/* - * Build kernel IDT. - */ static void -init_idt(void) +init_idt(gate_desc_t *idt) { char ivctname[80]; void (*ivctptr)(void); @@ -687,67 +735,13 @@ init_idt(void) * unsupported and reserved. */ for (i = 0; i < NIDT; i++) - set_gatesegd(&idt0[i], &resvtrap, KCS_SEL, 0, SDT_SYSTGT, - SEL_KPL); - - set_gatesegd(&idt0[T_ZERODIV], &div0trap, KCS_SEL, 0, SDT_SYSTGT, - SEL_KPL); - set_gatesegd(&idt0[T_SGLSTP], &dbgtrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_NMIFLT], &nmiint, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_BPTFLT], &brktrap, KCS_SEL, 0, SDT_SYSTGT, - SEL_UPL); - set_gatesegd(&idt0[T_OVFLW], &ovflotrap, KCS_SEL, 0, SDT_SYSTGT, - SEL_UPL); - set_gatesegd(&idt0[T_BOUNDFLT], &boundstrap, KCS_SEL, 0, SDT_SYSTGT, - SEL_KPL); - set_gatesegd(&idt0[T_ILLINST], &invoptrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_NOEXTFLT], &ndptrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - - /* - * Install TSS for T_DBLFLT handler. - */ - set_gatesegd(&idt0[T_DBLFLT], NULL, DFTSS_SEL, 0, SDT_SYSTASKGT, - SEL_KPL); - - /* - * T_EXTOVRFLT coprocessor-segment-overrun not supported. - */ - - set_gatesegd(&idt0[T_TSSFLT], &invtsstrap, KCS_SEL, 0, SDT_SYSTGT, - SEL_KPL); - set_gatesegd(&idt0[T_SEGFLT], &segnptrap, KCS_SEL, 0, SDT_SYSTGT, - SEL_KPL); - set_gatesegd(&idt0[T_STKFLT], &stktrap, KCS_SEL, 0, SDT_SYSTGT, - SEL_KPL); - set_gatesegd(&idt0[T_GPFLT], &gptrap, KCS_SEL, 0, SDT_SYSTGT, - SEL_KPL); - set_gatesegd(&idt0[T_PGFLT], &pftrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - - /* - * 15 reserved. - */ - set_gatesegd(&idt0[15], &resvtrap, KCS_SEL, 0, SDT_SYSTGT, SEL_KPL); - - set_gatesegd(&idt0[T_EXTERRFLT], &ndperr, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_ALIGNMENT], &achktrap, KCS_SEL, 0, SDT_SYSTGT, - SEL_KPL); - set_gatesegd(&idt0[T_MCE], &mcetrap, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); - set_gatesegd(&idt0[T_SIMDFPE], &xmtrap, KCS_SEL, 0, SDT_SYSTGT, - SEL_KPL); + set_gatesegd(&idt[i], &resvtrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); /* * 20-31 reserved */ for (i = 20; i < 32; i++) - set_gatesegd(&idt0[i], &invaltrap, KCS_SEL, 0, SDT_SYSTGT, - SEL_KPL); + set_gatesegd(&idt[i], &invaltrap, KCS_SEL, SDT_SYSIGT, SEL_KPL); /* * interrupts 32 - 255 @@ -758,67 +752,16 @@ init_idt(void) if (ivctptr == NULL) panic("kobj_getsymvalue(%s) failed", ivctname); - set_gatesegd(&idt0[i], ivctptr, KCS_SEL, 0, SDT_SYSIGT, - SEL_KPL); + set_gatesegd(&idt[i], ivctptr, KCS_SEL, SDT_SYSIGT, SEL_KPL); } /* - * install "int80" handler at, well, 0x80. - */ - set_gatesegd(&idt0[T_INT80], &sys_int80, KCS_SEL, 0, SDT_SYSIGT, - SEL_UPL); - - /* - * install fast trap handler at 210. - */ - set_gatesegd(&idt0[T_FASTTRAP], &fasttrap, KCS_SEL, 0, - SDT_SYSIGT, SEL_UPL); - - /* - * System call handler. Note that we don't use the hardware's parameter - * copying mechanism here; see the comment above sys_call() for details. + * Now install the common ones. Note that it will overlay some + * entries installed above like T_SYSCALLINT, T_FASTTRAP etc. */ - set_gatesegd(&idt0[T_SYSCALLINT], &sys_call, KCS_SEL, 0, - SDT_SYSIGT, SEL_UPL); - - /* - * Install the DTrace interrupt handler for the pid provider. - */ - set_gatesegd(&idt0[T_DTRACE_RET], &dtrace_ret, KCS_SEL, 0, - SDT_SYSIGT, SEL_UPL); - - if (boothowto & RB_DEBUG) - kdi_dvec_idt_sync(idt0); - - /* - * We must maintain a description of idt0 in convenient IDTR format - * for use by T_NMIFLT and T_PGFLT (nmiint() and pentium_pftrap()) - * handlers. - */ - idt0_default_r.dtr_limit = sizeof (idt0) - 1; - idt0_default_r.dtr_base = (uintptr_t)idt0; - wr_idtr(&idt0_default_r); - - /* - * Prepare interposing descriptors for the branded "int80" - * and syscall handlers and cache copies of the default - * descriptors. - */ - brand_tbl[0].ih_inum = T_INT80; - brand_tbl[0].ih_default_desc = idt0[T_INT80]; - set_gatesegd(&(brand_tbl[0].ih_interp_desc), &brand_sys_int80, KCS_SEL, - 0, SDT_SYSIGT, SEL_UPL); - - brand_tbl[1].ih_inum = T_SYSCALLINT; - brand_tbl[1].ih_default_desc = idt0[T_SYSCALLINT]; - set_gatesegd(&(brand_tbl[1].ih_interp_desc), &brand_sys_call, - KCS_SEL, 0, SDT_SYSIGT, SEL_UPL); - - brand_tbl[2].ih_inum = 0; + init_idt_common(idt); } -#endif /* __i386 */ - /* * The kernel does not deal with LDTs unless a user explicitly creates * one. Under normal circumstances, the LDTR contains 0. Any process attempting @@ -909,15 +852,61 @@ init_tss(void) #endif /* __i386 */ void -init_tables(void) +init_desctbls(void) { - init_gdt(); + user_desc_t *gdt; + desctbr_t idtr; + + /* + * Setup and install our GDT. + */ + gdt = init_gdt(); + ASSERT(IS_P2ALIGNED((uintptr_t)gdt, PAGESIZE)); + CPU->cpu_m.mcpu_gdt = gdt; + + /* + * Setup and install our IDT. + */ + init_idt(&idt0[0]); + + idtr.dtr_base = (uintptr_t)idt0; + idtr.dtr_limit = sizeof (idt0) - 1; + wr_idtr(&idtr); + CPU->cpu_m.mcpu_idt = idt0; + +#if defined(__i386) + /* + * We maintain a description of idt0 in convenient IDTR format + * for #pf's on some older pentium processors. See pentium_pftrap(). + */ + idt0_default_r = idtr; +#endif /* __i386 */ + init_tss(); - init_idt(); + CPU->cpu_tss = &ktss0; init_ldt(); } /* + * In the early kernel, we need to set up a simple GDT to run on. + */ +void +init_boot_gdt(user_desc_t *bgdt) +{ +#if defined(__amd64) + set_usegd(&bgdt[GDT_B32DATA], SDP_LONG, NULL, -1, SDT_MEMRWA, SEL_KPL, + SDP_PAGES, SDP_OP32); + set_usegd(&bgdt[GDT_B64CODE], SDP_LONG, NULL, -1, SDT_MEMERA, SEL_KPL, + SDP_PAGES, SDP_OP32); +#elif defined(__i386) + set_usegd(&bgdt[GDT_B32DATA], NULL, -1, SDT_MEMRWA, SEL_KPL, + SDP_PAGES, SDP_OP32); + set_usegd(&bgdt[GDT_B32CODE], NULL, -1, SDT_MEMERA, SEL_KPL, + SDP_PAGES, SDP_OP32); +#endif /* __i386 */ +} + +/* * Enable interpositioning on the system call path by rewriting the * sys{call|enter} MSRs and the syscall-related entries in the IDT to use * the branded entry points. diff --git a/usr/src/uts/intel/ia32/os/fpu.c b/usr/src/uts/intel/ia32/os/fpu.c index 7a09eba4bb..bd1ee71396 100644 --- a/usr/src/uts/intel/ia32/os/fpu.c +++ b/usr/src/uts/intel/ia32/os/fpu.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -104,13 +103,13 @@ const struct fnsave_state x87_initial = { }; #if defined(__amd64) -#define fpsave_begin fpxsave_begin +#define fpsave_ctxt fpxsave_ctxt #elif defined(__i386) /* - * This vector is patched to fpxsave_begin() if we discover + * This vector is patched to fpxsave_ctxt() if we discover * we have an SSE-capable chip in fpu_probe(). */ -void (*fpsave_begin)(void *) = fpnsave_begin; +void (*fpsave_ctxt)(void *) = fpnsave_ctxt; #endif static int fpe_sicode(uint_t); @@ -168,7 +167,7 @@ fp_new_lwp(kthread_id_t t, kthread_id_t ct) } #endif installctx(ct, cfp, - fpsave_begin, NULL, fp_new_lwp, fp_new_lwp, NULL, fp_free); + fpsave_ctxt, NULL, fp_new_lwp, fp_new_lwp, NULL, fp_free); /* * Now, when the new lwp starts running, it will take a trap * that will be handled inline in the trap table to cause @@ -291,7 +290,7 @@ fp_seed(void) * Always initialize a new context and initialize the hardware. */ installctx(curthread, fp, - fpsave_begin, NULL, fp_new_lwp, fp_new_lwp, NULL, fp_free); + fpsave_ctxt, NULL, fp_new_lwp, fp_new_lwp, NULL, fp_free); fpinit(); /* @@ -394,6 +393,9 @@ fpnoextflt(struct regs *rp) /* * Handle a processor extension overrun fault * Returns non zero for error. + * + * XXX Shouldn't this just be abolished given that we're not supporting + * anything prior to Pentium? */ /* ARGSUSED */ @@ -408,7 +410,6 @@ fpextovrflt(struct regs *rp) fpinit(); /* initialize the FPU hardware */ setcr0(cur_cr0); sti(); - return (1); /* error, send SIGSEGV signal to the thread */ } diff --git a/usr/src/uts/intel/ia32/os/sendsig.c b/usr/src/uts/intel/ia32/os/sendsig.c index 73a8800e24..4411476dc8 100644 --- a/usr/src/uts/intel/ia32/os/sendsig.c +++ b/usr/src/uts/intel/ia32/os/sendsig.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -184,7 +184,7 @@ sendsig(int sig, k_siginfo_t *sip, void (*hdlr)()) * and validate the stack requirements for the signal handler * context. on_fault will catch any faults. */ - newstack = sigismember(&u.u_sigonstack, sig) && + newstack = sigismember(&PTOU(curproc)->u_sigonstack, sig) && !(lwp->lwp_sigaltstack.ss_flags & (SS_ONSTACK|SS_DISABLE)); if (newstack) { @@ -415,7 +415,7 @@ sendsig32(int sig, k_siginfo_t *sip, void (*hdlr)()) * and validate the stack requirements for the signal handler * context. on_fault will catch any faults. */ - newstack = sigismember(&u.u_sigonstack, sig) && + newstack = sigismember(&PTOU(curproc)->u_sigonstack, sig) && !(lwp->lwp_sigaltstack.ss_flags & (SS_ONSTACK|SS_DISABLE)); if (newstack) { @@ -635,7 +635,7 @@ sendsig(int sig, k_siginfo_t *sip, void (*hdlr)()) * and validate the stack requirements for the signal handler * context. on_fault will catch any faults. */ - newstack = sigismember(&u.u_sigonstack, sig) && + newstack = sigismember(&PTOU(curproc)->u_sigonstack, sig) && !(lwp->lwp_sigaltstack.ss_flags & (SS_ONSTACK|SS_DISABLE)); if (newstack) { diff --git a/usr/src/uts/intel/ia32/os/sundep.c b/usr/src/uts/intel/ia32/os/sundep.c index 1fe1e7e72d..29299be2f1 100644 --- a/usr/src/uts/intel/ia32/os/sundep.c +++ b/usr/src/uts/intel/ia32/os/sundep.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -88,6 +88,7 @@ #include <sys/contract_impl.h> #include <sys/x86_archext.h> #include <sys/segments.h> +#include <sys/ontrap.h> /* * Compare the version of boot that boot says it is against @@ -219,7 +220,7 @@ kern_setup1(void) * XXX - we asssume that the u-area is zeroed out except for * ttolwp(curthread)->lwp_regs. */ - u.u_cmask = (mode_t)CMASK; + PTOU(curproc)->u_cmask = (mode_t)CMASK; thread_init(); /* init thread_free list */ pid_init(); /* initialize pid (proc) table */ @@ -292,8 +293,8 @@ lwp_load(klwp_t *lwp, gregset_t grp, uintptr_t thrptr) rp->r_ps = PSL_USER; /* - * For 64-bit lwps, we allow one magic %fs selector value, and one - * magic %gs selector to point anywhere in the address space using + * For 64-bit lwps, we allow null %fs selector value, and null + * %gs selector to point anywhere in the address space using * %fsbase and %gsbase behind the scenes. libc uses %fs to point * at the ulwp_t structure. * @@ -308,6 +309,31 @@ lwp_load(klwp_t *lwp, gregset_t grp, uintptr_t thrptr) if (lwp_getdatamodel(lwp) == DATAMODEL_ILP32) { if (grp[REG_GS] == LWPGS_SEL) (void) lwp_setprivate(lwp, _LWP_GSBASE, thrptr); + } else { + /* + * See lwp_setprivate in kernel and setup_context in libc. + * + * Currently libc constructs a ucontext from whole cloth for + * every new (not main) lwp created. For 64 bit processes + * %fsbase is directly set to point to current thread pointer. + * In the past (solaris 10) %fs was also set LWPFS_SEL to + * indicate %fsbase. Now we use the null GDT selector for + * this purpose. LWP[FS|GS]_SEL are only intended for 32 bit + * processes. To ease transition we support older libcs in + * the newer kernel by forcing %fs or %gs selector to null + * by calling lwp_setprivate if LWP[FS|GS]_SEL is passed in + * the ucontext. This is should be ripped out at some future + * date. Another fix would be for libc to do a getcontext + * and inherit the null %fs/%gs from the current context but + * that means an extra system call and could hurt performance. + */ + if (grp[REG_FS] == 0x1bb) /* hard code legacy LWPFS_SEL */ + (void) lwp_setprivate(lwp, _LWP_FSBASE, + (uintptr_t)grp[REG_FSBASE]); + + if (grp[REG_GS] == 0x1c3) /* hard code legacy LWPGS_SEL */ + (void) lwp_setprivate(lwp, _LWP_GSBASE, + (uintptr_t)grp[REG_GSBASE]); } #else if (grp[GS] == LWPGS_SEL) @@ -445,6 +471,125 @@ lwp_segregs_save(klwp_t *lwp) sizeof (lwp->lwp_pcb.pcb_gsdesc)) == 0); } +#if defined(__amd64) + +/* + * Update the segment registers with new values from the pcb + * + * We have to do this carefully, and in the following order, + * in case any of the selectors points at a bogus descriptor. + * If they do, we'll catch trap with on_trap and return 1. + * returns 0 on success. + * + * This is particularly tricky for %gs. + * This routine must be executed under a cli. + */ +int +update_sregs(struct regs *rp, klwp_t *lwp) +{ + pcb_t *pcb = &lwp->lwp_pcb; + ulong_t kgsbase; + on_trap_data_t otd; + int rc = 0; + + if (!on_trap(&otd, OT_SEGMENT_ACCESS)) { + + kgsbase = (ulong_t)CPU; + __set_gs(pcb->pcb_gs); + + /* + * If __set_gs fails it's because the new %gs is a bad %gs, + * we'll be taking a trap but with the original %gs and %gsbase + * undamaged (i.e. pointing at curcpu). + * + * We've just mucked up the kernel's gsbase. Oops. In + * particular we can't take any traps at all. Make the newly + * computed gsbase be the hidden gs via __swapgs , and fix + * the kernel's gsbase back again. Later, when we return to + * userland we'll swapgs again restoring gsbase just loaded + * above. + */ + __swapgs(); + rp->r_gs = pcb->pcb_gs; + + /* + * restore kernel's gsbase + */ + wrmsr(MSR_AMD_GSBASE, kgsbase); + + /* + * Only override the descriptor base address if + * r_gs == LWPGS_SEL or if r_gs == NULL. A note on + * NULL descriptors -- 32-bit programs take faults + * if they deference NULL descriptors; however, + * when 64-bit programs load them into %fs or %gs, + * they DONT fault -- only the base address remains + * whatever it was from the last load. Urk. + * + * XXX - note that lwp_setprivate now sets %fs/%gs to the + * null selector for 64 bit processes. Whereas before + * %fs/%gs were set to LWP(FS|GS)_SEL regardless of + * the process's data model. For now we check for both + * values so that the kernel can also support the older + * libc. This should be ripped out at some point in the + * future. + */ + if (pcb->pcb_gs == LWPGS_SEL || pcb->pcb_gs == 0) + wrmsr(MSR_AMD_KGSBASE, pcb->pcb_gsbase); + + __set_ds(pcb->pcb_ds); + rp->r_ds = pcb->pcb_ds; + + __set_es(pcb->pcb_es); + rp->r_es = pcb->pcb_es; + + __set_fs(pcb->pcb_fs); + rp->r_fs = pcb->pcb_fs; + + /* + * Same as for %gs + */ + if (pcb->pcb_fs == LWPFS_SEL || pcb->pcb_fs == 0) + wrmsr(MSR_AMD_FSBASE, pcb->pcb_fsbase); + + } else { + cli(); + rc = 1; + } + no_trap(); + return (rc); +} +#endif /* __amd64 */ + +#ifdef _SYSCALL32_IMPL + +/* + * Make it impossible for a process to change its data model. + * We do this by toggling the present bits for the 32 and + * 64-bit user code descriptors. That way if a user lwp attempts + * to change its data model (by using the wrong code descriptor in + * %cs) it will fault immediately. This also allows us to simplify + * assertions and checks in the kernel. + */ +static void +gdt_ucode_model(model_t model) +{ + cpu_t *cpu; + + kpreempt_disable(); + cpu = CPU; + if (model == DATAMODEL_NATIVE) { + cpu->cpu_gdt[GDT_UCODE].usd_p = 1; + cpu->cpu_gdt[GDT_U32CODE].usd_p = 0; + } else { + cpu->cpu_gdt[GDT_U32CODE].usd_p = 1; + cpu->cpu_gdt[GDT_UCODE].usd_p = 0; + } + kpreempt_enable(); +} + +#endif /* _SYSCALL32_IMPL */ + /* * Restore lwp private fs and gs segment descriptors * on current cpu's GDT. @@ -452,27 +597,19 @@ lwp_segregs_save(klwp_t *lwp) static void lwp_segregs_restore(klwp_t *lwp) { - cpu_t *cpu = CPU; pcb_t *pcb = &lwp->lwp_pcb; + cpu_t *cpu = CPU; ASSERT(VALID_LWP_DESC(&pcb->pcb_fsdesc)); ASSERT(VALID_LWP_DESC(&pcb->pcb_gsdesc)); +#ifdef _SYSCALL32_IMPL + gdt_ucode_model(DATAMODEL_NATIVE); +#endif + cpu->cpu_gdt[GDT_LWPFS] = pcb->pcb_fsdesc; cpu->cpu_gdt[GDT_LWPGS] = pcb->pcb_gsdesc; -#if defined(__amd64) - /* - * Make it impossible for a process to change its data model. - * We do this by toggling the present bits for the 32 and - * 64-bit user code descriptors. That way if a user lwp attempts - * to change its data model (by using the wrong code descriptor in - * %cs) it will fault immediately. This also allows us to simplify - * assertions and checks in the kernel. - */ - cpu->cpu_gdt[GDT_UCODE].usd_p = 1; - cpu->cpu_gdt[GDT_U32CODE].usd_p = 0; -#endif /* __amd64 */ } #ifdef _SYSCALL32_IMPL @@ -480,16 +617,16 @@ lwp_segregs_restore(klwp_t *lwp) static void lwp_segregs_restore32(klwp_t *lwp) { + /*LINTED*/ cpu_t *cpu = CPU; pcb_t *pcb = &lwp->lwp_pcb; - ASSERT(VALID_LWP_DESC(&pcb->pcb_fsdesc)); - ASSERT(VALID_LWP_DESC(&pcb->pcb_gsdesc)); + ASSERT(VALID_LWP_DESC(&lwp->lwp_pcb.pcb_fsdesc)); + ASSERT(VALID_LWP_DESC(&lwp->lwp_pcb.pcb_gsdesc)); + gdt_ucode_model(DATAMODEL_ILP32); cpu->cpu_gdt[GDT_LWPFS] = pcb->pcb_fsdesc; cpu->cpu_gdt[GDT_LWPGS] = pcb->pcb_gsdesc; - cpu->cpu_gdt[GDT_UCODE].usd_p = 0; - cpu->cpu_gdt[GDT_U32CODE].usd_p = 1; } #endif /* _SYSCALL32_IMPL */ @@ -644,18 +781,13 @@ setregs(uarg_t *args) pcb->pcb_fsbase = pcb->pcb_gsbase = 0; if (ttoproc(t)->p_model == DATAMODEL_NATIVE) { - cpu_t *cpu; rp->r_cs = UCS_SEL; /* * Only allow 64-bit user code descriptor to be present. */ - kpreempt_disable(); - cpu = CPU; - cpu->cpu_gdt[GDT_UCODE].usd_p = 1; - cpu->cpu_gdt[GDT_U32CODE].usd_p = 0; - kpreempt_enable(); + gdt_ucode_model(DATAMODEL_NATIVE); /* * Arrange that the virtualized %fs and %gs GDT descriptors @@ -672,7 +804,6 @@ setregs(uarg_t *args) (void) lwp_setprivate(lwp, _LWP_FSBASE, args->thrptr); } else { - cpu_t *cpu; rp->r_cs = U32CS_SEL; rp->r_ds = rp->r_es = UDS_SEL; @@ -680,11 +811,7 @@ setregs(uarg_t *args) /* * only allow 32-bit user code selector to be present. */ - kpreempt_disable(); - cpu = CPU; - cpu->cpu_gdt[GDT_UCODE].usd_p = 0; - cpu->cpu_gdt[GDT_U32CODE].usd_p = 1; - kpreempt_enable(); + gdt_ucode_model(DATAMODEL_ILP32); pcb->pcb_fsdesc = pcb->pcb_gsdesc = zero_u32desc; @@ -697,7 +824,6 @@ setregs(uarg_t *args) } - pcb->pcb_ds = rp->r_ds; pcb->pcb_es = rp->r_es; pcb->pcb_flags |= RUPDATE_PENDING; @@ -714,7 +840,6 @@ setregs(uarg_t *args) */ pcb->pcb_fsdesc = pcb->pcb_gsdesc = zero_udesc; - /* * For %gs we need to reset LWP_GSBASE in pcb and the * per-cpu GDT descriptor. thrptr is either NULL diff --git a/usr/src/uts/intel/ia32/os/sysi86.c b/usr/src/uts/intel/ia32/os/sysi86.c index 8b56b01002..be4eedcb9c 100644 --- a/usr/src/uts/intel/ia32/os/sysi86.c +++ b/usr/src/uts/intel/ia32/os/sysi86.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -61,15 +61,13 @@ #include <vm/faultcode.h> #include <sys/fp.h> #include <sys/cmn_err.h> +#include <sys/segments.h> +#include <sys/clock.h> static void setup_ldt(proc_t *pp); static void *ldt_map(proc_t *pp, uint_t seli); static void ldt_free(proc_t *pp); -extern void rtcsync(void); -extern long ggmtl(void); -extern void sgmtl(long); - /* * sysi86 System Call */ diff --git a/usr/src/uts/intel/ia32/promif/prom_enter.c b/usr/src/uts/intel/ia32/promif/prom_enter.c index f6ed906ea4..ba61f1e767 100644 --- a/usr/src/uts/intel/ia32/promif/prom_enter.c +++ b/usr/src/uts/intel/ia32/promif/prom_enter.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -49,7 +48,7 @@ prom_enter_mon(void) #endif if (boothowto & RB_DEBUG) - kdi_dvec_enter(); + kmdb_enter(); else { prom_printf("Press any key to continue."); (void) prom_getchar(); diff --git a/usr/src/uts/intel/ia32/promif/prom_exit.c b/usr/src/uts/intel/ia32/promif/prom_exit.c index fb5f662a78..a197cdc165 100644 --- a/usr/src/uts/intel/ia32/promif/prom_exit.c +++ b/usr/src/uts/intel/ia32/promif/prom_exit.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -56,7 +55,7 @@ prom_exit_to_mon(void) #else #if !defined(_KMDB) if (boothowto & RB_DEBUG) - kdi_dvec_enter(); + kmdb_enter(); #endif /* !_KMDB */ prom_reboot_prompt(); prom_reboot(NULL); diff --git a/usr/src/uts/intel/ia32/promif/prom_panic.c b/usr/src/uts/intel/ia32/promif/prom_panic.c index 76d29315ac..7fbd81cec2 100644 --- a/usr/src/uts/intel/ia32/promif/prom_panic.c +++ b/usr/src/uts/intel/ia32/promif/prom_panic.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -50,7 +49,7 @@ prom_panic(char *s) #elif defined(_KERNEL) prom_printf(fmt, "kernel", s); if (boothowto & RB_DEBUG) - kdi_dvec_enter(); + kmdb_enter(); #else #error "configuration error" #endif diff --git a/usr/src/uts/intel/ia32/sys/Makefile b/usr/src/uts/intel/ia32/sys/Makefile index bc26e0e42d..d97b2b007d 100644 --- a/usr/src/uts/intel/ia32/sys/Makefile +++ b/usr/src/uts/intel/ia32/sys/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -22,7 +21,7 @@ # #pragma ident "%Z%%M% %I% %E% SMI" # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # uts/intel/ia32/sys/Makefile @@ -32,8 +31,8 @@ include ../../../../Makefile.master HDRS= \ asm_linkage.h \ + kdi_regs.h \ machtypes.h \ - mmu.h \ privregs.h \ psw.h \ pte.h \ diff --git a/usr/src/uts/intel/ia32/sys/kdi_regs.h b/usr/src/uts/intel/ia32/sys/kdi_regs.h new file mode 100644 index 0000000000..3012272815 --- /dev/null +++ b/usr/src/uts/intel/ia32/sys/kdi_regs.h @@ -0,0 +1,87 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _IA32_SYS_KDI_REGS_H +#define _IA32_SYS_KDI_REGS_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define KDIREG_NGREG 21 + +/* + * %ss appears in a different place than a typical struct regs, since the + * machine won't save %ss on a trap entry from the same privilege level. + */ + +#define KDIREG_SAVFP 0 +#define KDIREG_SAVPC 1 +#define KDIREG_SS 2 +#define KDIREG_GS 3 +#define KDIREG_FS 4 +#define KDIREG_ES 5 +#define KDIREG_DS 6 +#define KDIREG_EDI 7 +#define KDIREG_ESI 8 +#define KDIREG_EBP 9 +#define KDIREG_ESP 10 +#define KDIREG_EBX 11 +#define KDIREG_EDX 12 +#define KDIREG_ECX 13 +#define KDIREG_EAX 14 +#define KDIREG_TRAPNO 15 +#define KDIREG_ERR 16 +#define KDIREG_EIP 17 +#define KDIREG_CS 18 +#define KDIREG_EFLAGS 19 +#define KDIREG_UESP 20 + +#define KDIREG_PC KDIREG_EIP +#define KDIREG_SP KDIREG_ESP +#define KDIREG_FP KDIREG_EBP + +#ifdef _ASM + +/* Patch point for MSR clearing. */ +#define KDI_MSR_PATCH \ + nop; nop; nop; nop; \ + nop; nop; nop; nop; \ + nop; nop; nop; nop; \ + nop + +#endif /* _ASM */ + +#define KDI_MSR_PATCHOFF 8 /* bytes of code before patch point */ +#define KDI_MSR_PATCHSZ 13 /* bytes in KDI_MSR_PATCH, above */ + +#ifdef __cplusplus +} +#endif + +#endif /* _IA32_SYS_KDI_REGS_H */ diff --git a/usr/src/uts/intel/ia32/sys/machtypes.h b/usr/src/uts/intel/ia32/sys/machtypes.h index c57e83fdf3..c4cbd311dd 100644 --- a/usr/src/uts/intel/ia32/sys/machtypes.h +++ b/usr/src/uts/intel/ia32/sys/machtypes.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,11 +41,24 @@ extern "C" { #if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || \ defined(__EXTENSIONS__) +#define REG_LABEL_PC 0 +#define REG_LABEL_SP 1 +#define REG_LABEL_BP 2 #if defined(__amd64) -typedef struct _label_t { long val[8]; } label_t; -#else -typedef struct _label_t { long val[6]; } label_t; -#endif +#define REG_LABEL_RBX 3 +#define REG_LABEL_R12 4 +#define REG_LABEL_R13 5 +#define REG_LABEL_R14 6 +#define REG_LABEL_R15 7 +#define REG_LABEL_MAX 8 +#else /* __amd64 */ +#define REG_LABEL_EBX 3 +#define REG_LABEL_ESI 4 +#define REG_LABEL_EDI 5 +#define REG_LABEL_MAX 6 +#endif /* __amd64 */ + +typedef struct _label_t { long val[REG_LABEL_MAX]; } label_t; #endif /* !defined(_POSIX_C_SOURCE)... */ diff --git a/usr/src/uts/intel/ia32/sys/mmu.h b/usr/src/uts/intel/ia32/sys/mmu.h deleted file mode 100644 index 135882602a..0000000000 --- a/usr/src/uts/intel/ia32/sys/mmu.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _IA32_SYS_MMU_H -#define _IA32_SYS_MMU_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifndef _ASM -#include <sys/pte.h> -#if defined(__GNUC__) && defined(_ASM_INLINES) && defined(_KERNEL) -#include <asm/mmu.h> -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Definitions for the Intel 80x86 MMU - */ - -/* - * Page fault error code, pushed onto stack on page fault exception - */ -#define MMU_PFEC_P 0x1 /* Page present */ -#define MMU_PFEC_WRITE 0x2 /* Write access */ -#define MMU_PFEC_USER 0x4 /* User mode access */ - -/* Access types based on above error codes */ -#define MMU_PFEC_AT_MASK (MMU_PFEC_USER|MMU_PFEC_WRITE) -#define MMU_PFEC_AT_UREAD MMU_PFEC_USER -#define MMU_PFEC_AT_UWRITE (MMU_PFEC_USER|MMU_PFEC_WRITE) -#define MMU_PFEC_AT_SREAD 0 -#define MMU_PFEC_AT_SWRITE MMU_PFEC_WRITE - -#if defined(_KERNEL) && !defined(_ASM) - -extern int valid_va_range(caddr_t *, size_t *, size_t, int); - -#endif /* defined(_KERNEL) && !defined(_ASM) */ - -/* - * Page directory and physical page parameters - */ -#ifndef MMU_PAGESIZE -#define MMU_PAGESIZE 4096 -#endif - - - -#define MMU_STD_PAGESIZE MMU_PAGESIZE -#ifdef __amd64 -#define MMU_STD_PAGEMASK 0xFFFFFFFFFFFFF000ULL -#else -#define MMU_STD_PAGEMASK 0xFFFFF000UL -#endif -#define MMU_STD_PAGESHIFT 12 - - - -/* ### also in pte.h */ - -#define TWOMB_PAGESIZE 0x200000 -#define TWOMB_PAGEOFFSET (TWOMB_PAGESIZE - 1) -#define TWOMB_PAGESHIFT 21 -#define FOURMB_PAGESIZE 0x400000 -#define FOURMB_PAGEOFFSET (FOURMB_PAGESIZE - 1) -#define FOURMB_PAGESHIFT 22 -#define FOURMB_PAGEMASK (~FOURMB_PAGEOFFSET) - -#define HAT_INVLDPFNUM 0xffffffff - -#define IN_SAME_4MB_PAGE(a, b) (MMU_L1_INDEX(a) == MMU_L1_INDEX(b)) -#define FOURMB_PDE(a, g, b, c) \ - ((((uint32_t)((uint_t)(a))) << MMU_STD_PAGESHIFT) |\ - ((g) << 8) | PTE_LARGEPAGE |(((b) & 0x03) << 1) | (c)) - -#ifndef _ASM -#define mmu_tlbflush_all() reload_cr3() - -/* Low-level functions */ -extern void mmu_tlbflush_entry(caddr_t); -extern ulong_t getcr3(void); -extern void reload_cr3(void); -extern void setcr3(ulong_t); -#endif /* !_ASM */ - -#ifdef __cplusplus -} -#endif - -#endif /* _IA32_SYS_MMU_H */ diff --git a/usr/src/uts/intel/ia32/sys/privregs.h b/usr/src/uts/intel/ia32/sys/privregs.h index 5c34410768..a1b5e0ae9f 100644 --- a/usr/src/uts/intel/ia32/sys/privregs.h +++ b/usr/src/uts/intel/ia32/sys/privregs.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -88,12 +88,16 @@ struct regs { #define GREG_NUM 8 /* Number of regs between %edi and %eax */ -#endif /* !_ASM */ - #ifdef _KERNEL #define lwptoregs(lwp) ((struct regs *)((lwp)->lwp_regs)) #endif /* _KERNEL */ +#else /* !_ASM */ + +#if defined(_MACHDEP) + +#include <sys/machprivregs.h> + /* * Save current frame on the stack. Uses %eax. */ @@ -149,52 +153,34 @@ struct regs { * and restoring them on exit. */ #define INTR_PUSH \ + cld; \ pusha; \ __SEGREGS_PUSH \ __FRAME_PUSH \ - cmpw $KGS_SEL, REGOFF_GS(%esp); \ - je 7f; \ + cmpw $KGS_SEL, REGOFF_GS(%esp); \ + je 8f; \ movl $0, REGOFF_SAVFP(%esp); \ __SEGREGS_LOAD_KERNEL \ -7: +8: CLEAN_CS -#define INTR_POP \ +#define __INTR_POP \ popa; \ addl $8, %esp; /* get TRAPNO and ERR off the stack */ #define INTR_POP_USER \ addl $8, %esp; /* get extra frame off the stack */ \ __SEGREGS_POP \ - INTR_POP + __INTR_POP -#define INTR_POP_KERNEL \ +#define INTR_POP_KERNEL \ addl $24, %esp; /* skip extra frame and segment registers */ \ - INTR_POP - -/* - * Macros for saving the original segment registers and restoring them - * for fast traps. - */ -#define FAST_INTR_PUSH \ - __SEGREGS_PUSH \ - __SEGREGS_LOAD_KERNEL - -#define FAST_INTR_POP \ - __SEGREGS_POP - -#define DISABLE_INTR_FLAGS \ - pushl $F_OFF; \ - popfl; - -#define ENABLE_INTR_FLAGS \ - pushl $F_ON; \ - popfl; - + __INTR_POP /* * Macros for saving all registers necessary on system call entry, * and restoring them on exit. */ #define SYSCALL_PUSH \ + cld; \ pusha; \ __SEGREGS_PUSH \ subl $8, %esp; \ @@ -204,9 +190,10 @@ struct regs { movl %ecx, REGOFF_EFL(%esp); \ movl $0, REGOFF_SAVPC(%esp); \ movl $0, REGOFF_SAVFP(%esp); \ - __SEGREGS_LOAD_KERNEL + __SEGREGS_LOAD_KERNEL; \ #define SYSENTER_PUSH \ + cld; \ pusha; \ __SEGREGS_PUSH \ subl $8, %esp; \ @@ -217,7 +204,17 @@ struct regs { #define SYSCALL_POP \ INTR_POP_USER +#endif /* _MACHDEP */ +/* + * This is used to set eflags to known values at the head of an + * interrupt gate handler, i.e. interrupts are -already- disabled. + */ +#define INTGATE_INIT_KERNEL_FLAGS \ + pushl $F_OFF; \ + popfl + +#endif /* !_ASM */ #include <sys/controlregs.h> diff --git a/usr/src/uts/intel/ia32/sys/psw.h b/usr/src/uts/intel/ia32/sys/psw.h index 2bee78b933..5697323d40 100644 --- a/usr/src/uts/intel/ia32/sys/psw.h +++ b/usr/src/uts/intel/ia32/sys/psw.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -24,7 +23,7 @@ /* All Rights Reserved */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -110,7 +109,7 @@ typedef int psw_t; #include <sys/tss.h> #include <sys/segments.h> /* selector definitions */ -#define USERMODE(cs) ((uint_t)((cs)&CPL_MASK) != 0) +#define USERMODE(cs) ((uint16_t)(cs) != KCS_SEL) #include <sys/spl.h> diff --git a/usr/src/uts/intel/ia32/sys/pte.h b/usr/src/uts/intel/ia32/sys/pte.h index c0c2726d9c..138647347a 100644 --- a/usr/src/uts/intel/ia32/sys/pte.h +++ b/usr/src/uts/intel/ia32/sys/pte.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,7 +30,6 @@ #ifndef _ASM #include <sys/types.h> -#include <ia32/sys/mmu.h> #endif /* _ASM */ #ifdef __cplusplus diff --git a/usr/src/uts/intel/ia32/sys/traptrace.h b/usr/src/uts/intel/ia32/sys/traptrace.h index a105e0fde2..89e13f513f 100644 --- a/usr/src/uts/intel/ia32/sys/traptrace.h +++ b/usr/src/uts/intel/ia32/sys/traptrace.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -36,19 +35,20 @@ extern "C" { #include <sys/privregs.h> /* - * XX64 Need to fix the following comment. - * * Trap tracing. If TRAPTRACE is defined, an entry is recorded every time * the CPU jumps through the Interrupt Descriptor Table (IDT). One exception * is the Double Fault handler, which does not record a traptrace entry. + * + * There are facilities to (conditionally) interleave tracing of related + * facilities e.h. x-calls. */ /* - * XX64 -- non-assembler files that include this file must include + * Note: non-assembler files that include this file must include * <sys/systm.h> before it, for the typedef of pc_t to be visible. */ -#define TTR_STACK_DEPTH 15 +#define TTR_STACK_DEPTH 10 #ifndef _ASM @@ -66,7 +66,7 @@ typedef struct { greg_t ttr_cr2; union _ttr_info { struct _idt_entry { - uchar_t vector; + short vector; uchar_t ipl; uchar_t spl; uchar_t pri; @@ -74,6 +74,17 @@ typedef struct { struct _gate_entry { int sysnum; } gate_entry; + struct _xc_entry { + ulong_t xce_arg; + ulong_t xce_func; + int8_t xce_pri; + uint8_t xce_marker, + xce_pend, + xce_wait, + xce_ack, + xce_state; + uint_t xce_retval; + } xc_entry; } ttr_info; uintptr_t ttr_curthread; uchar_t ttr_pad[TTR_PAD1_SIZE]; @@ -96,6 +107,8 @@ extern size_t trap_trace_bufsize; extern int trap_trace_freeze; extern trap_trace_rec_t trap_trace_postmort; /* Entry used after death */ +extern trap_trace_rec_t *trap_trace_get_traceptr(uint8_t, ulong_t, ulong_t); + #define TRAPTRACE_FREEZE trap_trace_freeze = 1; #define TRAPTRACE_UNFREEZE trap_trace_freeze = 0; @@ -160,6 +173,8 @@ extern trap_trace_rec_t trap_trace_postmort; /* Entry used after death */ * Note that this macro defines label "9". * Also captures curthread on exit of loop. */ +#define __GETCR2(_mov, reg) \ + _mov %cr2, reg #if defined(__amd64) @@ -173,7 +188,7 @@ extern trap_trace_rec_t trap_trace_postmort; /* Entry used after death */ jl 9b; \ movq %gs:CPU_THREAD, scr2; \ movq scr2, TTR_CURTHREAD(ptr); \ - movq %cr2, scr2; \ + __GETCR2(movq, scr2); \ movq scr2, TTR_CR2(ptr) #elif defined(__i386) @@ -188,7 +203,7 @@ extern trap_trace_rec_t trap_trace_postmort; /* Entry used after death */ jl 9b; \ movl %gs:CPU_THREAD, scr2; \ movl scr2, TTR_CURTHREAD(ptr); \ - movl %cr2, scr2; \ + __GETCR2(movl, scr2); \ movl scr2, TTR_CR2(ptr) #endif /* __i386 */ @@ -244,6 +259,23 @@ extern trap_trace_rec_t trap_trace_postmort; /* Entry used after death */ 9: movl %eax, TTR_STAMP(reg); \ movl %edx, TTR_STAMP+4(reg) +#define TRACE_STACK(tt) \ + pushl %eax; \ + pushl %ecx; \ + pushl %edx; \ + pushl %ebx; \ + pushl $TTR_STACK_DEPTH; \ + movl tt, %ebx; \ + leal TTR_STACK(%ebx), %eax; \ + pushl %eax; \ + call getpcstack; \ + addl $8, %esp; \ + movl %eax, TTR_SDEPTH(%ebx); \ + popl %ebx; \ + popl %edx; \ + popl %ecx; \ + popl %eax + #endif /* __i386 */ #else @@ -264,6 +296,22 @@ extern trap_trace_rec_t trap_trace_postmort; /* Entry used after death */ #define TT_INTERRUPT 0xbb #define TT_TRAP 0xcc #define TT_INTTRAP 0xdd +#define TT_EVENT 0xee /* hypervisor event */ +#define TT_XCALL 0xf0 /* x-call handling */ + +/* + * TT_XCALL subcodes: + */ +#define TT_XC_SVC_BEGIN 0 /* xc_serv() entry */ +#define TT_XC_SVC_END 1 /* xc_serv() return */ +#define TT_XC_START 2 /* xc_common() - pre-dirint */ +#define TT_XC_WAIT 3 /* xc_common() - wait for completion */ +#define TT_XC_ACK 4 /* xc_common() - ack completion */ +#define TT_XC_CAPTURE 5 /* xc_capture() */ +#define TT_XC_RELEASE 6 /* xc_release() */ +#define TT_XC_POKE_CPU 7 /* poke_cpu() */ +#define TT_XC_CBE_FIRE 8 /* cbe_fire() */ +#define TT_XC_CBE_XCALL 9 /* cbe_xcall() */ #ifdef __cplusplus } diff --git a/usr/src/uts/intel/ia32/syscall/lwp_private.c b/usr/src/uts/intel/ia32/syscall/lwp_private.c index 9e97c25efa..da9985a5a2 100644 --- a/usr/src/uts/intel/ia32/syscall/lwp_private.c +++ b/usr/src/uts/intel/ia32/syscall/lwp_private.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -65,13 +64,14 @@ lwp_setprivate(klwp_t *lwp, int which, uintptr_t base) * to work, which is needed by emulators for legacy application * environments .. * - * 64-bit processes also point to a per-cpu GDT segment descriptor + * 64-bit processes may also point to a per-cpu GDT segment descriptor * virtualized to the lwp. However the descriptor base is forced * to zero (because we can't express the full 64-bit address range * in a long mode descriptor), so don't reload segment registers - * in a 64-bit program! + * in a 64-bit program! 64-bit processes must have selector values + * of zero for %fs and %gs to use the 64-bit fs_base and gs_base + * respectively. */ - if ((pcb->pcb_flags & RUPDATE_PENDING) == 0) { pcb->pcb_ds = rp->r_ds; pcb->pcb_es = rp->r_es; @@ -84,28 +84,32 @@ lwp_setprivate(klwp_t *lwp, int which, uintptr_t base) switch (which) { case _LWP_FSBASE: - if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) + if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) { set_usegd(&pcb->pcb_fsdesc, SDP_LONG, 0, 0, SDT_MEMRWA, SEL_UPL, SDP_BYTES, SDP_OP32); - else + rval = pcb->pcb_fs = 0; /* null gdt descriptor */ + } else { set_usegd(&pcb->pcb_fsdesc, SDP_SHORT, (void *)base, -1, SDT_MEMRWA, SEL_UPL, SDP_PAGES, SDP_OP32); + rval = pcb->pcb_fs = LWPFS_SEL; + } if (thisthread) CPU->cpu_gdt[GDT_LWPFS] = pcb->pcb_fsdesc; pcb->pcb_fsbase = base; - rval = pcb->pcb_fs = LWPFS_SEL; break; case _LWP_GSBASE: - if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) + if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) { set_usegd(&pcb->pcb_gsdesc, SDP_LONG, 0, 0, SDT_MEMRWA, SEL_UPL, SDP_BYTES, SDP_OP32); - else + rval = pcb->pcb_gs = 0; /* null gdt descriptor */ + } else { set_usegd(&pcb->pcb_gsdesc, SDP_SHORT, (void *)base, -1, SDT_MEMRWA, SEL_UPL, SDP_PAGES, SDP_OP32); + rval = pcb->pcb_gs = LWPGS_SEL; + } if (thisthread) CPU->cpu_gdt[GDT_LWPGS] = pcb->pcb_gsdesc; pcb->pcb_gsbase = base; - rval = pcb->pcb_gs = LWPGS_SEL; break; default: rval = -1; @@ -115,7 +119,7 @@ lwp_setprivate(klwp_t *lwp, int which, uintptr_t base) #elif defined(__i386) /* - * 32-bit compatibility processes point to the per-cpu GDT segment + * 32-bit processes point to the per-cpu GDT segment * descriptors that are virtualized to the lwp. */ @@ -162,24 +166,44 @@ lwp_getprivate(klwp_t *lwp, int which, uintptr_t base) case _LWP_FSBASE: if ((sbase = pcb->pcb_fsbase) != 0) { - if (pcb->pcb_flags & RUPDATE_PENDING) { - if (pcb->pcb_fs == LWPFS_SEL) - break; + if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) { + if (pcb->pcb_flags & RUPDATE_PENDING) { + if (pcb->pcb_fs == 0) + break; + } else { + if (rp->r_fs == 0) + break; + } } else { - if (rp->r_fs == LWPFS_SEL) - break; + if (pcb->pcb_flags & RUPDATE_PENDING) { + if (pcb->pcb_fs == LWPFS_SEL) + break; + } else { + if (rp->r_fs == LWPFS_SEL) + break; + } } } error = EINVAL; break; case _LWP_GSBASE: if ((sbase = pcb->pcb_gsbase) != 0) { - if (pcb->pcb_flags & RUPDATE_PENDING) { - if (pcb->pcb_gs == LWPGS_SEL) - break; + if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) { + if (pcb->pcb_flags & RUPDATE_PENDING) { + if (pcb->pcb_gs == 0) + break; + } else { + if (rp->r_gs == 0) + break; + } } else { - if (rp->r_gs == LWPGS_SEL) - break; + if (pcb->pcb_flags & RUPDATE_PENDING) { + if (pcb->pcb_gs == LWPGS_SEL) + break; + } else { + if (rp->r_gs == LWPGS_SEL) + break; + } } } error = EINVAL; diff --git a/usr/src/uts/i86pc/io/acpica/README.txt b/usr/src/uts/intel/io/acpica/README.txt index b41ae583c3..b41ae583c3 100644 --- a/usr/src/uts/i86pc/io/acpica/README.txt +++ b/usr/src/uts/intel/io/acpica/README.txt diff --git a/usr/src/uts/i86pc/io/acpica/acpi_enum.c b/usr/src/uts/intel/io/acpica/acpi_enum.c index 9b0977bd62..9b0977bd62 100644 --- a/usr/src/uts/i86pc/io/acpica/acpi_enum.c +++ b/usr/src/uts/intel/io/acpica/acpi_enum.c diff --git a/usr/src/uts/i86pc/io/acpica/acpica.c b/usr/src/uts/intel/io/acpica/acpica.c index a1d10cb5ae..a1d10cb5ae 100644 --- a/usr/src/uts/i86pc/io/acpica/acpica.c +++ b/usr/src/uts/intel/io/acpica/acpica.c diff --git a/usr/src/uts/i86pc/io/acpica/acpica_ec.c b/usr/src/uts/intel/io/acpica/acpica_ec.c index eee4b90803..eee4b90803 100644 --- a/usr/src/uts/i86pc/io/acpica/acpica_ec.c +++ b/usr/src/uts/intel/io/acpica/acpica_ec.c diff --git a/usr/src/uts/i86pc/io/acpica/changes.txt b/usr/src/uts/intel/io/acpica/changes.txt index a7b0278cf5..a7b0278cf5 100644 --- a/usr/src/uts/i86pc/io/acpica/changes.txt +++ b/usr/src/uts/intel/io/acpica/changes.txt diff --git a/usr/src/uts/i86pc/io/acpica/cmp_ca.sh b/usr/src/uts/intel/io/acpica/cmp_ca.sh index b23cfd1f94..0113487ef6 100755 --- a/usr/src/uts/i86pc/io/acpica/cmp_ca.sh +++ b/usr/src/uts/intel/io/acpica/cmp_ca.sh @@ -20,7 +20,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -33,7 +33,7 @@ ACDIR=/export/home/myers/acpica/acpica-unix-20060721 DIFF="diff -w" WSDIR=`workspace name` -WSSRC=usr/src/uts/i86pc/io/acpica +WSSRC=usr/src/uts/intel/io/acpica WSHDR=usr/src/uts/intel/sys/acpi ACFILES=/tmp/$$.acfiles SRCDIRS="debugger disassembler events hardware interpreter namespace \ diff --git a/usr/src/uts/i86pc/io/acpica/debugger/dbcmds.c b/usr/src/uts/intel/io/acpica/debugger/dbcmds.c index b3ae57d306..b3ae57d306 100644 --- a/usr/src/uts/i86pc/io/acpica/debugger/dbcmds.c +++ b/usr/src/uts/intel/io/acpica/debugger/dbcmds.c diff --git a/usr/src/uts/i86pc/io/acpica/debugger/dbdisply.c b/usr/src/uts/intel/io/acpica/debugger/dbdisply.c index d2a7eb578a..d2a7eb578a 100644 --- a/usr/src/uts/i86pc/io/acpica/debugger/dbdisply.c +++ b/usr/src/uts/intel/io/acpica/debugger/dbdisply.c diff --git a/usr/src/uts/i86pc/io/acpica/debugger/dbexec.c b/usr/src/uts/intel/io/acpica/debugger/dbexec.c index 4547f0e5b4..4547f0e5b4 100644 --- a/usr/src/uts/i86pc/io/acpica/debugger/dbexec.c +++ b/usr/src/uts/intel/io/acpica/debugger/dbexec.c diff --git a/usr/src/uts/i86pc/io/acpica/debugger/dbfileio.c b/usr/src/uts/intel/io/acpica/debugger/dbfileio.c index 7a4c761882..7a4c761882 100644 --- a/usr/src/uts/i86pc/io/acpica/debugger/dbfileio.c +++ b/usr/src/uts/intel/io/acpica/debugger/dbfileio.c diff --git a/usr/src/uts/i86pc/io/acpica/debugger/dbhistry.c b/usr/src/uts/intel/io/acpica/debugger/dbhistry.c index afc12ba0d6..afc12ba0d6 100644 --- a/usr/src/uts/i86pc/io/acpica/debugger/dbhistry.c +++ b/usr/src/uts/intel/io/acpica/debugger/dbhistry.c diff --git a/usr/src/uts/i86pc/io/acpica/debugger/dbinput.c b/usr/src/uts/intel/io/acpica/debugger/dbinput.c index cf0162f737..cf0162f737 100644 --- a/usr/src/uts/i86pc/io/acpica/debugger/dbinput.c +++ b/usr/src/uts/intel/io/acpica/debugger/dbinput.c diff --git a/usr/src/uts/i86pc/io/acpica/debugger/dbstats.c b/usr/src/uts/intel/io/acpica/debugger/dbstats.c index 3dde13c246..3dde13c246 100644 --- a/usr/src/uts/i86pc/io/acpica/debugger/dbstats.c +++ b/usr/src/uts/intel/io/acpica/debugger/dbstats.c diff --git a/usr/src/uts/i86pc/io/acpica/debugger/dbutils.c b/usr/src/uts/intel/io/acpica/debugger/dbutils.c index 5a1b1b017f..5a1b1b017f 100644 --- a/usr/src/uts/i86pc/io/acpica/debugger/dbutils.c +++ b/usr/src/uts/intel/io/acpica/debugger/dbutils.c diff --git a/usr/src/uts/i86pc/io/acpica/debugger/dbxface.c b/usr/src/uts/intel/io/acpica/debugger/dbxface.c index fdc2ef797c..fdc2ef797c 100644 --- a/usr/src/uts/i86pc/io/acpica/debugger/dbxface.c +++ b/usr/src/uts/intel/io/acpica/debugger/dbxface.c diff --git a/usr/src/uts/i86pc/io/acpica/disassembler/dmbuffer.c b/usr/src/uts/intel/io/acpica/disassembler/dmbuffer.c index 8f7bbb4c97..8f7bbb4c97 100644 --- a/usr/src/uts/i86pc/io/acpica/disassembler/dmbuffer.c +++ b/usr/src/uts/intel/io/acpica/disassembler/dmbuffer.c diff --git a/usr/src/uts/i86pc/io/acpica/disassembler/dmnames.c b/usr/src/uts/intel/io/acpica/disassembler/dmnames.c index 939f4b183b..939f4b183b 100644 --- a/usr/src/uts/i86pc/io/acpica/disassembler/dmnames.c +++ b/usr/src/uts/intel/io/acpica/disassembler/dmnames.c diff --git a/usr/src/uts/i86pc/io/acpica/disassembler/dmobject.c b/usr/src/uts/intel/io/acpica/disassembler/dmobject.c index d3756e8369..d3756e8369 100644 --- a/usr/src/uts/i86pc/io/acpica/disassembler/dmobject.c +++ b/usr/src/uts/intel/io/acpica/disassembler/dmobject.c diff --git a/usr/src/uts/i86pc/io/acpica/disassembler/dmopcode.c b/usr/src/uts/intel/io/acpica/disassembler/dmopcode.c index 1d907e5bbb..1d907e5bbb 100644 --- a/usr/src/uts/i86pc/io/acpica/disassembler/dmopcode.c +++ b/usr/src/uts/intel/io/acpica/disassembler/dmopcode.c diff --git a/usr/src/uts/i86pc/io/acpica/disassembler/dmresrc.c b/usr/src/uts/intel/io/acpica/disassembler/dmresrc.c index 63e68926b6..63e68926b6 100644 --- a/usr/src/uts/i86pc/io/acpica/disassembler/dmresrc.c +++ b/usr/src/uts/intel/io/acpica/disassembler/dmresrc.c diff --git a/usr/src/uts/i86pc/io/acpica/disassembler/dmresrcl.c b/usr/src/uts/intel/io/acpica/disassembler/dmresrcl.c index 514e139184..514e139184 100644 --- a/usr/src/uts/i86pc/io/acpica/disassembler/dmresrcl.c +++ b/usr/src/uts/intel/io/acpica/disassembler/dmresrcl.c diff --git a/usr/src/uts/i86pc/io/acpica/disassembler/dmresrcs.c b/usr/src/uts/intel/io/acpica/disassembler/dmresrcs.c index 86c9d9f8e5..86c9d9f8e5 100644 --- a/usr/src/uts/i86pc/io/acpica/disassembler/dmresrcs.c +++ b/usr/src/uts/intel/io/acpica/disassembler/dmresrcs.c diff --git a/usr/src/uts/i86pc/io/acpica/disassembler/dmutils.c b/usr/src/uts/intel/io/acpica/disassembler/dmutils.c index ffcce5ca31..ffcce5ca31 100644 --- a/usr/src/uts/i86pc/io/acpica/disassembler/dmutils.c +++ b/usr/src/uts/intel/io/acpica/disassembler/dmutils.c diff --git a/usr/src/uts/i86pc/io/acpica/disassembler/dmwalk.c b/usr/src/uts/intel/io/acpica/disassembler/dmwalk.c index 69e38ff69d..69e38ff69d 100644 --- a/usr/src/uts/i86pc/io/acpica/disassembler/dmwalk.c +++ b/usr/src/uts/intel/io/acpica/disassembler/dmwalk.c diff --git a/usr/src/uts/i86pc/io/acpica/events/evevent.c b/usr/src/uts/intel/io/acpica/events/evevent.c index b9e880bf1a..b9e880bf1a 100644 --- a/usr/src/uts/i86pc/io/acpica/events/evevent.c +++ b/usr/src/uts/intel/io/acpica/events/evevent.c diff --git a/usr/src/uts/i86pc/io/acpica/events/evgpe.c b/usr/src/uts/intel/io/acpica/events/evgpe.c index 52d244eba6..52d244eba6 100644 --- a/usr/src/uts/i86pc/io/acpica/events/evgpe.c +++ b/usr/src/uts/intel/io/acpica/events/evgpe.c diff --git a/usr/src/uts/i86pc/io/acpica/events/evgpeblk.c b/usr/src/uts/intel/io/acpica/events/evgpeblk.c index 21a6692139..21a6692139 100644 --- a/usr/src/uts/i86pc/io/acpica/events/evgpeblk.c +++ b/usr/src/uts/intel/io/acpica/events/evgpeblk.c diff --git a/usr/src/uts/i86pc/io/acpica/events/evmisc.c b/usr/src/uts/intel/io/acpica/events/evmisc.c index d63b1b66ac..d63b1b66ac 100644 --- a/usr/src/uts/i86pc/io/acpica/events/evmisc.c +++ b/usr/src/uts/intel/io/acpica/events/evmisc.c diff --git a/usr/src/uts/i86pc/io/acpica/events/evregion.c b/usr/src/uts/intel/io/acpica/events/evregion.c index 27a470d1c7..27a470d1c7 100644 --- a/usr/src/uts/i86pc/io/acpica/events/evregion.c +++ b/usr/src/uts/intel/io/acpica/events/evregion.c diff --git a/usr/src/uts/i86pc/io/acpica/events/evrgnini.c b/usr/src/uts/intel/io/acpica/events/evrgnini.c index 88a7b1b23f..88a7b1b23f 100644 --- a/usr/src/uts/i86pc/io/acpica/events/evrgnini.c +++ b/usr/src/uts/intel/io/acpica/events/evrgnini.c diff --git a/usr/src/uts/i86pc/io/acpica/events/evsci.c b/usr/src/uts/intel/io/acpica/events/evsci.c index abde1c9d28..abde1c9d28 100644 --- a/usr/src/uts/i86pc/io/acpica/events/evsci.c +++ b/usr/src/uts/intel/io/acpica/events/evsci.c diff --git a/usr/src/uts/i86pc/io/acpica/events/evxface.c b/usr/src/uts/intel/io/acpica/events/evxface.c index ae1a12144f..ae1a12144f 100644 --- a/usr/src/uts/i86pc/io/acpica/events/evxface.c +++ b/usr/src/uts/intel/io/acpica/events/evxface.c diff --git a/usr/src/uts/i86pc/io/acpica/events/evxfevnt.c b/usr/src/uts/intel/io/acpica/events/evxfevnt.c index 5f52cdce82..5f52cdce82 100644 --- a/usr/src/uts/i86pc/io/acpica/events/evxfevnt.c +++ b/usr/src/uts/intel/io/acpica/events/evxfevnt.c diff --git a/usr/src/uts/i86pc/io/acpica/events/evxfregn.c b/usr/src/uts/intel/io/acpica/events/evxfregn.c index 834d65a65d..834d65a65d 100644 --- a/usr/src/uts/i86pc/io/acpica/events/evxfregn.c +++ b/usr/src/uts/intel/io/acpica/events/evxfregn.c diff --git a/usr/src/uts/i86pc/io/acpica/hardware/hwacpi.c b/usr/src/uts/intel/io/acpica/hardware/hwacpi.c index 6849bb0321..6849bb0321 100644 --- a/usr/src/uts/i86pc/io/acpica/hardware/hwacpi.c +++ b/usr/src/uts/intel/io/acpica/hardware/hwacpi.c diff --git a/usr/src/uts/i86pc/io/acpica/hardware/hwgpe.c b/usr/src/uts/intel/io/acpica/hardware/hwgpe.c index a9da5e29ac..a9da5e29ac 100644 --- a/usr/src/uts/i86pc/io/acpica/hardware/hwgpe.c +++ b/usr/src/uts/intel/io/acpica/hardware/hwgpe.c diff --git a/usr/src/uts/i86pc/io/acpica/hardware/hwregs.c b/usr/src/uts/intel/io/acpica/hardware/hwregs.c index 81d63f8f2a..81d63f8f2a 100644 --- a/usr/src/uts/i86pc/io/acpica/hardware/hwregs.c +++ b/usr/src/uts/intel/io/acpica/hardware/hwregs.c diff --git a/usr/src/uts/i86pc/io/acpica/hardware/hwsleep.c b/usr/src/uts/intel/io/acpica/hardware/hwsleep.c index 56e7783a20..56e7783a20 100644 --- a/usr/src/uts/i86pc/io/acpica/hardware/hwsleep.c +++ b/usr/src/uts/intel/io/acpica/hardware/hwsleep.c diff --git a/usr/src/uts/i86pc/io/acpica/hardware/hwtimer.c b/usr/src/uts/intel/io/acpica/hardware/hwtimer.c index 827a828b8c..827a828b8c 100644 --- a/usr/src/uts/i86pc/io/acpica/hardware/hwtimer.c +++ b/usr/src/uts/intel/io/acpica/hardware/hwtimer.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsfield.c b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsfield.c index 7f17d5ed4d..7f17d5ed4d 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsfield.c +++ b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsfield.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsinit.c b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsinit.c index 4ead117b08..4ead117b08 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsinit.c +++ b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsinit.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsmethod.c b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsmethod.c index cbb6869bd6..cbb6869bd6 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsmethod.c +++ b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsmethod.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsmthdat.c b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsmthdat.c index c649f10fd9..c649f10fd9 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsmthdat.c +++ b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsmthdat.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsobject.c b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsobject.c index 6ad096ba84..6ad096ba84 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsobject.c +++ b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsobject.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsopcode.c b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsopcode.c index b5e5675fa0..b5e5675fa0 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsopcode.c +++ b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsopcode.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsutils.c b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsutils.c index 496df6767b..496df6767b 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dsutils.c +++ b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dsutils.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswexec.c b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswexec.c index 4b84880880..4b84880880 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswexec.c +++ b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswexec.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswload.c b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswload.c index 1abe72c5fa..1abe72c5fa 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswload.c +++ b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswload.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswscope.c b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswscope.c index f5d05a7496..f5d05a7496 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswscope.c +++ b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswscope.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswstate.c b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswstate.c index 204acfc559..204acfc559 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/dispatcher/dswstate.c +++ b/usr/src/uts/intel/io/acpica/interpreter/dispatcher/dswstate.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exconfig.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exconfig.c index 90bb058480..90bb058480 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exconfig.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exconfig.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exconvrt.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exconvrt.c index a5882b183a..a5882b183a 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exconvrt.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exconvrt.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/excreate.c b/usr/src/uts/intel/io/acpica/interpreter/executer/excreate.c index 64b2920060..64b2920060 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/excreate.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/excreate.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exdump.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exdump.c index 2a106e871f..2a106e871f 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exdump.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exdump.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exfield.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exfield.c index b134302c8d..b134302c8d 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exfield.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exfield.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exfldio.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exfldio.c index d17d4fb68f..d17d4fb68f 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exfldio.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exfldio.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exmisc.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exmisc.c index 21f065ba89..21f065ba89 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exmisc.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exmisc.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exmutex.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exmutex.c index 23414c4457..23414c4457 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exmutex.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exmutex.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exnames.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exnames.c index 1fd5d260db..1fd5d260db 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exnames.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exnames.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg1.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exoparg1.c index 70157e591d..70157e591d 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg1.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exoparg1.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg2.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exoparg2.c index 53ee147640..53ee147640 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg2.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exoparg2.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg3.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exoparg3.c index 77a4e915b6..77a4e915b6 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg3.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exoparg3.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg6.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exoparg6.c index f65c313f93..f65c313f93 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exoparg6.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exoparg6.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exprep.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exprep.c index 7c024ec11d..7c024ec11d 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exprep.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exprep.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exregion.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exregion.c index c53757fea6..c53757fea6 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exregion.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exregion.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exresnte.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exresnte.c index c7b5a460c5..c7b5a460c5 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exresnte.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exresnte.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exresolv.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exresolv.c index 2efa748144..2efa748144 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exresolv.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exresolv.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exresop.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exresop.c index 2f684ae4df..2f684ae4df 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exresop.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exresop.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exstore.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exstore.c index bc3ee25f39..bc3ee25f39 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exstore.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exstore.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exstoren.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exstoren.c index 452563ff44..452563ff44 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exstoren.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exstoren.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exstorob.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exstorob.c index 4810c0b860..4810c0b860 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exstorob.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exstorob.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exsystem.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exsystem.c index 194bdaf293..194bdaf293 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exsystem.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exsystem.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exutils.c b/usr/src/uts/intel/io/acpica/interpreter/executer/exutils.c index 12e97cda51..12e97cda51 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/executer/exutils.c +++ b/usr/src/uts/intel/io/acpica/interpreter/executer/exutils.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/parser/psargs.c b/usr/src/uts/intel/io/acpica/interpreter/parser/psargs.c index a5aca6460a..a5aca6460a 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/parser/psargs.c +++ b/usr/src/uts/intel/io/acpica/interpreter/parser/psargs.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/parser/psloop.c b/usr/src/uts/intel/io/acpica/interpreter/parser/psloop.c index d3ef539bd1..d3ef539bd1 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/parser/psloop.c +++ b/usr/src/uts/intel/io/acpica/interpreter/parser/psloop.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/parser/psopcode.c b/usr/src/uts/intel/io/acpica/interpreter/parser/psopcode.c index 833073f612..833073f612 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/parser/psopcode.c +++ b/usr/src/uts/intel/io/acpica/interpreter/parser/psopcode.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/parser/psparse.c b/usr/src/uts/intel/io/acpica/interpreter/parser/psparse.c index 6bf7fdc7c5..6bf7fdc7c5 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/parser/psparse.c +++ b/usr/src/uts/intel/io/acpica/interpreter/parser/psparse.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/parser/psscope.c b/usr/src/uts/intel/io/acpica/interpreter/parser/psscope.c index aa57aa3bc5..aa57aa3bc5 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/parser/psscope.c +++ b/usr/src/uts/intel/io/acpica/interpreter/parser/psscope.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/parser/pstree.c b/usr/src/uts/intel/io/acpica/interpreter/parser/pstree.c index d7f62ebecc..d7f62ebecc 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/parser/pstree.c +++ b/usr/src/uts/intel/io/acpica/interpreter/parser/pstree.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/parser/psutils.c b/usr/src/uts/intel/io/acpica/interpreter/parser/psutils.c index 63105b4615..63105b4615 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/parser/psutils.c +++ b/usr/src/uts/intel/io/acpica/interpreter/parser/psutils.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/parser/pswalk.c b/usr/src/uts/intel/io/acpica/interpreter/parser/pswalk.c index 439f842b53..439f842b53 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/parser/pswalk.c +++ b/usr/src/uts/intel/io/acpica/interpreter/parser/pswalk.c diff --git a/usr/src/uts/i86pc/io/acpica/interpreter/parser/psxface.c b/usr/src/uts/intel/io/acpica/interpreter/parser/psxface.c index ac1dbdb6f6..ac1dbdb6f6 100644 --- a/usr/src/uts/i86pc/io/acpica/interpreter/parser/psxface.c +++ b/usr/src/uts/intel/io/acpica/interpreter/parser/psxface.c diff --git a/usr/src/uts/i86pc/io/acpica/master_ops.c b/usr/src/uts/intel/io/acpica/master_ops.c index e37029f6cf..e37029f6cf 100644 --- a/usr/src/uts/i86pc/io/acpica/master_ops.c +++ b/usr/src/uts/intel/io/acpica/master_ops.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nsaccess.c b/usr/src/uts/intel/io/acpica/namespace/nsaccess.c index 9452903499..9452903499 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nsaccess.c +++ b/usr/src/uts/intel/io/acpica/namespace/nsaccess.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nsalloc.c b/usr/src/uts/intel/io/acpica/namespace/nsalloc.c index 322e0b8117..322e0b8117 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nsalloc.c +++ b/usr/src/uts/intel/io/acpica/namespace/nsalloc.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nsdump.c b/usr/src/uts/intel/io/acpica/namespace/nsdump.c index 5621745320..5621745320 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nsdump.c +++ b/usr/src/uts/intel/io/acpica/namespace/nsdump.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nsdumpdv.c b/usr/src/uts/intel/io/acpica/namespace/nsdumpdv.c index c74b4c386f..c74b4c386f 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nsdumpdv.c +++ b/usr/src/uts/intel/io/acpica/namespace/nsdumpdv.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nseval.c b/usr/src/uts/intel/io/acpica/namespace/nseval.c index f9b7ead8d7..f9b7ead8d7 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nseval.c +++ b/usr/src/uts/intel/io/acpica/namespace/nseval.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nsinit.c b/usr/src/uts/intel/io/acpica/namespace/nsinit.c index be13cb49be..be13cb49be 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nsinit.c +++ b/usr/src/uts/intel/io/acpica/namespace/nsinit.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nsload.c b/usr/src/uts/intel/io/acpica/namespace/nsload.c index 10a75070e5..10a75070e5 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nsload.c +++ b/usr/src/uts/intel/io/acpica/namespace/nsload.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nsnames.c b/usr/src/uts/intel/io/acpica/namespace/nsnames.c index 236776c994..236776c994 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nsnames.c +++ b/usr/src/uts/intel/io/acpica/namespace/nsnames.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nsobject.c b/usr/src/uts/intel/io/acpica/namespace/nsobject.c index a59f0c0748..a59f0c0748 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nsobject.c +++ b/usr/src/uts/intel/io/acpica/namespace/nsobject.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nsparse.c b/usr/src/uts/intel/io/acpica/namespace/nsparse.c index c5a21928ab..c5a21928ab 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nsparse.c +++ b/usr/src/uts/intel/io/acpica/namespace/nsparse.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nssearch.c b/usr/src/uts/intel/io/acpica/namespace/nssearch.c index 7ec8f1f048..7ec8f1f048 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nssearch.c +++ b/usr/src/uts/intel/io/acpica/namespace/nssearch.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nsutils.c b/usr/src/uts/intel/io/acpica/namespace/nsutils.c index 4994384da8..4994384da8 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nsutils.c +++ b/usr/src/uts/intel/io/acpica/namespace/nsutils.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nswalk.c b/usr/src/uts/intel/io/acpica/namespace/nswalk.c index b1d5087c78..b1d5087c78 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nswalk.c +++ b/usr/src/uts/intel/io/acpica/namespace/nswalk.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nsxfeval.c b/usr/src/uts/intel/io/acpica/namespace/nsxfeval.c index 3b88369187..3b88369187 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nsxfeval.c +++ b/usr/src/uts/intel/io/acpica/namespace/nsxfeval.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nsxfname.c b/usr/src/uts/intel/io/acpica/namespace/nsxfname.c index 5aa6d37c42..5aa6d37c42 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nsxfname.c +++ b/usr/src/uts/intel/io/acpica/namespace/nsxfname.c diff --git a/usr/src/uts/i86pc/io/acpica/namespace/nsxfobj.c b/usr/src/uts/intel/io/acpica/namespace/nsxfobj.c index 799729b1a4..799729b1a4 100644 --- a/usr/src/uts/i86pc/io/acpica/namespace/nsxfobj.c +++ b/usr/src/uts/intel/io/acpica/namespace/nsxfobj.c diff --git a/usr/src/uts/i86pc/io/acpica/osl.c b/usr/src/uts/intel/io/acpica/osl.c index 205e7a0ea9..205e7a0ea9 100644 --- a/usr/src/uts/i86pc/io/acpica/osl.c +++ b/usr/src/uts/intel/io/acpica/osl.c diff --git a/usr/src/uts/i86pc/io/acpica/osl_ml.s b/usr/src/uts/intel/io/acpica/osl_ml.s index 07c85bbc6b..07c85bbc6b 100644 --- a/usr/src/uts/i86pc/io/acpica/osl_ml.s +++ b/usr/src/uts/intel/io/acpica/osl_ml.s diff --git a/usr/src/uts/i86pc/io/acpica/resources/rsaddr.c b/usr/src/uts/intel/io/acpica/resources/rsaddr.c index 5172e77f1b..5172e77f1b 100644 --- a/usr/src/uts/i86pc/io/acpica/resources/rsaddr.c +++ b/usr/src/uts/intel/io/acpica/resources/rsaddr.c diff --git a/usr/src/uts/i86pc/io/acpica/resources/rscalc.c b/usr/src/uts/intel/io/acpica/resources/rscalc.c index 97fd5a3e71..97fd5a3e71 100644 --- a/usr/src/uts/i86pc/io/acpica/resources/rscalc.c +++ b/usr/src/uts/intel/io/acpica/resources/rscalc.c diff --git a/usr/src/uts/i86pc/io/acpica/resources/rscreate.c b/usr/src/uts/intel/io/acpica/resources/rscreate.c index 1cb836adc7..1cb836adc7 100644 --- a/usr/src/uts/i86pc/io/acpica/resources/rscreate.c +++ b/usr/src/uts/intel/io/acpica/resources/rscreate.c diff --git a/usr/src/uts/i86pc/io/acpica/resources/rsdump.c b/usr/src/uts/intel/io/acpica/resources/rsdump.c index 1f90cf7b42..1f90cf7b42 100644 --- a/usr/src/uts/i86pc/io/acpica/resources/rsdump.c +++ b/usr/src/uts/intel/io/acpica/resources/rsdump.c diff --git a/usr/src/uts/i86pc/io/acpica/resources/rsinfo.c b/usr/src/uts/intel/io/acpica/resources/rsinfo.c index e731c5413c..e731c5413c 100644 --- a/usr/src/uts/i86pc/io/acpica/resources/rsinfo.c +++ b/usr/src/uts/intel/io/acpica/resources/rsinfo.c diff --git a/usr/src/uts/i86pc/io/acpica/resources/rsio.c b/usr/src/uts/intel/io/acpica/resources/rsio.c index 8cbc3c06c1..8cbc3c06c1 100644 --- a/usr/src/uts/i86pc/io/acpica/resources/rsio.c +++ b/usr/src/uts/intel/io/acpica/resources/rsio.c diff --git a/usr/src/uts/i86pc/io/acpica/resources/rsirq.c b/usr/src/uts/intel/io/acpica/resources/rsirq.c index bfd15936bd..bfd15936bd 100644 --- a/usr/src/uts/i86pc/io/acpica/resources/rsirq.c +++ b/usr/src/uts/intel/io/acpica/resources/rsirq.c diff --git a/usr/src/uts/i86pc/io/acpica/resources/rslist.c b/usr/src/uts/intel/io/acpica/resources/rslist.c index d1d60e4630..d1d60e4630 100644 --- a/usr/src/uts/i86pc/io/acpica/resources/rslist.c +++ b/usr/src/uts/intel/io/acpica/resources/rslist.c diff --git a/usr/src/uts/i86pc/io/acpica/resources/rsmemory.c b/usr/src/uts/intel/io/acpica/resources/rsmemory.c index 0e0e3a8dae..0e0e3a8dae 100644 --- a/usr/src/uts/i86pc/io/acpica/resources/rsmemory.c +++ b/usr/src/uts/intel/io/acpica/resources/rsmemory.c diff --git a/usr/src/uts/i86pc/io/acpica/resources/rsmisc.c b/usr/src/uts/intel/io/acpica/resources/rsmisc.c index e7da574321..e7da574321 100644 --- a/usr/src/uts/i86pc/io/acpica/resources/rsmisc.c +++ b/usr/src/uts/intel/io/acpica/resources/rsmisc.c diff --git a/usr/src/uts/i86pc/io/acpica/resources/rsutils.c b/usr/src/uts/intel/io/acpica/resources/rsutils.c index f17c68b64f..f17c68b64f 100644 --- a/usr/src/uts/i86pc/io/acpica/resources/rsutils.c +++ b/usr/src/uts/intel/io/acpica/resources/rsutils.c diff --git a/usr/src/uts/i86pc/io/acpica/resources/rsxface.c b/usr/src/uts/intel/io/acpica/resources/rsxface.c index 1ff12f34b2..1ff12f34b2 100644 --- a/usr/src/uts/i86pc/io/acpica/resources/rsxface.c +++ b/usr/src/uts/intel/io/acpica/resources/rsxface.c diff --git a/usr/src/uts/i86pc/io/acpica/tables/tbconvrt.c b/usr/src/uts/intel/io/acpica/tables/tbconvrt.c index cf84622ecc..cf84622ecc 100644 --- a/usr/src/uts/i86pc/io/acpica/tables/tbconvrt.c +++ b/usr/src/uts/intel/io/acpica/tables/tbconvrt.c diff --git a/usr/src/uts/i86pc/io/acpica/tables/tbget.c b/usr/src/uts/intel/io/acpica/tables/tbget.c index b16cbdded9..b16cbdded9 100644 --- a/usr/src/uts/i86pc/io/acpica/tables/tbget.c +++ b/usr/src/uts/intel/io/acpica/tables/tbget.c diff --git a/usr/src/uts/i86pc/io/acpica/tables/tbgetall.c b/usr/src/uts/intel/io/acpica/tables/tbgetall.c index d6422c0f1c..d6422c0f1c 100644 --- a/usr/src/uts/i86pc/io/acpica/tables/tbgetall.c +++ b/usr/src/uts/intel/io/acpica/tables/tbgetall.c diff --git a/usr/src/uts/i86pc/io/acpica/tables/tbinstal.c b/usr/src/uts/intel/io/acpica/tables/tbinstal.c index b192646abb..b192646abb 100644 --- a/usr/src/uts/i86pc/io/acpica/tables/tbinstal.c +++ b/usr/src/uts/intel/io/acpica/tables/tbinstal.c diff --git a/usr/src/uts/i86pc/io/acpica/tables/tbrsdt.c b/usr/src/uts/intel/io/acpica/tables/tbrsdt.c index 68e2c5fe9e..68e2c5fe9e 100644 --- a/usr/src/uts/i86pc/io/acpica/tables/tbrsdt.c +++ b/usr/src/uts/intel/io/acpica/tables/tbrsdt.c diff --git a/usr/src/uts/i86pc/io/acpica/tables/tbutils.c b/usr/src/uts/intel/io/acpica/tables/tbutils.c index ac09472a7b..ac09472a7b 100644 --- a/usr/src/uts/i86pc/io/acpica/tables/tbutils.c +++ b/usr/src/uts/intel/io/acpica/tables/tbutils.c diff --git a/usr/src/uts/i86pc/io/acpica/tables/tbxface.c b/usr/src/uts/intel/io/acpica/tables/tbxface.c index 3a37e79dbd..3a37e79dbd 100644 --- a/usr/src/uts/i86pc/io/acpica/tables/tbxface.c +++ b/usr/src/uts/intel/io/acpica/tables/tbxface.c diff --git a/usr/src/uts/i86pc/io/acpica/tables/tbxfroot.c b/usr/src/uts/intel/io/acpica/tables/tbxfroot.c index de849be97b..de849be97b 100644 --- a/usr/src/uts/i86pc/io/acpica/tables/tbxfroot.c +++ b/usr/src/uts/intel/io/acpica/tables/tbxfroot.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utalloc.c b/usr/src/uts/intel/io/acpica/utilities/utalloc.c index 91dcfcfcec..91dcfcfcec 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utalloc.c +++ b/usr/src/uts/intel/io/acpica/utilities/utalloc.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utcache.c b/usr/src/uts/intel/io/acpica/utilities/utcache.c index 7b6ff37126..7b6ff37126 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utcache.c +++ b/usr/src/uts/intel/io/acpica/utilities/utcache.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utclib.c b/usr/src/uts/intel/io/acpica/utilities/utclib.c index 2fbebcb804..2fbebcb804 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utclib.c +++ b/usr/src/uts/intel/io/acpica/utilities/utclib.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utcopy.c b/usr/src/uts/intel/io/acpica/utilities/utcopy.c index 111af3085f..111af3085f 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utcopy.c +++ b/usr/src/uts/intel/io/acpica/utilities/utcopy.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utdebug.c b/usr/src/uts/intel/io/acpica/utilities/utdebug.c index 4cb018aed2..4cb018aed2 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utdebug.c +++ b/usr/src/uts/intel/io/acpica/utilities/utdebug.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utdelete.c b/usr/src/uts/intel/io/acpica/utilities/utdelete.c index c85ea669be..c85ea669be 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utdelete.c +++ b/usr/src/uts/intel/io/acpica/utilities/utdelete.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/uteval.c b/usr/src/uts/intel/io/acpica/utilities/uteval.c index ab747d452f..ab747d452f 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/uteval.c +++ b/usr/src/uts/intel/io/acpica/utilities/uteval.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utglobal.c b/usr/src/uts/intel/io/acpica/utilities/utglobal.c index 9a7323df41..9a7323df41 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utglobal.c +++ b/usr/src/uts/intel/io/acpica/utilities/utglobal.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utinit.c b/usr/src/uts/intel/io/acpica/utilities/utinit.c index e9bfab002e..e9bfab002e 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utinit.c +++ b/usr/src/uts/intel/io/acpica/utilities/utinit.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utmath.c b/usr/src/uts/intel/io/acpica/utilities/utmath.c index 0cb9e0782e..0cb9e0782e 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utmath.c +++ b/usr/src/uts/intel/io/acpica/utilities/utmath.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utmisc.c b/usr/src/uts/intel/io/acpica/utilities/utmisc.c index 79a6b51ac1..79a6b51ac1 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utmisc.c +++ b/usr/src/uts/intel/io/acpica/utilities/utmisc.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utmutex.c b/usr/src/uts/intel/io/acpica/utilities/utmutex.c index 53186ec8c5..53186ec8c5 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utmutex.c +++ b/usr/src/uts/intel/io/acpica/utilities/utmutex.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utobject.c b/usr/src/uts/intel/io/acpica/utilities/utobject.c index 6d7a058e5a..6d7a058e5a 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utobject.c +++ b/usr/src/uts/intel/io/acpica/utilities/utobject.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utresrc.c b/usr/src/uts/intel/io/acpica/utilities/utresrc.c index 87f0c15e8e..87f0c15e8e 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utresrc.c +++ b/usr/src/uts/intel/io/acpica/utilities/utresrc.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utstate.c b/usr/src/uts/intel/io/acpica/utilities/utstate.c index 7c9d72f125..7c9d72f125 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utstate.c +++ b/usr/src/uts/intel/io/acpica/utilities/utstate.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/uttrack.c b/usr/src/uts/intel/io/acpica/utilities/uttrack.c index 4dbf0bf755..4dbf0bf755 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/uttrack.c +++ b/usr/src/uts/intel/io/acpica/utilities/uttrack.c diff --git a/usr/src/uts/i86pc/io/acpica/utilities/utxface.c b/usr/src/uts/intel/io/acpica/utilities/utxface.c index 4fad6dfa2d..4fad6dfa2d 100644 --- a/usr/src/uts/i86pc/io/acpica/utilities/utxface.c +++ b/usr/src/uts/intel/io/acpica/utilities/utxface.c diff --git a/usr/src/uts/i86pc/io/agpgart/agp_kstat.c b/usr/src/uts/intel/io/agpgart/agp_kstat.c index 1913fb878c..1913fb878c 100644 --- a/usr/src/uts/i86pc/io/agpgart/agp_kstat.c +++ b/usr/src/uts/intel/io/agpgart/agp_kstat.c diff --git a/usr/src/uts/i86pc/io/agpgart/agpgart.c b/usr/src/uts/intel/io/agpgart/agpgart.c index 9f17285944..9f17285944 100644 --- a/usr/src/uts/i86pc/io/agpgart/agpgart.c +++ b/usr/src/uts/intel/io/agpgart/agpgart.c diff --git a/usr/src/uts/i86pc/io/agpgart/agpgart.conf b/usr/src/uts/intel/io/agpgart/agpgart.conf index 0223702758..0223702758 100644 --- a/usr/src/uts/i86pc/io/agpgart/agpgart.conf +++ b/usr/src/uts/intel/io/agpgart/agpgart.conf diff --git a/usr/src/uts/i86pc/io/agpgart/agptarget.c b/usr/src/uts/intel/io/agpgart/agptarget.c index 4cce6c8550..4cce6c8550 100644 --- a/usr/src/uts/i86pc/io/agpgart/agptarget.c +++ b/usr/src/uts/intel/io/agpgart/agptarget.c diff --git a/usr/src/uts/i86pc/io/agpgart/amd64_gart.c b/usr/src/uts/intel/io/agpgart/amd64_gart.c index fbcebf781d..fbcebf781d 100644 --- a/usr/src/uts/i86pc/io/agpgart/amd64_gart.c +++ b/usr/src/uts/intel/io/agpgart/amd64_gart.c diff --git a/usr/src/uts/i86pc/io/agpmaster/agpmaster.c b/usr/src/uts/intel/io/agpmaster/agpmaster.c index 2accb3d2fc..2accb3d2fc 100644 --- a/usr/src/uts/i86pc/io/agpmaster/agpmaster.c +++ b/usr/src/uts/intel/io/agpmaster/agpmaster.c diff --git a/usr/src/uts/intel/io/dktp/controller/ata/ata_disk.c b/usr/src/uts/intel/io/dktp/controller/ata/ata_disk.c index e19a1f6427..7a172402c8 100644 --- a/usr/src/uts/intel/io/dktp/controller/ata/ata_disk.c +++ b/usr/src/uts/intel/io/dktp/controller/ata/ata_disk.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2471,10 +2471,6 @@ ata_disk_initialize_device_parameters( { int rc; -#ifdef _SIMULATOR_SUPPORT - extern int simulator_run; /* running under simulator ? */ -#endif /* _SIMULATOR_SUPPORT */ - rc = ata_command(ata_ctlp, ata_drvp, FALSE, FALSE, ata_disk_init_dev_parm_wait, ATC_SETPARAM, @@ -2485,15 +2481,8 @@ ata_disk_initialize_device_parameters( 0, /* cyl_low n/a */ 0); /* cyl_hi n/a */ -#ifdef _SIMULATOR_SUPPORT - if (rc || simulator_run) { - return (TRUE); - } -#else - if (rc) { + if (rc) return (TRUE); - } -#endif /* _SIMULATOR_SUPPORT */ ADBG_ERROR(("ata_init_dev_parms: failed\n")); return (FALSE); diff --git a/usr/src/uts/intel/io/dktp/controller/ata/atapi.c b/usr/src/uts/intel/io/dktp/controller/ata/atapi.c index 0a0f01350a..048f498d31 100644 --- a/usr/src/uts/intel/io/dktp/controller/ata/atapi.c +++ b/usr/src/uts/intel/io/dktp/controller/ata/atapi.c @@ -2,7 +2,7 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). + * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE @@ -20,7 +20,7 @@ */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -164,7 +164,7 @@ atapi_detach( ADBG_TRACE(("atapi_detach entered\n")); if (ata_ctlp->ac_flags & AC_SCSI_HBA_ATTACH) - scsi_hba_detach(ata_ctlp->ac_dip); + (void) scsi_hba_detach(ata_ctlp->ac_dip); if (ata_ctlp->ac_flags & AC_SCSI_HBA_TRAN_ALLOC) scsi_hba_tran_free(ata_ctlp->ac_atapi_tran); diff --git a/usr/src/uts/i86pc/io/dnet.c b/usr/src/uts/intel/io/dnet.c index e3e4d87ae3..e3e4d87ae3 100644 --- a/usr/src/uts/i86pc/io/dnet.c +++ b/usr/src/uts/intel/io/dnet.c diff --git a/usr/src/uts/i86pc/io/dnet.conf b/usr/src/uts/intel/io/dnet.conf index 4a4692dec2..4a4692dec2 100644 --- a/usr/src/uts/i86pc/io/dnet.conf +++ b/usr/src/uts/intel/io/dnet.conf diff --git a/usr/src/uts/i86pc/io/drm/drm_asm.s b/usr/src/uts/intel/io/drm/drm_asm.s index 9a0440dfce..9a0440dfce 100644 --- a/usr/src/uts/i86pc/io/drm/drm_asm.s +++ b/usr/src/uts/intel/io/drm/drm_asm.s diff --git a/usr/src/uts/i86pc/io/drm/i915_dma.c b/usr/src/uts/intel/io/drm/i915_dma.c index e0ffdef164..e0ffdef164 100644 --- a/usr/src/uts/i86pc/io/drm/i915_dma.c +++ b/usr/src/uts/intel/io/drm/i915_dma.c diff --git a/usr/src/uts/i86pc/io/drm/i915_drm.h b/usr/src/uts/intel/io/drm/i915_drm.h index 2069454ec1..2069454ec1 100644 --- a/usr/src/uts/i86pc/io/drm/i915_drm.h +++ b/usr/src/uts/intel/io/drm/i915_drm.h diff --git a/usr/src/uts/i86pc/io/drm/i915_drv.c b/usr/src/uts/intel/io/drm/i915_drv.c index bceeeb6071..bceeeb6071 100644 --- a/usr/src/uts/i86pc/io/drm/i915_drv.c +++ b/usr/src/uts/intel/io/drm/i915_drv.c diff --git a/usr/src/uts/i86pc/io/drm/i915_drv.h b/usr/src/uts/intel/io/drm/i915_drv.h index 5725ffbb7b..5725ffbb7b 100644 --- a/usr/src/uts/i86pc/io/drm/i915_drv.h +++ b/usr/src/uts/intel/io/drm/i915_drv.h diff --git a/usr/src/uts/i86pc/io/drm/i915_irq.c b/usr/src/uts/intel/io/drm/i915_irq.c index 9d23b2cb24..9d23b2cb24 100644 --- a/usr/src/uts/i86pc/io/drm/i915_irq.c +++ b/usr/src/uts/intel/io/drm/i915_irq.c diff --git a/usr/src/uts/i86pc/io/drm/i915_mem.c b/usr/src/uts/intel/io/drm/i915_mem.c index 43f9582a57..43f9582a57 100644 --- a/usr/src/uts/i86pc/io/drm/i915_mem.c +++ b/usr/src/uts/intel/io/drm/i915_mem.c diff --git a/usr/src/uts/i86pc/io/drm/i915_sundrv.c b/usr/src/uts/intel/io/drm/i915_sundrv.c index f588bd0a3c..f588bd0a3c 100644 --- a/usr/src/uts/i86pc/io/drm/i915_sundrv.c +++ b/usr/src/uts/intel/io/drm/i915_sundrv.c diff --git a/usr/src/uts/i86pc/io/fd.conf b/usr/src/uts/intel/io/fd.conf index 1f3a662175..1f3a662175 100644 --- a/usr/src/uts/i86pc/io/fd.conf +++ b/usr/src/uts/intel/io/fd.conf diff --git a/usr/src/uts/common/io/i8254.c b/usr/src/uts/intel/io/i8254.c index ff590fc879..80209c228b 100644 --- a/usr/src/uts/common/io/i8254.c +++ b/usr/src/uts/intel/io/i8254.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -45,12 +44,6 @@ #define PIT_COUNTDOWN (PIT_READMODE | PIT_NDIVMODE) #define MICROCOUNT 0x2000 -#ifdef _SIMULATOR_SUPPORT - -extern int simulator_run; /* if non-zero then running under simulator */ - -#endif /* _SIMULATOR_SUPPORT */ - void microfind(void) { @@ -74,15 +67,9 @@ microfind(void) * algorithm progresses in order to facilitate faster cpu's. */ unsigned long found, min = 0xe000; - int s; + ulong_t s; unsigned char status; -#ifdef _SIMULATOR_SUPPORT - if (simulator_run) { - microdata = 133; /* 40 Mhz cpu simulator hack */ - return; - } -#endif /* _SIMULATOR_SUPPORT */ s = clear_int_flag(); /* disable interrupts */ /*CONSTCOND*/ diff --git a/usr/src/uts/i86pc/io/logi.c b/usr/src/uts/intel/io/logi.c index 2207862737..2207862737 100644 --- a/usr/src/uts/i86pc/io/logi.c +++ b/usr/src/uts/intel/io/logi.c diff --git a/usr/src/uts/i86pc/io/mii.c b/usr/src/uts/intel/io/mii.c index 5167ec1976..5167ec1976 100644 --- a/usr/src/uts/i86pc/io/mii.c +++ b/usr/src/uts/intel/io/mii.c diff --git a/usr/src/uts/i86pc/io/mscsi.c b/usr/src/uts/intel/io/mscsi.c index 749baa478f..749baa478f 100644 --- a/usr/src/uts/i86pc/io/mscsi.c +++ b/usr/src/uts/intel/io/mscsi.c diff --git a/usr/src/uts/i86pc/io/mscsi.conf b/usr/src/uts/intel/io/mscsi.conf index 90f721857e..90f721857e 100644 --- a/usr/src/uts/i86pc/io/mscsi.conf +++ b/usr/src/uts/intel/io/mscsi.conf diff --git a/usr/src/uts/i86pc/io/msm.c b/usr/src/uts/intel/io/msm.c index 152b8983f2..152b8983f2 100644 --- a/usr/src/uts/i86pc/io/msm.c +++ b/usr/src/uts/intel/io/msm.c diff --git a/usr/src/uts/i86pc/io/pci/mps_table.h b/usr/src/uts/intel/io/pci/mps_table.h index 8f8c1dc24e..8f8c1dc24e 100644 --- a/usr/src/uts/i86pc/io/pci/mps_table.h +++ b/usr/src/uts/intel/io/pci/mps_table.h diff --git a/usr/src/uts/i86pc/io/pci/pci_autoconfig.c b/usr/src/uts/intel/io/pci/pci_autoconfig.c index bbcc2ed420..bbcc2ed420 100644 --- a/usr/src/uts/i86pc/io/pci/pci_autoconfig.c +++ b/usr/src/uts/intel/io/pci/pci_autoconfig.c diff --git a/usr/src/uts/i86pc/io/pci/pci_boot.c b/usr/src/uts/intel/io/pci/pci_boot.c index 8a3bc25529..8a3bc25529 100644 --- a/usr/src/uts/i86pc/io/pci/pci_boot.c +++ b/usr/src/uts/intel/io/pci/pci_boot.c diff --git a/usr/src/uts/i86pc/io/pci/pci_memlist.c b/usr/src/uts/intel/io/pci/pci_memlist.c index f03e33a785..f03e33a785 100644 --- a/usr/src/uts/i86pc/io/pci/pci_memlist.c +++ b/usr/src/uts/intel/io/pci/pci_memlist.c diff --git a/usr/src/uts/i86pc/io/pci/pci_pci.c b/usr/src/uts/intel/io/pci/pci_pci.c index b6dbe7f1b9..b6dbe7f1b9 100644 --- a/usr/src/uts/i86pc/io/pci/pci_pci.c +++ b/usr/src/uts/intel/io/pci/pci_pci.c diff --git a/usr/src/uts/i86pc/io/pci/pci_resource.c b/usr/src/uts/intel/io/pci/pci_resource.c index bb8c8b1ea3..bb8c8b1ea3 100644 --- a/usr/src/uts/i86pc/io/pci/pci_resource.c +++ b/usr/src/uts/intel/io/pci/pci_resource.c diff --git a/usr/src/uts/i86pc/io/pci/pcihrt.h b/usr/src/uts/intel/io/pci/pcihrt.h index 7192eca2c5..7192eca2c5 100644 --- a/usr/src/uts/i86pc/io/pci/pcihrt.h +++ b/usr/src/uts/intel/io/pci/pcihrt.h diff --git a/usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_acpi.c b/usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_acpi.c index ec4b63c128..753ddf8899 100644 --- a/usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_acpi.c +++ b/usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_acpi.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -119,7 +118,7 @@ pciehpc_acpi_hotplug_enabled(dev_info_t *dip) * No ACPI device for this bus node. Assume there is * no ACPI hot plug support on this bus. */ - PCIEHPC_DEBUG((CE_CONT, "No ACPI device found (dip %p)", + PCIEHPC_DEBUG((CE_CONT, "No ACPI device found (dip %p)\n", (void *)dip)); return (0); } @@ -368,7 +367,7 @@ pciehpc_acpi_slotinfo_init(pciehpc_t *ctrl_p) if (pciehpc_acpi_install_event_handler(ctrl_p) != AE_OK) return (DDI_FAILURE); - PCIEHPC_DEBUG((CE_NOTE, "ACPI hot plug is enabled for slot #%d", + PCIEHPC_DEBUG((CE_NOTE, "ACPI hot plug is enabled for slot #%d\n", ctrl_p->slot.slotNum)); return (DDI_SUCCESS); @@ -427,7 +426,7 @@ pciehpc_acpi_slot_connect(caddr_t ops_arg, hpc_slot_t slot_hdl, /* make sure the MRL switch is closed if present */ if ((ctrl_p->has_mrl) && (status & PCIE_SLOTSTS_MRL_SENSOR_OPEN)) { /* MRL switch is open */ - cmn_err(CE_WARN, "MRL switch is open on slot %d\n", + cmn_err(CE_WARN, "MRL switch is open on slot %d", ctrl_p->slot.slotNum); goto cleanup; } @@ -505,7 +504,7 @@ pciehpc_acpi_slot_disconnect(caddr_t ops_arg, hpc_slot_t slot_hdl, /* make sure the slot has a device present */ if (!(status & PCIE_SLOTSTS_PRESENCE_DETECTED)) { /* slot is empty */ - PCIEHPC_DEBUG((CE_WARN, "slot %d is empty\n", + PCIEHPC_DEBUG((CE_WARN, "slot %d is empty", ctrl_p->slot.slotNum)); goto cleanup; } @@ -587,7 +586,7 @@ pciehpc_acpi_notify_handler(ACPI_HANDLE device, uint32_t val, void *context) acpi_p = ctrl_p->misc_data; if (pciehpc_acpi_get_dev_state(acpi_p->slot_dev_obj, &dev_state) != AE_OK) { - cmn_err(CE_WARN, "failed to get device status on slot %d\n", + cmn_err(CE_WARN, "failed to get device status on slot %d", ctrl_p->slot.slotNum); } PCIEHPC_DEBUG((CE_CONT, "(1)device state on slot #%d: 0x%x\n", @@ -599,12 +598,12 @@ pciehpc_acpi_notify_handler(ACPI_HANDLE device, uint32_t val, void *context) case 0: /* (re)enumerate the device */ case 3: /* Request Eject */ if (ctrl_p->slot.slot_state != HPC_SLOT_CONNECTED) { - /* unexpected slot state; suprise removal? */ - cmn_err(CE_WARN, "Unexpteced event on slot #%d" - "(state 0x%x)\n", ctrl_p->slot.slotNum, dev_state); + /* unexpected slot state; surprise removal? */ + cmn_err(CE_WARN, "Unexpected event on slot #%d" + "(state 0x%x)", ctrl_p->slot.slotNum, dev_state); } /* send the ATTN button event to HPS framework */ - hpc_slot_event_notify(ctrl_p->slot.slot_handle, + (void) hpc_slot_event_notify(ctrl_p->slot.slot_handle, HPC_EVENT_SLOT_ATTN, HPC_EVENT_NORMAL); break; default: @@ -647,7 +646,7 @@ pciehpc_acpi_power_on_slot(pciehpc_t *ctrl_p) if (status == AE_OK) { if (pciehpc_acpi_get_dev_state(acpi_p->slot_dev_obj, &dev_state) != AE_OK) - cmn_err(CE_WARN, "failed to get device status on slot #%d\n", + cmn_err(CE_WARN, "failed to get device status on slot #%d", ctrl_p->slot.slotNum); } PCIEHPC_DEBUG((CE_CONT, "(3)device state on slot #%d: 0x%x\n", @@ -657,7 +656,7 @@ pciehpc_acpi_power_on_slot(pciehpc_t *ctrl_p) if (ctrl_p->slot.slot_state != HPC_SLOT_CONNECTED) { cmn_err(CE_WARN, "failed to power on the slot #%d" - "(dev_state 0x%x, ACPI_STATUS 0x%x)\n", + "(dev_state 0x%x, ACPI_STATUS 0x%x)", ctrl_p->slot.slotNum, dev_state, status); return (AE_ERROR); } @@ -684,7 +683,7 @@ pciehpc_acpi_power_off_slot(pciehpc_t *ctrl_p) if (status == AE_OK) { if (pciehpc_acpi_get_dev_state(acpi_p->slot_dev_obj, &dev_state) != AE_OK) - cmn_err(CE_WARN, "failed to get device status on slot #%d\n", + cmn_err(CE_WARN, "failed to get device status on slot #%d", ctrl_p->slot.slotNum); } PCIEHPC_DEBUG((CE_CONT, "(2)device state on slot #%d: 0x%x\n", @@ -694,7 +693,7 @@ pciehpc_acpi_power_off_slot(pciehpc_t *ctrl_p) if (ctrl_p->slot.slot_state == HPC_SLOT_CONNECTED) { cmn_err(CE_WARN, "failed to power OFF the slot #%d" - "(dev_state 0x%x, ACPI_STATUS 0x%x)\n", + "(dev_state 0x%x, ACPI_STATUS 0x%x)", ctrl_p->slot.slotNum, dev_state, status); return (AE_ERROR); } diff --git a/usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_acpi.h b/usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_acpi.h index 96e78556e2..96e78556e2 100644 --- a/usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_acpi.h +++ b/usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_acpi.h diff --git a/usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_nvidia.c b/usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_nvidia.c index e1294c2998..e1294c2998 100644 --- a/usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_nvidia.c +++ b/usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_nvidia.c diff --git a/usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_nvidia.h b/usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_nvidia.h index 3ea7fb1f9e..3ea7fb1f9e 100644 --- a/usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_nvidia.h +++ b/usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_nvidia.h diff --git a/usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_x86.c b/usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_x86.c index f9659bbd9e..f9659bbd9e 100644 --- a/usr/src/uts/i86pc/io/pciex/hotplug/pciehpc/pciehpc_x86.c +++ b/usr/src/uts/intel/io/pciex/hotplug/pciehpc/pciehpc_x86.c diff --git a/usr/src/uts/i86pc/io/pciex/pcie_error.c b/usr/src/uts/intel/io/pciex/pcie_error.c index e688c7885c..e688c7885c 100644 --- a/usr/src/uts/i86pc/io/pciex/pcie_error.c +++ b/usr/src/uts/intel/io/pciex/pcie_error.c diff --git a/usr/src/uts/i86pc/io/pciex/pcie_error.h b/usr/src/uts/intel/io/pciex/pcie_error.h index b829525850..b829525850 100644 --- a/usr/src/uts/i86pc/io/pciex/pcie_error.h +++ b/usr/src/uts/intel/io/pciex/pcie_error.h diff --git a/usr/src/uts/i86pc/io/pciex/pcie_nvidia.c b/usr/src/uts/intel/io/pciex/pcie_nvidia.c index aec3a31580..aec3a31580 100644 --- a/usr/src/uts/i86pc/io/pciex/pcie_nvidia.c +++ b/usr/src/uts/intel/io/pciex/pcie_nvidia.c diff --git a/usr/src/uts/i86pc/io/pciex/pcie_nvidia.h b/usr/src/uts/intel/io/pciex/pcie_nvidia.h index b3550a878f..b3550a878f 100644 --- a/usr/src/uts/i86pc/io/pciex/pcie_nvidia.h +++ b/usr/src/uts/intel/io/pciex/pcie_nvidia.h diff --git a/usr/src/uts/i86pc/io/pciex/pcie_pci.c b/usr/src/uts/intel/io/pciex/pcie_pci.c index abf22ceb20..abf22ceb20 100644 --- a/usr/src/uts/i86pc/io/pciex/pcie_pci.c +++ b/usr/src/uts/intel/io/pciex/pcie_pci.c diff --git a/usr/src/uts/i86pc/io/pciex/pcie_pci.conf b/usr/src/uts/intel/io/pciex/pcie_pci.conf index b8d0d8b148..b8d0d8b148 100644 --- a/usr/src/uts/i86pc/io/pciex/pcie_pci.conf +++ b/usr/src/uts/intel/io/pciex/pcie_pci.conf diff --git a/usr/src/uts/i86pc/io/smcp/smcp.c b/usr/src/uts/intel/io/smcp/smcp.c index 74cc4ea3b6..74cc4ea3b6 100644 --- a/usr/src/uts/i86pc/io/smcp/smcp.c +++ b/usr/src/uts/intel/io/smcp/smcp.c diff --git a/usr/src/uts/i86pc/io/smcp/smcp.h b/usr/src/uts/intel/io/smcp/smcp.h index 41e1a26829..41e1a26829 100644 --- a/usr/src/uts/i86pc/io/smcp/smcp.h +++ b/usr/src/uts/intel/io/smcp/smcp.h diff --git a/usr/src/uts/i86pc/kb8042/Makefile b/usr/src/uts/intel/kb8042/Makefile index acfdfb36ef..173b286437 100644 --- a/usr/src/uts/i86pc/kb8042/Makefile +++ b/usr/src/uts/intel/kb8042/Makefile @@ -19,15 +19,15 @@ # CDDL HEADER END # # -# uts/i86pc/kb8042/%M% -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# uts/intel/kb8042/%M% +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" # # This makefile drives the production of the kb8042 driver # -# i86pc implementation architecture dependent +# intel architecture dependent # # @@ -41,12 +41,12 @@ UTSBASE = ../.. MODULE = kb8042 OBJECTS = $(KB8042_OBJS:%=$(OBJS_DIR)/%) LINTS = $(KB8042_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel LDFLAGS += -dy -Nmisc/kbtrans @@ -88,4 +88,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/intel/kdi/amd64/kdi_asm.s b/usr/src/uts/intel/kdi/amd64/kdi_asm.s new file mode 100644 index 0000000000..365d4fdaea --- /dev/null +++ b/usr/src/uts/intel/kdi/amd64/kdi_asm.s @@ -0,0 +1,641 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Debugger entry for both master and slave CPUs + */ + +#if defined(__lint) +#include <sys/types.h> +#endif + +#include <sys/segments.h> +#include <sys/asm_linkage.h> +#include <sys/controlregs.h> +#include <sys/x86_archext.h> +#include <sys/privregs.h> +#include <sys/machprivregs.h> +#include <sys/kdi_regs.h> +#include <sys/psw.h> +#include <sys/uadmin.h> + +#ifdef _ASM + +#include <kdi_assym.h> +#include <assym.h> + +/* clobbers %rdx, %rcx, returns addr in %rax, CPU ID in %rbx */ +#define GET_CPUSAVE_ADDR \ + movzbq %gs:CPU_ID, %rbx; \ + movq %rbx, %rax; \ + movq $KRS_SIZE, %rcx; \ + mulq %rcx; \ + movq $kdi_cpusave, %rdx; \ + /*CSTYLED*/ \ + addq (%rdx), %rax + +/* + * Save copies of the IDT and GDT descriptors. Note that we only save the IDT + * and GDT if the IDT isn't ours, as we may be legitimately re-entering the + * debugger through the trap handler. We don't want to clobber the saved IDT + * in the process, as we'd end up resuming the world on our IDT. + */ +#define SAVE_IDTGDT \ + movq %gs:CPU_IDT, %r11; \ + leaq kdi_idt(%rip), %rsi; \ + cmpq %rsi, %r11; \ + je 1f; \ + movq %r11, KRS_IDT(%rax); \ + movq %gs:CPU_GDT, %r11; \ + movq %r11, KRS_GDT(%rax); \ +1: + +/* %ss, %rsp, %rflags, %cs, %rip, %err, %trapno already on stack */ + +#define KDI_SAVE_REGS(base) \ + movq %rdi, REG_OFF(KDIREG_RDI)(base); \ + movq %rsi, REG_OFF(KDIREG_RSI)(base); \ + movq %rdx, REG_OFF(KDIREG_RDX)(base); \ + movq %rcx, REG_OFF(KDIREG_RCX)(base); \ + movq %r8, REG_OFF(KDIREG_R8)(base); \ + movq %r9, REG_OFF(KDIREG_R9)(base); \ + movq %rax, REG_OFF(KDIREG_RAX)(base); \ + movq %rbx, REG_OFF(KDIREG_RBX)(base); \ + movq %rbp, REG_OFF(KDIREG_RBP)(base); \ + movq %r10, REG_OFF(KDIREG_R10)(base); \ + movq %r11, REG_OFF(KDIREG_R11)(base); \ + movq %r12, REG_OFF(KDIREG_R12)(base); \ + movq %r13, REG_OFF(KDIREG_R13)(base); \ + movq %r14, REG_OFF(KDIREG_R14)(base); \ + movq %r15, REG_OFF(KDIREG_R15)(base); \ + movq %rbp, REG_OFF(KDIREG_SAVFP)(base); \ + movq REG_OFF(KDIREG_RIP)(base), %rax; \ + movq %rax, REG_OFF(KDIREG_SAVPC)(base); \ + clrq %rax; \ + movw %ds, %ax; \ + movq %rax, REG_OFF(KDIREG_DS)(base); \ + movw %es, %ax; \ + movq %rax, REG_OFF(KDIREG_ES)(base); \ + movw %fs, %ax; \ + movq %rax, REG_OFF(KDIREG_FS)(base); \ + movw %gs, %ax; \ + movq %rax, REG_OFF(KDIREG_GS)(base) + +#define KDI_RESTORE_REGS(base) \ + movq base, %rdi; \ + movq REG_OFF(KDIREG_ES)(%rdi), %rax; \ + movw %ax, %es; \ + movq REG_OFF(KDIREG_DS)(%rdi), %rax; \ + movw %ax, %ds; \ + movq REG_OFF(KDIREG_R15)(%rdi), %r15; \ + movq REG_OFF(KDIREG_R14)(%rdi), %r14; \ + movq REG_OFF(KDIREG_R13)(%rdi), %r13; \ + movq REG_OFF(KDIREG_R12)(%rdi), %r12; \ + movq REG_OFF(KDIREG_R11)(%rdi), %r11; \ + movq REG_OFF(KDIREG_R10)(%rdi), %r10; \ + movq REG_OFF(KDIREG_RBP)(%rdi), %rbp; \ + movq REG_OFF(KDIREG_RBX)(%rdi), %rbx; \ + movq REG_OFF(KDIREG_RAX)(%rdi), %rax; \ + movq REG_OFF(KDIREG_R9)(%rdi), %r9; \ + movq REG_OFF(KDIREG_R8)(%rdi), %r8; \ + movq REG_OFF(KDIREG_RCX)(%rdi), %rcx; \ + movq REG_OFF(KDIREG_RDX)(%rdi), %rdx; \ + movq REG_OFF(KDIREG_RSI)(%rdi), %rsi; \ + movq REG_OFF(KDIREG_RDI)(%rdi), %rdi + +/* + * Each cpusave buffer has an area set aside for a ring buffer of breadcrumbs. + * The following macros manage the buffer. + */ + +/* Advance the ring buffer */ +#define ADVANCE_CRUMB_POINTER(cpusave, tmp1, tmp2) \ + movq KRS_CURCRUMBIDX(cpusave), tmp1; \ + cmpq $[KDI_NCRUMBS - 1], tmp1; \ + jge 1f; \ + /* Advance the pointer and index */ \ + addq $1, tmp1; \ + movq tmp1, KRS_CURCRUMBIDX(cpusave); \ + movq KRS_CURCRUMB(cpusave), tmp1; \ + addq $KRM_SIZE, tmp1; \ + jmp 2f; \ +1: /* Reset the pointer and index */ \ + movq $0, KRS_CURCRUMBIDX(cpusave); \ + leaq KRS_CRUMBS(cpusave), tmp1; \ +2: movq tmp1, KRS_CURCRUMB(cpusave); \ + /* Clear the new crumb */ \ + movq $KDI_NCRUMBS, tmp2; \ +3: movq $0, -4(tmp1, tmp2, 4); \ + decq tmp2; \ + jnz 3b + +/* Set a value in the current breadcrumb buffer */ +#define ADD_CRUMB(cpusave, offset, value, tmp) \ + movq KRS_CURCRUMB(cpusave), tmp; \ + movq value, offset(tmp) + +#endif /* _ASM */ + +/* + * The main entry point for master CPUs. It also serves as the trap handler + * for all traps and interrupts taken during single-step. + */ +#if defined(__lint) +void +kdi_cmnint(void) +{ +} +#else /* __lint */ + + /* XXX implement me */ + ENTRY_NP(kdi_nmiint) + clrq %rcx + movq (%rcx), %rcx + SET_SIZE(kdi_nmiint) + + ENTRY_NP(kdi_cmnint) + ALTENTRY(kdi_master_entry) + + pushq %rax + CLI(%rax) + popq %rax + + /* Save current register state */ + subq $REG_OFF(KDIREG_TRAPNO), %rsp + KDI_SAVE_REGS(%rsp) + + /* + * Switch to the kernel's GSBASE. Neither GSBASE nor the ill-named + * KGSBASE can be trusted, as the kernel may or may not have already + * done a swapgs. All is not lost, as the kernel can divine the correct + * value for us. + */ + subq $10, %rsp + sgdt (%rsp) + movq 2(%rsp), %rdi /* gdt base now in %rdi */ + addq $10, %rsp + call kdi_gdt2gsbase /* returns kernel's GSBASE in %rax */ + + movq %rax, %rdx + shrq $32, %rdx + movl $MSR_AMD_GSBASE, %ecx + wrmsr + + GET_CPUSAVE_ADDR /* %rax = cpusave, %rbx = CPU ID */ + + ADVANCE_CRUMB_POINTER(%rax, %rcx, %rdx) + + ADD_CRUMB(%rax, KRM_CPU_STATE, $KDI_CPU_STATE_MASTER, %rdx) + + movq REG_OFF(KDIREG_RIP)(%rsp), %rcx + ADD_CRUMB(%rax, KRM_PC, %rcx, %rdx) + ADD_CRUMB(%rax, KRM_SP, %rsp, %rdx) + movq REG_OFF(KDIREG_TRAPNO)(%rsp), %rcx + ADD_CRUMB(%rax, KRM_TRAPNO, %rcx, %rdx) + + movq %rsp, %rbp + pushq %rax + + /* + * Were we in the debugger when we took the trap (i.e. was %esp in one + * of the debugger's memory ranges)? + */ + leaq kdi_memranges, %rcx + movl kdi_nmemranges, %edx +1: cmpq MR_BASE(%rcx), %rsp + jl 2f /* below this range -- try the next one */ + cmpq MR_LIM(%rcx), %rsp + jg 2f /* above this range -- try the next one */ + jmp 3f /* matched within this range */ + +2: decl %edx + jz kdi_save_common_state /* %rsp not within debugger memory */ + addq $MR_SIZE, %rcx + jmp 1b + +3: /* + * The master is still set. That should only happen if we hit a trap + * while running in the debugger. Note that it may be an intentional + * fault. kmdb_dpi_handle_fault will sort it all out. + */ + + movq REG_OFF(KDIREG_TRAPNO)(%rbp), %rdi + movq REG_OFF(KDIREG_RIP)(%rbp), %rsi + movq REG_OFF(KDIREG_RSP)(%rbp), %rdx + movq %rbx, %rcx /* cpuid */ + + call kdi_dvec_handle_fault + + /* + * If we're here, we ran into a debugger problem, and the user + * elected to solve it by having the debugger debug itself. The + * state we're about to save is that of the debugger when it took + * the fault. + */ + + jmp kdi_save_common_state + + SET_SIZE(kdi_master_entry) + SET_SIZE(kdi_cmnint) + +#endif /* __lint */ + +/* + * The cross-call handler for slave CPUs. + * + * The debugger is single-threaded, so only one CPU, called the master, may be + * running it at any given time. The other CPUs, known as slaves, spin in a + * busy loop until there's something for them to do. This is the entry point + * for the slaves - they'll be sent here in response to a cross-call sent by the + * master. + */ + +#if defined(__lint) +char kdi_slave_entry_patch; + +void +kdi_slave_entry(void) +{ +} +#else /* __lint */ + .globl kdi_slave_entry_patch; + + ENTRY_NP(kdi_slave_entry) + + /* kdi_msr_add_clrentry knows where this is */ +kdi_slave_entry_patch: + KDI_MSR_PATCH; + + /* + * Cross calls are implemented as function calls, so our stack currently + * looks like one you'd get from a zero-argument function call. That + * is, there's the return %rip at %rsp, and that's about it. We need + * to make it look like an interrupt stack. When we first save, we'll + * reverse the saved %ss and %rip, which we'll fix back up when we've + * freed up some general-purpose registers. We'll also need to fix up + * the saved %rsp. + */ + + pushq %rsp /* pushed value off by 8 */ + pushfq + CLI(%rax) + pushq $KCS_SEL + clrq %rax + movw %ss, %ax + pushq %rax /* rip should be here */ + pushq $-1 /* phony trap error code */ + pushq $-1 /* phony trap number */ + + subq $REG_OFF(KDIREG_TRAPNO), %rsp + KDI_SAVE_REGS(%rsp) + + movq REG_OFF(KDIREG_SS)(%rsp), %rax + xchgq REG_OFF(KDIREG_RIP)(%rsp), %rax + movq %rax, REG_OFF(KDIREG_SS)(%rsp) + + movq REG_OFF(KDIREG_RSP)(%rsp), %rax + addq $8, %rax + movq %rax, REG_OFF(KDIREG_RSP)(%rsp) + + /* + * We've saved all of the general-purpose registers, and have a stack + * that is irettable (after we strip down to the error code) + */ + + GET_CPUSAVE_ADDR /* %rax = cpusave, %rbx = CPU ID */ + + ADVANCE_CRUMB_POINTER(%rax, %rcx, %rdx) + + ADD_CRUMB(%rax, KRM_CPU_STATE, $KDI_CPU_STATE_SLAVE, %rdx) + + movq REG_OFF(KDIREG_RIP)(%rsp), %rcx + ADD_CRUMB(%rax, KRM_PC, %rcx, %rdx) + + pushq %rax + jmp kdi_save_common_state + + SET_SIZE(kdi_slave_entry) + +#endif /* __lint */ + +#if !defined(__lint) + + ENTRY_NP(kdi_save_common_state) + + /* + * The state of the world: + * + * The stack has a complete set of saved registers and segment + * selectors, arranged in the kdi_regs.h order. It also has a pointer + * to our cpusave area. + * + * We need to save, into the cpusave area, a pointer to these saved + * registers. After that, we save a few more registers, ready the + * machine for debugger entry, and enter the debugger. + */ + + popq %rax /* the cpusave area */ + movq %rsp, KRS_GREGS(%rax) /* save ptr to current saved regs */ + + SAVE_IDTGDT + + /* Save off %cr0, and clear write protect */ + movq %cr0, %rcx + movq %rcx, KRS_CR0(%rax) + andq $_BITNOT(CR0_WP), %rcx + movq %rcx, %cr0 + + /* Save the debug registers and disable any active watchpoints */ + + movq %rax, %r15 /* save cpusave area ptr */ + movl $7, %edi + call kdi_dreg_get + movq %rax, KRS_DRCTL(%r15) + + andq $_BITNOT(KDIREG_DRCTL_WPALLEN_MASK), %rax + movq %rax, %rsi + movl $7, %edi + call kdi_dreg_set + + movl $6, %edi + call kdi_dreg_get + movq %rax, KRS_DRSTAT(%r15) + + movl $0, %edi + call kdi_dreg_get + movq %rax, KRS_DROFF(0)(%r15) + + movl $1, %edi + call kdi_dreg_get + movq %rax, KRS_DROFF(1)(%r15) + + movl $2, %edi + call kdi_dreg_get + movq %rax, KRS_DROFF(2)(%r15) + + movl $3, %edi + call kdi_dreg_get + movq %rax, KRS_DROFF(3)(%r15) + + movq %r15, %rax /* restore cpu save area to rax */ + + /* + * Save any requested MSRs. + */ + movq KRS_MSR(%rax), %rcx + cmpq $0, %rcx + je no_msr + + pushq %rax /* rdmsr clobbers %eax */ + movq %rcx, %rbx + +1: + movl MSR_NUM(%rbx), %ecx + cmpl $0, %ecx + je msr_done + + movl MSR_TYPE(%rbx), %edx + cmpl $KDI_MSR_READ, %edx + jne msr_next + + rdmsr /* addr in %ecx, value into %edx:%eax */ + movl %eax, MSR_VAL(%rbx) + movl %edx, _CONST(MSR_VAL + 4)(%rbx) + +msr_next: + addq $MSR_SIZE, %rbx + jmp 1b + +msr_done: + popq %rax + +no_msr: + clrq %rbp /* stack traces should end here */ + + pushq %rax + movq %rax, %rdi /* cpusave */ + + call kdi_debugger_entry + + /* Pass cpusave and debugger return code for "call" to resume */ + popq %rdi + movq %rax, %rsi + + jmp kdi_resume + + SET_SIZE(kdi_save_common_state) + +#endif /* !__lint */ + +/* + * Given the address of the current CPU's cpusave area in %rax, the following + * macro restores the debugging state to said CPU. Restored state includes + * the debug registers from the global %dr variables, and debugging MSRs from + * the CPU save area. This code would be in a separate routine, but for the + * fact that some of the MSRs are jump-sensitive. As such, we need to minimize + * the number of jumps taken subsequent to the update of said MSRs. We can + * remove one jump (the ret) by using a macro instead of a function for the + * debugging state restoration code. + * + * Takes the cpusave area in %rdi as a parameter, clobbers %rax-%rdx + */ +#define KDI_RESTORE_DEBUGGING_STATE \ + pushq %rdi; \ + leaq kdi_drreg, %r15; \ + movl $7, %edi; \ + movq DR_CTL(%r15), %rsi; \ + call kdi_dreg_set; \ + \ + movl $6, %edi; \ + movq $KDIREG_DRSTAT_RESERVED, %rsi; \ + call kdi_dreg_set; \ + \ + movl $0, %edi; \ + movq DRADDR_OFF(0)(%r15), %rsi; \ + call kdi_dreg_set; \ + movl $1, %edi; \ + movq DRADDR_OFF(1)(%r15), %rsi; \ + call kdi_dreg_set; \ + movl $2, %edi; \ + movq DRADDR_OFF(2)(%r15), %rsi; \ + call kdi_dreg_set; \ + movl $3, %edi; \ + movq DRADDR_OFF(3)(%r15), %rsi; \ + call kdi_dreg_set; \ + popq %rdi; \ + \ + /* \ + * Write any requested MSRs. \ + */ \ + movq KRS_MSR(%rdi), %rbx; \ + cmpq $0, %rbx; \ + je 3f; \ +1: \ + movl MSR_NUM(%rbx), %ecx; \ + cmpl $0, %ecx; \ + je 3f; \ + \ + movl MSR_TYPE(%rbx), %edx; \ + cmpl $KDI_MSR_WRITE, %edx; \ + jne 2f; \ + \ + movq MSR_VALP(%rbx), %rdx; \ + movl 0(%rdx), %eax; \ + movl 4(%rdx), %edx; \ + wrmsr; \ +2: \ + addq $MSR_SIZE, %rbx; \ + jmp 1b; \ +3: \ + /* \ + * We must not branch after re-enabling LBR. If \ + * kdi_wsr_wrexit_msr is set, it contains the number \ + * of the MSR that controls LBR. kdi_wsr_wrexit_valp \ + * contains the value that is to be written to enable \ + * LBR. \ + */ \ + movl kdi_msr_wrexit_msr, %ecx; \ + cmpl $0, %ecx; \ + je 1f; \ + \ + movq kdi_msr_wrexit_valp, %rdx; \ + movl 0(%rdx), %eax; \ + movl 4(%rdx), %edx; \ + \ + wrmsr; \ +1: + +#if defined(__lint) +/*ARGSUSED*/ +void +kdi_cpu_debug_init(kdi_cpusave_t *save) +{ +} +#else /* __lint */ + + ENTRY_NP(kdi_cpu_debug_init) + pushq %rbp + movq %rsp, %rbp + + pushq %rbx /* macro will clobber %rbx */ + KDI_RESTORE_DEBUGGING_STATE + popq %rbx + + leave + ret + + SET_SIZE(kdi_cpu_debug_init) +#endif /* !__lint */ + +/* + * Resume the world. The code that calls kdi_resume has already + * decided whether or not to restore the IDT. + */ +#if defined(__lint) +void +kdi_resume(void) +{ +} +#else /* __lint */ + + ENTRY_NP(kdi_resume) + + /* cpusave in %rdi, debugger command in %rsi */ + + cmpq $KDI_RESUME_PASS_TO_KERNEL, %rsi + je kdi_pass_to_kernel + + /* + * Send this CPU back into the world + */ + movq KRS_CR0(%rdi), %rdx + movq %rdx, %cr0 + + KDI_RESTORE_DEBUGGING_STATE + + movq KRS_GREGS(%rdi), %rsp + KDI_RESTORE_REGS(%rsp) + addq $REG_OFF(KDIREG_RIP), %rsp /* Discard state, trapno, err */ + IRET + /*NOTREACHED*/ + SET_SIZE(kdi_resume) + +#endif /* __lint */ + +#if !defined(__lint) + + ENTRY_NP(kdi_pass_to_kernel) + + /* cpusave is still in %rdi */ + movq KRS_CR0(%rdi), %rdx + movq %rdx, %cr0 + + /* + * When we replaced the kernel's handlers in the IDT, we made note of + * the handlers being replaced, thus allowing us to pass traps directly + * to said handlers here. We won't have any registers available for use + * after we start popping, and we know we're single-threaded here, so + * we have to use a global to store the handler address. + */ + movq KRS_GREGS(%rdi), %rsp + movq REG_OFF(KDIREG_TRAPNO)(%rsp), %rdi + call kdi_kernel_trap2hdlr + movq %rax, kdi_kernel_handler + + /* + * The trap handler will expect the stack to be in trap order, with + * %rip being the last entry. Our stack is currently in kdi_regs.h + * order, so we'll need to pop (and restore) our way back down. + */ + KDI_RESTORE_REGS(%rsp) + addq $REG_OFF(KDIREG_RIP), %rsp /* Discard state, trapno, err */ + + jmp *%cs:kdi_kernel_handler + /*NOTREACHED*/ + + SET_SIZE(kdi_pass_to_kernel) + + /* + * Reboot the system. This routine is to be called only by the master + * CPU. + */ + ENTRY_NP(kdi_reboot) + + movl $AD_BOOT, %edi + movl $A_SHUTDOWN, %esi + call *psm_shutdownf + + /* + * psm_shutdown didn't work or it wasn't set, try pc_reset. + */ + call pc_reset + /*NOTREACHED*/ + + SET_SIZE(kdi_reboot) + +#endif /* !__lint */ diff --git a/usr/src/uts/intel/kdi/ia32/kdi_asm.s b/usr/src/uts/intel/kdi/ia32/kdi_asm.s new file mode 100644 index 0000000000..b8232ab58b --- /dev/null +++ b/usr/src/uts/intel/kdi/ia32/kdi_asm.s @@ -0,0 +1,692 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Debugger entry for both master and slave CPUs + */ + +#if defined(__lint) +#include <sys/types.h> +#endif + +#include <sys/segments.h> +#include <sys/asm_linkage.h> +#include <sys/controlregs.h> +#include <sys/x86_archext.h> +#include <sys/privregs.h> +#include <sys/machprivregs.h> +#include <sys/kdi_regs.h> +#include <sys/uadmin.h> +#include <sys/psw.h> + +#ifdef _ASM + +#include <kdi_assym.h> +#include <assym.h> + +/* clobbers %edx, %ecx, returns addr in %eax, cpu id in %ebx */ +#define GET_CPUSAVE_ADDR \ + movl %gs:CPU_ID, %ebx; \ + movl %ebx, %eax; \ + movl $KRS_SIZE, %ecx; \ + mull %ecx; \ + movl $kdi_cpusave, %edx; \ + /*CSTYLED*/ \ + addl (%edx), %eax + +/* + * Save copies of the IDT and GDT descriptors. Note that we only save the IDT + * and GDT if the IDT isn't ours, as we may be legitimately re-entering the + * debugger through the trap handler. We don't want to clobber the saved IDT + * in the process, as we'd end up resuming the world on our IDT. + */ +#define SAVE_IDTGDT \ + movl %gs:CPU_IDT, %edx; \ + cmpl $kdi_idt, %edx; \ + je 1f; \ + movl %edx, KRS_IDT(%eax); \ + movl %gs:CPU_GDT, %edx; \ + movl %edx, KRS_GDT(%eax); \ +1: + +/* + * Each cpusave buffer has an area set aside for a ring buffer of breadcrumbs. + * The following macros manage the buffer. + */ + +/* Advance the ring buffer */ +#define ADVANCE_CRUMB_POINTER(cpusave, tmp1, tmp2) \ + movl KRS_CURCRUMBIDX(cpusave), tmp1; \ + cmpl $[KDI_NCRUMBS - 1], tmp1; \ + jge 1f; \ + /* Advance the pointer and index */ \ + addl $1, tmp1; \ + movl tmp1, KRS_CURCRUMBIDX(cpusave); \ + movl KRS_CURCRUMB(cpusave), tmp1; \ + addl $KRM_SIZE, tmp1; \ + jmp 2f; \ +1: /* Reset the pointer and index */ \ + movw $0, KRS_CURCRUMBIDX(cpusave); \ + leal KRS_CRUMBS(cpusave), tmp1; \ +2: movl tmp1, KRS_CURCRUMB(cpusave); \ + /* Clear the new crumb */ \ + movl $KDI_NCRUMBS, tmp2; \ +3: movl $0, -4(tmp1, tmp2, 4); \ + decl tmp2; \ + jnz 3b + +/* Set a value in the current breadcrumb buffer */ +#define ADD_CRUMB(cpusave, offset, value, tmp) \ + movl KRS_CURCRUMB(cpusave), tmp; \ + movl value, offset(tmp) + +#endif /* _ASM */ + +/* + * The main entry point for master CPUs. It also serves as the trap handler + * for all traps and interrupts taken during single-step. + */ +#if defined(__lint) +void +kdi_cmnint(void) +{ +} +#else /* __lint */ + + /* XXX implement me */ + ENTRY_NP(kdi_nmiint) + clr %ecx + movl (%ecx), %ecx + SET_SIZE(kdi_nmiint) + + ENTRY_NP(kdi_cmnint) + ALTENTRY(kdi_master_entry) + + /* Save all registers and selectors */ + + pushal + pushl %ds + pushl %es + pushl %fs + pushl %gs + pushl %ss + + subl $8, %esp + movl %ebp, REG_OFF(KDIREG_SAVFP)(%esp) + movl REG_OFF(KDIREG_EIP)(%esp), %eax + movl %eax, REG_OFF(KDIREG_SAVPC)(%esp) + + /* + * If the kernel has started using its own selectors, we should too. + * Update our saved selectors if they haven't been updated already. + */ + movw %cs, %ax + cmpw $KCS_SEL, %ax + jne 1f /* The kernel hasn't switched yet */ + + movw $KDS_SEL, %ax + movw %ax, %ds + movw kdi_cs, %ax + cmpw $KCS_SEL, %ax + je 1f /* We already switched */ + + /* + * The kernel switched, but we haven't. Update our saved selectors + * to match the kernel's copies for use below. + */ + movl $KCS_SEL, kdi_cs + movl $KDS_SEL, kdi_ds + movl $KFS_SEL, kdi_fs + movl $KGS_SEL, kdi_gs + +1: + /* + * Set the selectors to a known state. If we come in from kmdb's IDT, + * we'll be on boot's %cs. This will cause GET_CPUSAVE_ADDR to return + * CPU 0's cpusave, regardless of which CPU we're on, and chaos will + * ensue. So, if we've got $KCSSEL in kdi_cs, switch to it. The other + * selectors are restored normally. + */ + movw %cs:kdi_cs, %ax + cmpw $KCS_SEL, %ax + jne 1f + ljmp $KCS_SEL, $1f +1: + movw %cs:kdi_ds, %ds + movw kdi_ds, %es + movw kdi_fs, %fs + movw kdi_gs, %gs + movw kdi_ds, %ss + + /* + * This has to come after we set %gs to the kernel descriptor. Since + * we've hijacked some IDT entries used in user-space such as the + * breakpoint handler, we can enter kdi_cmnint() with GDT_LWPGS used + * in %gs. On the hypervisor, CLI() needs GDT_GS to access the machcpu. + */ + CLI(%eax) + + GET_CPUSAVE_ADDR /* %eax = cpusave, %ebx = CPU ID */ + + ADVANCE_CRUMB_POINTER(%eax, %ecx, %edx) + + ADD_CRUMB(%eax, KRM_CPU_STATE, $KDI_CPU_STATE_MASTER, %edx) + + movl REG_OFF(KDIREG_EIP)(%esp), %ecx + ADD_CRUMB(%eax, KRM_PC, %ecx, %edx) + ADD_CRUMB(%eax, KRM_SP, %esp, %edx) + movl REG_OFF(KDIREG_TRAPNO)(%esp), %ecx + ADD_CRUMB(%eax, KRM_TRAPNO, %ecx, %edx) + + movl %esp, %ebp + pushl %eax + + /* + * Were we in the debugger when we took the trap (i.e. was %esp in one + * of the debugger's memory ranges)? + */ + leal kdi_memranges, %ecx + movl kdi_nmemranges, %edx +1: cmpl MR_BASE(%ecx), %esp + jl 2f /* below this range -- try the next one */ + cmpl MR_LIM(%ecx), %esp + jg 2f /* above this range -- try the next one */ + jmp 3f /* matched within this range */ + +2: decl %edx + jz kdi_save_common_state /* %esp not within debugger memory */ + addl $MR_SIZE, %ecx + jmp 1b + +3: /* + * %esp was within one of the debugger's memory ranges. This should + * only happen when we take a trap while running in the debugger. + * kmdb_dpi_handle_fault will determine whether or not it was an + * expected trap, and will take the appropriate action. + */ + + pushl %ebx /* cpuid */ + + movl REG_OFF(KDIREG_ESP)(%ebp), %ecx + addl $REG_OFF(KDIREG_EFLAGS - KDIREG_EAX), %ecx + pushl %ecx + + pushl REG_OFF(KDIREG_EIP)(%ebp) + pushl REG_OFF(KDIREG_TRAPNO)(%ebp) + + call kdi_dvec_handle_fault + addl $16, %esp + + /* + * If we're here, we ran into a debugger problem, and the user + * elected to solve it by having the debugger debug itself. The + * state we're about to save is that of the debugger when it took + * the fault. + */ + + jmp kdi_save_common_state + + SET_SIZE(kdi_master_entry) + SET_SIZE(kdi_cmnint) + +#endif /* __lint */ + +/* + * The cross-call handler for slave CPUs. + * + * The debugger is single-threaded, so only one CPU, called the master, may be + * running it at any given time. The other CPUs, known as slaves, spin in a + * busy loop until there's something for them to do. This is the entry point + * for the slaves - they'll be sent here in response to a cross-call sent by the + * master. + */ + +#if defined(__lint) +char kdi_slave_entry_patch; + +void +kdi_slave_entry(void) +{ +} +#else /* __lint */ + .globl kdi_slave_entry_patch; + + ENTRY_NP(kdi_slave_entry) + + /* kdi_msr_add_clrentry knows where this is */ +kdi_slave_entry_patch: + KDI_MSR_PATCH; + + /* + * Cross calls are implemented as function calls, so our stack + * currently looks like one you'd get from a zero-argument function + * call. There's an %eip at %esp, and that's about it. We want to + * make it look like the master CPU's stack. By doing this, we can + * use the same resume code for both master and slave. We need to + * make our stack look like a `struct regs' before we jump into the + * common save routine. + */ + + pushl %cs + pushfl + pushl $-1 /* A phony trap error code */ + pushl $-1 /* A phony trap number */ + pushal + pushl %ds + pushl %es + pushl %fs + pushl %gs + pushl %ss + + subl $8, %esp + movl %ebp, REG_OFF(KDIREG_SAVFP)(%esp) + movl REG_OFF(KDIREG_EIP)(%esp), %eax + movl %eax, REG_OFF(KDIREG_SAVPC)(%esp) + + /* + * Swap our saved EFLAGS and %eip. Each is where the other + * should be. + */ + movl REG_OFF(KDIREG_EFLAGS)(%esp), %eax + xchgl REG_OFF(KDIREG_EIP)(%esp), %eax + movl %eax, REG_OFF(KDIREG_EFLAGS)(%esp) + + /* + * Our stack now matches struct regs, and is irettable. We don't need + * to do anything special for the hypervisor w.r.t. PS_IE since we + * iret twice anyway; the second iret back to the hypervisor + * will re-enable interrupts. + */ + CLI(%eax) + + /* Load sanitized segment selectors */ + movw kdi_ds, %ds + movw kdi_ds, %es + movw kdi_fs, %fs + movw kdi_gs, %gs + movw kdi_ds, %ss + + GET_CPUSAVE_ADDR /* %eax = cpusave, %ebx = CPU ID */ + + ADVANCE_CRUMB_POINTER(%eax, %ecx, %edx) + + ADD_CRUMB(%eax, KRM_CPU_STATE, $KDI_CPU_STATE_SLAVE, %edx) + + movl REG_OFF(KDIREG_EIP)(%esp), %ecx + ADD_CRUMB(%eax, KRM_PC, %ecx, %edx) + + pushl %eax + jmp kdi_save_common_state + + SET_SIZE(kdi_slave_entry) + +#endif /* __lint */ + +#if !defined(__lint) + + ENTRY_NP(kdi_save_common_state) + + /* + * The state of the world: + * + * The stack has a complete set of saved registers and segment + * selectors, arranged in `struct regs' order (or vice-versa), up to + * and including EFLAGS. It also has a pointer to our cpusave area. + * + * We need to save a pointer to these saved registers. We also want + * to adjust the saved %esp - it should point just beyond the saved + * registers to the last frame of the thread we interrupted. Finally, + * we want to clear out bits 16-31 of the saved selectors, as the + * selector pushls don't automatically clear them. + */ + popl %eax /* the cpusave area */ + + movl %esp, KRS_GREGS(%eax) /* save ptr to current saved regs */ + + SAVE_IDTGDT + + addl $REG_OFF(KDIREG_EFLAGS - KDIREG_EAX), KDIREG_OFF(KDIREG_ESP)(%esp) + + andl $0xffff, KDIREG_OFF(KDIREG_SS)(%esp) + andl $0xffff, KDIREG_OFF(KDIREG_GS)(%esp) + andl $0xffff, KDIREG_OFF(KDIREG_FS)(%esp) + andl $0xffff, KDIREG_OFF(KDIREG_ES)(%esp) + andl $0xffff, KDIREG_OFF(KDIREG_DS)(%esp) + + /* Save off %cr0, and clear write protect */ + movl %cr0, %ecx + movl %ecx, KRS_CR0(%eax) + andl $_BITNOT(CR0_WP), %ecx + movl %ecx, %cr0 + pushl %edi + movl %eax, %edi + + /* Save the debug registers and disable any active watchpoints */ + pushl $7 + call kdi_dreg_get + addl $4, %esp + + movl %eax, KRS_DRCTL(%edi) + andl $_BITNOT(KDIREG_DRCTL_WPALLEN_MASK), %eax + + pushl %eax + pushl $7 + call kdi_dreg_set + addl $8, %esp + + pushl $6 + call kdi_dreg_get + addl $4, %esp + movl %eax, KRS_DRSTAT(%edi) + + pushl $0 + call kdi_dreg_get + addl $4, %esp + movl %eax, KRS_DROFF(0)(%edi) + + pushl $1 + call kdi_dreg_get + addl $4, %esp + movl %eax, KRS_DROFF(1)(%edi) + + pushl $2 + call kdi_dreg_get + addl $4, %esp + movl %eax, KRS_DROFF(2)(%edi) + + pushl $3 + call kdi_dreg_get + addl $4, %esp + movl %eax, KRS_DROFF(3)(%edi) + + movl %edi, %eax + popl %edi + + /* + * Save any requested MSRs. + */ + movl KRS_MSR(%eax), %ecx + cmpl $0, %ecx + je no_msr + + pushl %eax /* rdmsr clobbers %eax */ + movl %ecx, %ebx +1: + movl MSR_NUM(%ebx), %ecx + cmpl $0, %ecx + je msr_done + + movl MSR_TYPE(%ebx), %edx + cmpl $KDI_MSR_READ, %edx + jne msr_next + + rdmsr /* addr in %ecx, value into %edx:%eax */ + movl %eax, MSR_VAL(%ebx) + movl %edx, _CONST(MSR_VAL + 4)(%ebx) + +msr_next: + addl $MSR_SIZE, %ebx + jmp 1b + +msr_done: + popl %eax + +no_msr: + clr %ebp /* stack traces should end here */ + + pushl %eax + call kdi_debugger_entry + pushl %eax /* leave cpusave on the stack */ + + jmp kdi_resume + + SET_SIZE(kdi_save_common_state) + +#endif /* !__lint */ + +/* + * Given the address of the current CPU's cpusave area in %edi, the following + * macro restores the debugging state to said CPU. Restored state includes + * the debug registers from the global %dr variables, and debugging MSRs from + * the CPU save area. This code would be in a separate routine, but for the + * fact that some of the MSRs are jump-sensitive. As such, we need to minimize + * the number of jumps taken subsequent to the update of said MSRs. We can + * remove one jump (the ret) by using a macro instead of a function for the + * debugging state restoration code. + * + * Takes the cpusave area in %edi as a parameter, clobbers %eax-%edx + */ +#define KDI_RESTORE_DEBUGGING_STATE \ + leal kdi_drreg, %ebx; \ + \ + pushl DR_CTL(%ebx); \ + pushl $7; \ + call kdi_dreg_set; \ + addl $8, %esp; \ + \ + pushl $KDIREG_DRSTAT_RESERVED; \ + pushl $6; \ + call kdi_dreg_set; \ + addl $8, %esp; \ + \ + pushl DRADDR_OFF(0)(%ebx); \ + pushl $0; \ + call kdi_dreg_set; \ + addl $8, %esp; \ + \ + pushl DRADDR_OFF(1)(%ebx); \ + pushl $1; \ + call kdi_dreg_set; \ + addl $8, %esp; \ + \ + pushl DRADDR_OFF(2)(%ebx); \ + pushl $2; \ + call kdi_dreg_set; \ + addl $8, %esp; \ + \ + pushl DRADDR_OFF(3)(%ebx); \ + pushl $3; \ + call kdi_dreg_set; \ + addl $8, %esp; \ + \ + /* \ + * Write any requested MSRs. \ + */ \ + movl KRS_MSR(%edi), %ebx; \ + cmpl $0, %ebx; \ + je 3f; \ +1: \ + movl MSR_NUM(%ebx), %ecx; \ + cmpl $0, %ecx; \ + je 3f; \ + \ + movl MSR_TYPE(%ebx), %edx; \ + cmpl $KDI_MSR_WRITE, %edx; \ + jne 2f; \ + \ + movl MSR_VALP(%ebx), %edx; \ + movl 0(%edx), %eax; \ + movl 4(%edx), %edx; \ + wrmsr; \ +2: \ + addl $MSR_SIZE, %ebx; \ + jmp 1b; \ +3: \ + /* \ + * We must not branch after re-enabling LBR. If \ + * kdi_wsr_wrexit_msr is set, it contains the number \ + * of the MSR that controls LBR. kdi_wsr_wrexit_valp \ + * contains the value that is to be written to enable \ + * LBR. \ + */ \ + movl kdi_msr_wrexit_msr, %ecx; \ + cmpl $0, %ecx; \ + je 1f; \ + \ + movl kdi_msr_wrexit_valp, %edx; \ + movl 0(%edx), %eax; \ + movl 4(%edx), %edx; \ + \ + wrmsr; \ +1: + +#if defined(__lint) +/*ARGSUSED*/ +void +kdi_cpu_debug_init(kdi_cpusave_t *save) +{ +} +#else /* __lint */ + + ENTRY_NP(kdi_cpu_debug_init) + pushl %ebp + movl %esp, %ebp + + pushl %edi + pushl %ebx + + movl 8(%ebp), %edi + + KDI_RESTORE_DEBUGGING_STATE + + popl %ebx + popl %edi + leave + ret + + SET_SIZE(kdi_cpu_debug_init) +#endif /* !__lint */ + +/* + * Resume the world. The code that calls kdi_resume has already + * decided whether or not to restore the IDT. + */ +#if defined(__lint) +void +kdi_resume(void) +{ +} +#else /* __lint */ + + ENTRY_NP(kdi_resume) + popl %ebx /* command */ + popl %eax /* cpusave */ + + cmpl $KDI_RESUME_PASS_TO_KERNEL, %ebx + je kdi_pass_to_kernel + + /* + * Send this CPU back into the world + */ + + movl KRS_CR0(%eax), %edx + movl %edx, %cr0 + + pushl %edi + movl %eax, %edi + + KDI_RESTORE_DEBUGGING_STATE + + popl %edi + + addl $8, %esp /* Discard savfp and savpc */ + + popl %ss + popl %gs + popl %fs + popl %es + popl %ds + popal + + addl $8, %esp /* Discard TRAPNO and ERROR */ + + IRET + + SET_SIZE(kdi_resume) +#endif /* __lint */ + +#if !defined(__lint) + + ENTRY_NP(kdi_pass_to_kernel) + + /* cpusave is still in %eax */ + movl KRS_CR0(%eax), %edx + movl %edx, %cr0 + + /* + * When we replaced the kernel's handlers in the IDT, we made note of + * the handlers being replaced, thus allowing us to pass traps directly + * to said handlers here. We won't have any registers available for use + * after we start popping, and we know we're single-threaded here, so + * we have to use a global to store the handler address. + */ + pushl REG_OFF(KDIREG_TRAPNO)(%esp) + call kdi_kernel_trap2hdlr + addl $4, %esp + movl %eax, kdi_kernel_handler + + /* + * The trap handler will expect the stack to be in trap order, with + * %eip being the last entry. Our stack is currently in KDIREG_* + * order, so we'll need to pop (and restore) our way back down. + */ + addl $8, %esp /* Discard savfp and savpc */ + popl %ss + popl %gs + popl %fs + popl %es + popl %ds + popal + addl $8, %esp /* Discard trapno and err */ + + ljmp $KCS_SEL, $1f +1: jmp *%cs:kdi_kernel_handler + /*NOTREACHED*/ + + SET_SIZE(kdi_pass_to_kernel) + + /* + * Reboot the system. This routine is to be called only by the master + * CPU. + */ + ENTRY_NP(kdi_reboot) + + pushl $AD_BOOT + pushl $A_SHUTDOWN + call *psm_shutdownf + addl $8, %esp + + /* + * psm_shutdown didn't work or it wasn't set, try pc_reset. + */ + call pc_reset + /*NOTREACHED*/ + + SET_SIZE(kdi_reboot) + +#endif /* !__lint */ diff --git a/usr/src/uts/intel/kdi/kdi_idt.c b/usr/src/uts/intel/kdi/kdi_idt.c new file mode 100644 index 0000000000..5b170550d3 --- /dev/null +++ b/usr/src/uts/intel/kdi/kdi_idt.c @@ -0,0 +1,555 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Management of KMDB's IDT, which is installed upon KMDB activation. + * + * Debugger activation has two flavors, which cover the cases where KMDB is + * loaded at boot, and when it is loaded after boot. In brief, in both cases, + * the KDI needs to interpose upon several handlers in the IDT. When + * mod-loaded KMDB is deactivated, we undo the IDT interposition, restoring the + * handlers to what they were before we started. + * + * We also take over the entirety of IDT (except the double-fault handler) on + * the active CPU when we're in kmdb so we can handle things like page faults + * sensibly. + * + * Boot-loaded KMDB + * + * When we're first activated, we're running on boot's IDT. We need to be able + * to function in this world, so we'll install our handlers into boot's IDT. + * This is a little complicated: we're using the fake cpu_t set up by + * boot_kdi_tmpinit(), so we can't access cpu_idt directly. Instead, + * kdi_idt_write() notices that cpu_idt is NULL, and works around this problem. + * + * Later, when we're about to switch to the kernel's IDT, it'll call us via + * kdi_idt_sync(), allowing us to add our handlers to the new IDT. While + * boot-loaded KMDB can't be unloaded, we still need to save the descriptors we + * replace so we can pass traps back to the kernel as necessary. + * + * The last phase of boot-loaded KMDB activation occurs at non-boot CPU + * startup. We will be called on each non-boot CPU, thus allowing us to set up + * any watchpoints that may have been configured on the boot CPU and interpose + * on the given CPU's IDT. We don't save the interposed descriptors in this + * case -- see kdi_cpu_init() for details. + * + * Mod-loaded KMDB + * + * This style of activation is much simpler, as the CPUs are already running, + * and are using their own copy of the kernel's IDT. We simply interpose upon + * each CPU's IDT. We save the handlers we replace, both for deactivation and + * for passing traps back to the kernel. Note that for Xen's benefit, we need + * to xcall to the other CPUs to do this, since we need to actively set the + * trap entries in its virtual IDT from that vcpu's context rather than just + * modify the IDT table from the CPU running kdi_activate(). + */ + +#include <sys/types.h> +#include <sys/segments.h> +#include <sys/trap.h> +#include <sys/cpuvar.h> +#include <sys/reboot.h> +#include <sys/sunddi.h> +#include <sys/archsystm.h> +#include <sys/kdi_impl.h> +#include <sys/x_call.h> +#include <ia32/sys/psw.h> + +#define KDI_GATE_NVECS 3 + +#define KDI_IDT_NOSAVE 0 +#define KDI_IDT_SAVE 1 + +#define KDI_IDT_DTYPE_KERNEL 0 +#define KDI_IDT_DTYPE_BOOT 1 + +kdi_cpusave_t *kdi_cpusave; +int kdi_ncpusave; + +static kdi_main_t kdi_kmdb_main; + +kdi_drreg_t kdi_drreg; + +#ifndef __amd64 +/* Used to track the current set of valid kernel selectors. */ +uint32_t kdi_cs; +uint32_t kdi_ds; +uint32_t kdi_fs; +uint32_t kdi_gs; +#endif + +uint_t kdi_msr_wrexit_msr; +uint64_t *kdi_msr_wrexit_valp; + +uintptr_t kdi_kernel_handler; + +int kdi_trap_switch; + +#define KDI_MEMRANGES_MAX 2 + +kdi_memrange_t kdi_memranges[KDI_MEMRANGES_MAX]; +int kdi_nmemranges; + +typedef void idt_hdlr_f(void); + +extern idt_hdlr_f kdi_trap0, kdi_trap1, kdi_int2, kdi_trap3, kdi_trap4; +extern idt_hdlr_f kdi_trap5, kdi_trap6, kdi_trap7, kdi_trap9; +extern idt_hdlr_f kdi_traperr10, kdi_traperr11, kdi_traperr12; +extern idt_hdlr_f kdi_traperr13, kdi_traperr14, kdi_trap16, kdi_trap17; +extern idt_hdlr_f kdi_trap18, kdi_trap19, kdi_trap20, kdi_ivct32; +extern idt_hdlr_f kdi_invaltrap; +extern size_t kdi_ivct_size; +extern char kdi_slave_entry_patch; + +typedef struct kdi_gate_spec { + uint_t kgs_vec; + uint_t kgs_dpl; +} kdi_gate_spec_t; + +static const kdi_gate_spec_t kdi_gate_specs[KDI_GATE_NVECS] = { + { T_SGLSTP, SEL_KPL }, + { T_BPTFLT, SEL_UPL }, + { T_DBGENTR, SEL_KPL } +}; + +static gate_desc_t kdi_kgates[KDI_GATE_NVECS]; + +gate_desc_t kdi_idt[NIDT]; + +struct idt_description { + uint_t id_low; + uint_t id_high; + idt_hdlr_f *id_basehdlr; + size_t *id_incrp; +} idt_description[] = { + { T_ZERODIV, 0, kdi_trap0, NULL }, + { T_SGLSTP, 0, kdi_trap1, NULL }, + { T_NMIFLT, 0, kdi_int2, NULL }, + { T_BPTFLT, 0, kdi_trap3, NULL }, + { T_OVFLW, 0, kdi_trap4, NULL }, + { T_BOUNDFLT, 0, kdi_trap5, NULL }, + { T_ILLINST, 0, kdi_trap6, NULL }, + { T_NOEXTFLT, 0, kdi_trap7, NULL }, + { T_DBLFLT, 0, syserrtrap, NULL }, + { T_EXTOVRFLT, 0, kdi_trap9, NULL }, + { T_TSSFLT, 0, kdi_traperr10, NULL }, + { T_SEGFLT, 0, kdi_traperr11, NULL }, + { T_STKFLT, 0, kdi_traperr12, NULL }, + { T_GPFLT, 0, kdi_traperr13, NULL }, + { T_PGFLT, 0, kdi_traperr14, NULL }, + { 15, 0, kdi_invaltrap, NULL }, + { T_EXTERRFLT, 0, kdi_trap16, NULL }, + { T_ALIGNMENT, 0, kdi_trap17, NULL }, + { T_MCE, 0, kdi_trap18, NULL }, + { T_SIMDFPE, 0, kdi_trap19, NULL }, + { T_DBGENTR, 0, kdi_trap20, NULL }, + { 21, 31, kdi_invaltrap, NULL }, + { 32, 255, kdi_ivct32, &kdi_ivct_size }, + { 0, 0, NULL }, +}; + +void +kdi_idt_init(selector_t sel) +{ + struct idt_description *id; + int i; + + for (id = idt_description; id->id_basehdlr != NULL; id++) { + uint_t high = id->id_high != 0 ? id->id_high : id->id_low; + size_t incr = id->id_incrp != NULL ? *id->id_incrp : 0; + + for (i = id->id_low; i <= high; i++) { + caddr_t hdlr = (caddr_t)id->id_basehdlr + + incr * (i - id->id_low); + set_gatesegd(&kdi_idt[i], (void (*)())hdlr, sel, + SDT_SYSIGT, SEL_KPL); + } + } +} + +/* + * Patch caller-provided code into the debugger's IDT handlers. This code is + * used to save MSRs that must be saved before the first branch. All handlers + * are essentially the same, and end with a branch to kdi_cmnint. To save the + * MSR, we need to patch in before the branch. The handlers have the following + * structure: KDI_MSR_PATCHOFF bytes of code, KDI_MSR_PATCHSZ bytes of + * patchable space, followed by more code. + */ +void +kdi_idt_patch(caddr_t code, size_t sz) +{ + int i; + + ASSERT(sz <= KDI_MSR_PATCHSZ); + + for (i = 0; i < sizeof (kdi_idt) / sizeof (struct gate_desc); i++) { + gate_desc_t *gd; + uchar_t *patch; + + if (i == T_DBLFLT) + continue; /* uses kernel's handler */ + + gd = &kdi_idt[i]; + patch = (uchar_t *)GATESEG_GETOFFSET(gd) + KDI_MSR_PATCHOFF; + + /* + * We can't ASSERT that there's a nop here, because this may be + * a debugger restart. In that case, we're copying the new + * patch point over the old one. + */ + /* FIXME: dtrace fbt ... */ + bcopy(code, patch, sz); + + /* Fill the rest with nops to be sure */ + while (sz < KDI_MSR_PATCHSZ) + patch[sz++] = 0x90; /* nop */ + } +} + +static void +kdi_idt_gates_install(selector_t sel, int saveold) +{ + gate_desc_t gates[KDI_GATE_NVECS]; + int i; + + bzero(gates, sizeof (*gates)); + + for (i = 0; i < KDI_GATE_NVECS; i++) { + const kdi_gate_spec_t *gs = &kdi_gate_specs[i]; + uintptr_t func = GATESEG_GETOFFSET(&kdi_idt[gs->kgs_vec]); + set_gatesegd(&gates[i], (void (*)())func, sel, SDT_SYSIGT, + gs->kgs_dpl); + } + + for (i = 0; i < KDI_GATE_NVECS; i++) { + uint_t vec = kdi_gate_specs[i].kgs_vec; + + if (saveold) + kdi_kgates[i] = CPU->cpu_m.mcpu_idt[vec]; + + kdi_idt_write(&gates[i], vec); + } +} + +static void +kdi_idt_gates_restore(void) +{ + int i; + + for (i = 0; i < KDI_GATE_NVECS; i++) + kdi_idt_write(&kdi_kgates[i], kdi_gate_specs[i].kgs_vec); +} + +/* + * Used by the code which passes traps back to the kernel to retrieve the + * address of the kernel's handler for a given trap. We get this address + * from the descriptor save area, which we populated when we loaded the + * debugger (mod-loaded) or initialized the kernel's IDT (boot-loaded). + */ +uintptr_t +kdi_kernel_trap2hdlr(int vec) +{ + int i; + + for (i = 0; i < KDI_GATE_NVECS; i++) { + if (kdi_gate_specs[i].kgs_vec == vec) + return (GATESEG_GETOFFSET(&kdi_kgates[i])); + } + + return (NULL); +} + +/* + * Called when we switch to the kernel's IDT. We need to interpose on the + * kernel's IDT entries and stop using KMDBCODE_SEL. + */ +void +kdi_idt_sync(void) +{ + kdi_idt_init(KCS_SEL); + kdi_idt_gates_install(KCS_SEL, KDI_IDT_SAVE); +} + +/* + * On some processors, we'll need to clear a certain MSR before proceeding into + * the debugger. Complicating matters, this MSR must be cleared before we take + * any branches. We have patch points in every trap handler, which will cover + * all entry paths for master CPUs. We also have a patch point in the slave + * entry code. + */ +static void +kdi_msr_add_clrentry(uint_t msr) +{ +#ifdef __amd64 + uchar_t code[] = { + 0x51, 0x50, 0x52, /* pushq %rcx, %rax, %rdx */ + 0xb9, 0x00, 0x00, 0x00, 0x00, /* movl $MSRNUM, %ecx */ + 0x31, 0xc0, /* clr %eax */ + 0x31, 0xd2, /* clr %edx */ + 0x0f, 0x30, /* wrmsr */ + 0x5a, 0x58, 0x59 /* popq %rdx, %rax, %rcx */ + }; + uchar_t *patch = &code[4]; +#else + uchar_t code[] = { + 0x60, /* pushal */ + 0xb9, 0x00, 0x00, 0x00, 0x00, /* movl $MSRNUM, %ecx */ + 0x31, 0xc0, /* clr %eax */ + 0x31, 0xd2, /* clr %edx */ + 0x0f, 0x30, /* wrmsr */ + 0x61 /* popal */ + }; + uchar_t *patch = &code[2]; +#endif + + bcopy(&msr, patch, sizeof (uint32_t)); + + kdi_idt_patch((caddr_t)code, sizeof (code)); + + bcopy(code, &kdi_slave_entry_patch, sizeof (code)); +} + +static void +kdi_msr_add_wrexit(uint_t msr, uint64_t *valp) +{ + kdi_msr_wrexit_msr = msr; + kdi_msr_wrexit_valp = valp; +} + +void +kdi_set_debug_msrs(kdi_msr_t *msrs) +{ + int nmsrs, i; + + ASSERT(kdi_cpusave[0].krs_msr == NULL); + + /* Look in CPU0's MSRs for any special MSRs. */ + for (nmsrs = 0; msrs[nmsrs].msr_num != 0; nmsrs++) { + switch (msrs[nmsrs].msr_type) { + case KDI_MSR_CLEARENTRY: + kdi_msr_add_clrentry(msrs[nmsrs].msr_num); + break; + + case KDI_MSR_WRITEDELAY: + kdi_msr_add_wrexit(msrs[nmsrs].msr_num, + msrs[nmsrs].kdi_msr_valp); + break; + } + } + + nmsrs++; + + for (i = 0; i < kdi_ncpusave; i++) + kdi_cpusave[i].krs_msr = &msrs[nmsrs * i]; +} + +void +kdi_update_drreg(kdi_drreg_t *drreg) +{ + kdi_drreg = *drreg; +} + +void +kdi_memrange_add(caddr_t base, size_t len) +{ + kdi_memrange_t *mr = &kdi_memranges[kdi_nmemranges]; + + ASSERT(kdi_nmemranges != KDI_MEMRANGES_MAX); + + mr->mr_base = base; + mr->mr_lim = base + len - 1; + kdi_nmemranges++; +} + +void +kdi_idt_switch(kdi_cpusave_t *cpusave) +{ + if (cpusave == NULL) + kdi_idtr_set(kdi_idt, sizeof (kdi_idt) - 1); + else + kdi_idtr_set(cpusave->krs_idt, sizeof (idt0) - 1); +} + +/* + * Activation for CPUs other than the boot CPU, called from that CPU's + * mp_startup(). We saved the kernel's descriptors when we initialized the + * boot CPU, so we don't want to do it again. Saving the handlers from this + * CPU's IDT would actually be dangerous with the CPU initialization method in + * use at the time of this writing. With that method, the startup code creates + * the IDTs for slave CPUs by copying the one used by the boot CPU, which has + * already been interposed upon by KMDB. Were we to interpose again, we'd + * replace the kernel's descriptors with our own in the save area. By not + * saving, but still overwriting, we'll work in the current world, and in any + * future world where the IDT is generated from scratch. + */ +void +kdi_cpu_init(void) +{ + kdi_idt_gates_install(KCS_SEL, KDI_IDT_NOSAVE); + /* Load the debug registers and MSRs */ + kdi_cpu_debug_init(&kdi_cpusave[CPU->cpu_id]); +} + +/* + * Activation for all CPUs for mod-loaded kmdb, i.e. a kmdb that wasn't + * loaded at boot. + */ +static int +kdi_cpu_activate(void) +{ + kdi_idt_gates_install(KCS_SEL, KDI_IDT_SAVE); + return (0); +} + +void +kdi_activate(kdi_main_t main, kdi_cpusave_t *cpusave, uint_t ncpusave) +{ + int i; + cpuset_t cpuset; + + CPUSET_ALL(cpuset); + + kdi_cpusave = cpusave; + kdi_ncpusave = ncpusave; + + kdi_kmdb_main = main; + + for (i = 0; i < kdi_ncpusave; i++) { + kdi_cpusave[i].krs_cpu_id = i; + + kdi_cpusave[i].krs_curcrumb = + &kdi_cpusave[i].krs_crumbs[KDI_NCRUMBS - 1]; + kdi_cpusave[i].krs_curcrumbidx = KDI_NCRUMBS - 1; + } + + if (boothowto & RB_KMDB) + kdi_idt_init(KMDBCODE_SEL); + else + kdi_idt_init(KCS_SEL); + + /* The initial selector set. Updated by the debugger-entry code */ +#ifndef __amd64 + kdi_cs = B32CODE_SEL; + kdi_ds = kdi_fs = kdi_gs = B32DATA_SEL; +#endif + + kdi_memranges[0].mr_base = kdi_segdebugbase; + kdi_memranges[0].mr_lim = kdi_segdebugbase + kdi_segdebugsize - 1; + kdi_nmemranges = 1; + + kdi_drreg.dr_ctl = KDIREG_DRCTL_RESERVED; + kdi_drreg.dr_stat = KDIREG_DRSTAT_RESERVED; + + kdi_msr_wrexit_msr = 0; + kdi_msr_wrexit_valp = NULL; + + if (boothowto & RB_KMDB) { + kdi_idt_gates_install(KMDBCODE_SEL, KDI_IDT_NOSAVE); + } else { + xc_call(0, 0, 0, X_CALL_HIPRI, cpuset, + (xc_func_t)kdi_cpu_activate); + } +} + +static int +kdi_cpu_deactivate(void) +{ + kdi_idt_gates_restore(); + return (0); +} + +void +kdi_deactivate(void) +{ + cpuset_t cpuset; + CPUSET_ALL(cpuset); + + xc_call(0, 0, 0, X_CALL_HIPRI, cpuset, (xc_func_t)kdi_cpu_deactivate); + kdi_nmemranges = 0; +} + +/* + * We receive all breakpoints and single step traps. Some of them, + * including those from userland and those induced by DTrace providers, + * are intended for the kernel, and must be processed there. We adopt + * this ours-until-proven-otherwise position due to the painful + * consequences of sending the kernel an unexpected breakpoint or + * single step. Unless someone can prove to us that the kernel is + * prepared to handle the trap, we'll assume there's a problem and will + * give the user a chance to debug it. + */ +static int +kdi_trap_pass(kdi_cpusave_t *cpusave) +{ + greg_t tt = cpusave->krs_gregs[KDIREG_TRAPNO]; + greg_t pc = cpusave->krs_gregs[KDIREG_PC]; + greg_t cs = cpusave->krs_gregs[KDIREG_CS]; + + if (USERMODE(cs)) + return (1); + + if (tt != T_BPTFLT && tt != T_SGLSTP) + return (0); + + if (tt == T_BPTFLT && kdi_dtrace_get_state() == + KDI_DTSTATE_DTRACE_ACTIVE) + return (1); + + /* + * See the comments in the kernel's T_SGLSTP handler for why we need to + * do this. + */ + if (tt == T_SGLSTP && + pc == (greg_t)sys_sysenter || pc == (greg_t)brand_sys_sysenter) + return (1); + + return (0); +} + +/* + * State has been saved, and all CPUs are on the CPU-specific stacks. All + * CPUs enter here, and head off into the debugger proper. + */ +int +kdi_debugger_entry(kdi_cpusave_t *cpusave) +{ + if (kdi_trap_pass(cpusave)) { + cpusave->krs_cpu_state = KDI_CPU_STATE_NONE; + return (KDI_RESUME_PASS_TO_KERNEL); + } + + /* + * BPTFLT gives us control with %eip set to the instruction *after* + * the int 3. Back it off, so we're looking at the instruction that + * triggered the fault. + */ + if (cpusave->krs_gregs[KDIREG_TRAPNO] == T_BPTFLT) + cpusave->krs_gregs[KDIREG_PC]--; + + kdi_kmdb_main(cpusave); + return (KDI_RESUME); +} diff --git a/usr/src/cmd/mdb/intel/kmdb/kaif_idthdl.s b/usr/src/uts/intel/kdi/kdi_idthdl.s index 45fdba6c78..0d2e31322b 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kaif_idthdl.s +++ b/usr/src/uts/intel/kdi/kdi_idthdl.s @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,22 +19,22 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /* - * Companion to kaif_idt.c - the implementation of the trap and interrupt + * Companion to kdi_idt.c - the implementation of the trap and interrupt * handlers. For the most part, these handlers do the same thing - they - * push a trap number onto the stack, followed by a jump to kaif_cmnint. + * push a trap number onto the stack, followed by a jump to kdi_cmnint. * Each trap and interrupt has its own handler because each one pushes a * different number. */ #include <sys/asm_linkage.h> -#include <kmdb/kaif_asmutil.h> +#include <sys/kdi_regs.h> /* Nothing in this file is of interest to lint. */ #if !defined(__lint) @@ -49,88 +48,74 @@ /* * We need the .align in ENTRY_NP (defined to be ASM_ENTRY_ALIGN) to match our - * manual .align (KAIF_MSR_PATCHOFF) in order to ensure that the space reserved - * at the beginning of the handler for code is exactly KAIF_MSR_PATCHOFF bytes + * manual .align (KDI_MSR_PATCHOFF) in order to ensure that the space reserved + * at the beginning of the handler for code is exactly KDI_MSR_PATCHOFF bytes * long. Note that the #error below isn't supported by the preprocessor invoked * by as(1), and won't stop the build, but it'll emit a noticeable error message * which won't escape the filters. */ -#if ASM_ENTRY_ALIGN != KAIF_MSR_PATCHOFF -#error "ASM_ENTRY_ALIGN != KAIF_MSR_PATCHOFF" +#if ASM_ENTRY_ALIGN != KDI_MSR_PATCHOFF +#error "ASM_ENTRY_ALIGN != KDI_MSR_PATCHOFF" this won't assemble #endif /* - * kaif_idt_patch will, on certain processors, replace the patch points below - * with MSR-clearing code. kaif_id_patch has intimate knowledge of the size of + * kdi_idt_patch will, on certain processors, replace the patch points below + * with MSR-clearing code. kdi_id_patch has intimate knowledge of the size of * the nop hole, as well as the structure of the handlers. Do not change - * anything here without also changing kaif_idt_patch. + * anything here without also changing kdi_idt_patch. */ /* * Generic trap and interrupt handlers. */ -#if defined(__amd64) - -#define TRAP_NOERR(trapno) \ - pushq $trapno - -#define TRAP_ERR(trapno) \ - pushq $0; \ - pushq $trapno - -#else /* __i386 */ - -#define TRAP_NOERR(trapno) \ - pushl $trapno - -#define TRAP_ERR(trapno) \ - pushl $0; \ - pushl $trapno - -#endif +#define TRAP_NOERR(trapno) \ + push $trapno +#define TRAP_ERR(trapno) \ + push $0; \ + push $trapno #define MKIVCT(n) \ - ENTRY_NP(kaif_ivct/**/n/**/); \ + ENTRY_NP(kdi_ivct/**/n/**/); \ TRAP_ERR(n); \ - .align KAIF_MSR_PATCHOFF; \ - KAIF_MSR_PATCH; \ - jmp kaif_cmnint; \ - SET_SIZE(kaif_ivct/**/n/**/) + .align KDI_MSR_PATCHOFF; \ + KDI_MSR_PATCH; \ + jmp kdi_cmnint; \ + SET_SIZE(kdi_ivct/**/n/**/) #define MKTRAPHDLR(n) \ - ENTRY_NP(kaif_trap/**/n); \ + ENTRY_NP(kdi_trap/**/n); \ TRAP_ERR(n); \ - .align KAIF_MSR_PATCHOFF; \ - KAIF_MSR_PATCH; \ - jmp kaif_cmnint; \ - SET_SIZE(kaif_trap/**/n/**/) + .align KDI_MSR_PATCHOFF; \ + KDI_MSR_PATCH; \ + jmp kdi_cmnint; \ + SET_SIZE(kdi_trap/**/n/**/) #define MKTRAPERRHDLR(n) \ - ENTRY_NP(kaif_traperr/**/n); \ + ENTRY_NP(kdi_traperr/**/n); \ TRAP_NOERR(n); \ - .align KAIF_MSR_PATCHOFF; \ - KAIF_MSR_PATCH; \ - jmp kaif_cmnint; \ - SET_SIZE(kaif_traperr/**/n) + .align KDI_MSR_PATCHOFF; \ + KDI_MSR_PATCH; \ + jmp kdi_cmnint; \ + SET_SIZE(kdi_traperr/**/n) #define MKNMIHDLR \ - ENTRY_NP(kaif_int2); \ + ENTRY_NP(kdi_int2); \ TRAP_NOERR(2); \ - .align KAIF_MSR_PATCHOFF; \ - KAIF_MSR_PATCH; \ - jmp kaif_nmiint; \ - SET_SIZE(kaif_int2) + .align KDI_MSR_PATCHOFF; \ + KDI_MSR_PATCH; \ + jmp kdi_nmiint; \ + SET_SIZE(kdi_int2) #define MKINVALHDLR \ - ENTRY_NP(kaif_invaltrap); \ + ENTRY_NP(kdi_invaltrap); \ TRAP_NOERR(255); \ - .align KAIF_MSR_PATCHOFF; \ - KAIF_MSR_PATCH; \ - jmp kaif_cmnint; \ - SET_SIZE(kaif_invaltrap) + .align KDI_MSR_PATCHOFF; \ + KDI_MSR_PATCH; \ + jmp kdi_cmnint; \ + SET_SIZE(kdi_invaltrap) /* * The handlers themselves @@ -160,12 +145,12 @@ this won't assemble MKTRAPERRHDLR(13) MKTRAPERRHDLR(14) - .globl kaif_ivct_size -kaif_ivct_size: - .NWORD [kaif_ivct33-kaif_ivct32] + .globl kdi_ivct_size +kdi_ivct_size: + .NWORD [kdi_ivct33-kdi_ivct32] /* 10 billion and one interrupt handlers */ -kaif_ivct_base: +kdi_ivct_base: MKIVCT(32); MKIVCT(33); MKIVCT(34); MKIVCT(35); MKIVCT(36); MKIVCT(37); MKIVCT(38); MKIVCT(39); MKIVCT(40); MKIVCT(41); MKIVCT(42); MKIVCT(43); diff --git a/usr/src/cmd/mdb/intel/kmdb/kaif_off.in b/usr/src/uts/intel/kdi/kdi_offsets.in index ed1a65605b..80c0c24334 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kaif_off.in +++ b/usr/src/uts/intel/kdi/kdi_offsets.in @@ -1,13 +1,12 @@ \ -\ Copyright 2005 Sun Microsystems, Inc. All rights reserved. +\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. \ Use is subject to license terms. \ \ CDDL HEADER START \ \ The contents of this file are subject to the terms of the -\ Common Development and Distribution License, Version 1.0 only -\ (the "License"). You may not use this file except in compliance -\ with the License. +\ Common Development and Distribution License (the "License"). +\ You may not use this file except in compliance with the License. \ \ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE \ or http://www.opensolaris.org/os/licensing. @@ -26,46 +25,41 @@ \ \ CPU-save structure offsets for use in assembly code. \ -\ Keep in sync with kaif_regs.h +\ Keep in sync with kdi_state.h \ #include <sys/cpuvar.h> #include <sys/kdi_impl.h> -#include <kmdb/kaif.h> -#include <kmdb/kaif_regs.h> -#include <mdb/mdb.h> - -kaif_memrange_t MR_SIZE +kdi_memrange_t MR_SIZE mr_base mr_lim -kaif_crumb_t KRM_SIZE +kdi_crumb_t KRM_SIZE krm_cpu_state krm_pc krm_sp krm_trapno krm_flag -kaif_drreg_t +kdi_drreg_t dr_ctl dr_stat dr_addr -kmdb_msr_t MSR_SIZE +kdi_msr_t MSR_SIZE msr_num msr_type _u._msr_valp MSR_VALP _u._msr_val MSR_VAL -kaif_cpusave_t KRS_SIZE +kdi_cpusave_t KRS_SIZE krs_gregs krs_dr krs_dr.dr_ctl KRS_DRCTL krs_dr.dr_stat KRS_DRSTAT - krs_gdtr - krs_idtr - krs_tmpdesc + krs_gdt + krs_idt krs_cr0 krs_msr krs_cpu_state @@ -76,15 +70,7 @@ kaif_cpusave_t KRS_SIZE cpu cpu_id -#if defined(__amd64) -mdb_t - m_kdi MDB_KDI - -kdi_t - kdi_mach.mkdi_gdt2gsbase MKDI_GDT2GSBASE -#endif - -kreg_t KREG_SIZE +greg_t KREG_SIZE #if defined(__amd64) \#define REG_SHIFT 3 @@ -96,4 +82,4 @@ kreg_t KREG_SIZE \#define DRADDR_OFF(num) _CONST(DRADDR_IDX(num) + DR_ADDR) \#define KRS_DROFF(num) _CONST(DRADDR_OFF(num) + KRS_DR) \#define REG_OFF(reg) _CONST(_CONST(reg) << REG_SHIFT) -\#define KREG_OFF(reg) _CONST(_MUL(KREG_SIZE, reg) + KRS_GREGS) +\#define KDIREG_OFF(reg) _CONST(_MUL(KREG_SIZE, reg) + KRS_GREGS) diff --git a/usr/src/uts/intel/krtld/Makefile b/usr/src/uts/intel/krtld/Makefile deleted file mode 100644 index 9b88eaad0a..0000000000 --- a/usr/src/uts/intel/krtld/Makefile +++ /dev/null @@ -1,150 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# kernel linker/loader makefile. -# -# x86 architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = krtld -OBJECTS = $(KRTLD_BOOT_OBJS:%=$(OBJS_DIR)/%) \ - $(KRTLD_OBJS:%=$(OBJS_DIR)/%) - -LINTS = $(KRTLD_BOOT_OBJS:%.o=$(LINTS_DIR)/%.ln) \ - $(KRTLD_OBJS:%.o=$(LINTS_DIR)/%.ln) -PICS = $(KRTLD_BOOT_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE) - -INC_PATH_32 = -I$(UTSBASE)/common/krtld -I../ia32/krtld -I$(COMMONBASE) -INC_PATH_64 = -I$(UTSBASE)/common/krtld -I../amd64/krtld -I$(COMMONBASE) -INC_PATH += $(INC_PATH_$(CLASS)) - -MODSUFFIX_32 = -MODSUFFIX_64 = -DMODDIR_SUFFIX=\"amd64\" -MODSUFFIX = $(MODSUFFIX_$(CLASS)) - -# -# Include common rules. -# -include $(UTSBASE)/intel/Makefile.intel - -# -# Define targets -# -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Overrides. -# -CFLAGS += -Wu,-no_got_reloc - -KRTLD_CPPFLAGS_32 = -DELF_TARGET_386 -D_KRTLD -KRTLD_CPPFLAGS_64 = -DELF_TARGET_AMD64 -D_KRTLD -CPPFLAGS += $(KRTLD_CPPFLAGS_$(CLASS)) $(MODSUFFIX) - -MAPFILE = $(UTSBASE)/common/krtld/mapfile -LDFLAGS = -e _kobj_boot -M$(MAPFILE) -Breduce -znoversion -zverbose - -# krtld uses a mapfile during the link to hide some symbols, thus changing -# their scope from global to local. This will fool ctfmerge (it won't record -# the changed symbols) unless we tell it to use fuzzy matching. -CTFMRGFLAGS = -f - -PIC_CFLAGS_32 = -K pic -PIC_CFLAGS_64 = -K pic -_gcc=-mcmodel=small -$(PICS) := CFLAGS += $(PIC_CFLAGS_$(CLASS)) - -# -# krtld has its own private copies of these functions and objects -# -$(OBJECTS) $(LINTS) := CPPFLAGS += -Dstrcmp=$(MODULE)_strcmp -$(OBJECTS) $(LINTS) := CPPFLAGS += -Dstrncmp=$(MODULE)_strncmp -$(OBJECTS) $(LINTS) := CPPFLAGS += -Dstrlen=$(MODULE)_strlen -$(OBJECTS) $(LINTS) := CPPFLAGS += -Dstrcpy=$(MODULE)_strcpy -$(OBJECTS) $(LINTS) := CPPFLAGS += -Dstrncpy=$(MODULE)_strncpy -$(OBJECTS) $(LINTS) := CPPFLAGS += -Dstrcat=$(MODULE)_strcat -$(OBJECTS) $(LINTS) := CPPFLAGS += -Dstrlcat=$(MODULE)_strlcat -$(OBJECTS) $(LINTS) := CPPFLAGS += -Dstrchr=$(MODULE)_strchr -$(OBJECTS) $(LINTS) := CPPFLAGS += -Dbzero=$(MODULE)_bzero -$(OBJECTS) $(LINTS) := CPPFLAGS += -Dbcopy=$(MODULE)_bcopy - -# -# krtld has variant targets, depending on what the kernel instruction -# set actually is -# -MAKEFILE_RULES_32 = $(UTSBASE)/intel/ia32/Makefile.rules -MAKEFILE_RULES_64 = $(UTSBASE)/intel/amd64/Makefile.rules -include $(MAKEFILE_RULES_$(CLASS)) - -# -# For now, disable these lint checks; maintainers should endeavor -# to investigate and remove these for maximum lint coverage. -# Please do not carry these forward to new Makefiles. -# -LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN -LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW -LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV -LINTTAGS += -erroff=E_SUPPRESSION_DIRECTIVE_UNUSED -LINTTAGS += -erroff=E_SUSPICIOUS_COMPARISON -LINTTAGS += -erroff=E_STATIC_UNUSED - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -$(BINARY): $(MAPFILE) - -# -# Include common targets. -# -include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/logi/Makefile b/usr/src/uts/intel/logi/Makefile index cb9c34be1e..e50b94600f 100644 --- a/usr/src/uts/i86pc/logi/Makefile +++ b/usr/src/uts/intel/logi/Makefile @@ -19,9 +19,9 @@ # CDDL HEADER END # # -# uts/i86pc/logi/Makefile +# uts/intel/logi/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -29,7 +29,7 @@ # This makefile drives the production of the logi driver # kernel module. # -# i86pc architecture dependent +# intel architecture dependent # # @@ -43,12 +43,12 @@ UTSBASE = ../.. MODULE = logi OBJECTS = $(LOGI_OBJS:%=$(OBJS_DIR)/%) LINTS = $(LOGI_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -91,4 +91,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/mscsi/Makefile b/usr/src/uts/intel/mscsi/Makefile index 04b976bb6b..312ae3a621 100644 --- a/usr/src/uts/i86pc/mscsi/Makefile +++ b/usr/src/uts/intel/mscsi/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,9 +19,9 @@ # CDDL HEADER END # # -# uts/i86pc/mscsi/Makefile +# uts/intel/mscsi/Makefile # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -30,7 +29,7 @@ # This makefile drives the production of the mscsi # bus nexus driver kernel module. # -# i86pc architecture dependent +# intel architecture dependent # # @@ -44,13 +43,13 @@ UTSBASE = ../.. MODULE = mscsi OBJECTS = $(MSCSI_OBJS:%=$(OBJS_DIR)/%) LINTS = $(MSCSI_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/i86pc/io +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) +CONF_SRCDIR = $(UTSBASE)/intel/io # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -94,4 +93,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/msm/Makefile b/usr/src/uts/intel/msm/Makefile index 0c00a0b06f..b02a39c5cb 100644 --- a/usr/src/uts/i86pc/msm/Makefile +++ b/usr/src/uts/intel/msm/Makefile @@ -19,9 +19,9 @@ # CDDL HEADER END # # -# uts/i86pc/msmouse/Makefile +# uts/intel/msmouse/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -29,7 +29,7 @@ # This makefile drives the production of the msmouse driver # kernel module. # -# i86pc architecture dependent +# intel architecture dependent # # @@ -43,12 +43,12 @@ UTSBASE = ../.. MODULE = msm OBJECTS = $(MSMOUSE_OBJS:%=$(OBJS_DIR)/%) LINTS = $(MSMOUSE_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -94,4 +94,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/intel/os/arch_kdi.c b/usr/src/uts/intel/os/arch_kdi.c new file mode 100644 index 0000000000..abc2dfa599 --- /dev/null +++ b/usr/src/uts/intel/os/arch_kdi.c @@ -0,0 +1,169 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Kernel/Debugger Interface (KDI) routines. Called during debugger under + * various system states (boot, while running, while the debugger has control). + * Functions intended for use while the debugger has control may not grab any + * locks or perform any functions that assume the availability of other system + * services. + */ + +#include <sys/systm.h> +#include <sys/x86_archext.h> +#include <sys/kdi_impl.h> +#include <sys/smp_impldefs.h> +#include <sys/psm_types.h> +#include <sys/segments.h> +#include <sys/archsystm.h> +#include <sys/controlregs.h> +#include <sys/trap.h> +#include <sys/kobj.h> +#include <sys/kobj_impl.h> + +static void +kdi_system_claim(void) +{ + psm_notifyf(PSM_DEBUG_ENTER); +} + +static void +kdi_system_release(void) +{ + psm_notifyf(PSM_DEBUG_EXIT); +} + +static cpu_t * +kdi_gdt2cpu(uintptr_t gdtbase) +{ + cpu_t *cp = cpu_list; + + if (cp == NULL) + return (NULL); + + do { + if (gdtbase == (uintptr_t)cp->cpu_gdt) + return (cp); + } while ((cp = cp->cpu_next) != cpu_list); + + return (NULL); +} + +#if defined(__amd64) +uintptr_t +kdi_gdt2gsbase(uintptr_t gdtbase) +{ + return ((uintptr_t)kdi_gdt2cpu(gdtbase)); +} +#endif + +static uintptr_t +kdi_get_userlimit(void) +{ + return (_userlimit); +} + +static int +kdi_get_cpuinfo(uint_t *vendorp, uint_t *familyp, uint_t *modelp) +{ + desctbr_t gdtr; + cpu_t *cpu; + + /* + * CPU doesn't work until the GDT and gs/GSBASE have been set up. + * Boot-loaded kmdb will call us well before then, so we have to + * find the current cpu_t the hard way. + */ + rd_gdtr(&gdtr); + if ((cpu = kdi_gdt2cpu(gdtr.dtr_base)) == NULL || + !cpuid_checkpass(cpu, 1)) + return (EAGAIN); /* cpuid isn't done yet */ + + *vendorp = cpuid_getvendor(cpu); + *familyp = cpuid_getfamily(cpu); + *modelp = cpuid_getmodel(cpu); + + return (0); +} + +void +kdi_idtr_set(gate_desc_t *idt, size_t limit) +{ + desctbr_t idtr; + + /* + * This rare case could happen if we entered kmdb whilst still on the + * fake CPU set up by boot_kdi_tmpinit(). We're trying to restore the + * kernel's IDT that we saved on entry, but it was from the fake cpu_t + * rather than the real IDT (which is still boot's). It's unpleasant, + * but we just encode knowledge that it's idt0 we want to restore. + */ + if (idt == NULL) + idt = idt0; + + CPU->cpu_m.mcpu_idt = idt; + idtr.dtr_base = (uintptr_t)idt; + idtr.dtr_limit = limit; + kdi_idtr_write(&idtr); +} + +static void +kdi_plat_call(void (*platfn)(void)) +{ + if (platfn != NULL) + platfn(); +} + +/* + * On Intel, most of these are shared between i86*, so this is really an + * arch_kdi_init(). + */ +void +mach_kdi_init(kdi_t *kdi) +{ + kdi->kdi_plat_call = kdi_plat_call; + kdi->kdi_kmdb_enter = kmdb_enter; + kdi->mkdi_activate = kdi_activate; + kdi->mkdi_deactivate = kdi_deactivate; + kdi->mkdi_idt_switch = kdi_idt_switch; + kdi->mkdi_update_drreg = kdi_update_drreg; + kdi->mkdi_set_debug_msrs = kdi_set_debug_msrs; + kdi->mkdi_get_userlimit = kdi_get_userlimit; + kdi->mkdi_get_cpuinfo = kdi_get_cpuinfo; + kdi->mkdi_stop_slaves = kdi_stop_slaves; + kdi->mkdi_start_slaves = kdi_start_slaves; + kdi->mkdi_slave_wait = kdi_slave_wait; + kdi->mkdi_memrange_add = kdi_memrange_add; + kdi->mkdi_reboot = kdi_reboot; +} + +void +plat_kdi_init(kdi_t *kdi) +{ + kdi->pkdi_system_claim = kdi_system_claim; + kdi->pkdi_system_release = kdi_system_release; +} diff --git a/usr/src/uts/i86pc/pci_autoconfig/Makefile b/usr/src/uts/intel/pci_autoconfig/Makefile index 4c562f700b..d858a8bbfc 100644 --- a/usr/src/uts/i86pc/pci_autoconfig/Makefile +++ b/usr/src/uts/intel/pci_autoconfig/Makefile @@ -19,8 +19,8 @@ # CDDL HEADER END # # -# uts/i86pc/pci_autoconfig/Makefile -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# uts/intel/pci_autoconfig/Makefile +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -28,7 +28,7 @@ # This makefile drives the production of the PCI autoconfiguration # kernel module. # -# i86pc platform dependent +# intel platform dependent # # @@ -44,12 +44,13 @@ OBJECTS = $(PCI_AUTOCONFIG_OBJS:%=$(OBJS_DIR)/%) \ $(PCI_STRING_OBJS:%=$(OBJS_DIR)/%) LINTS = $(PCI_AUTOCONFIG_OBJS:%.o=$(LINTS_DIR)/%.ln) \ $(PCI_STRING_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_MISC_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE) +INC_PATH += -I$(UTSBASE)/i86pc # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -95,4 +96,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/pci_pci/Makefile b/usr/src/uts/intel/pci_pci/Makefile index b5e3779ed3..b278711141 100644 --- a/usr/src/uts/i86pc/pci_pci/Makefile +++ b/usr/src/uts/intel/pci_pci/Makefile @@ -19,9 +19,9 @@ # CDDL HEADER END # # -# uts/i86pc/pci_pci/Makefile +# uts/intel/pci_pci/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -40,14 +40,14 @@ UTSBASE = ../.. MODULE = pci_pci OBJECTS = $(PCI_PCINEXUS_OBJS:%=$(OBJS_DIR)/%) LINTS = $(PCI_PCINEXUS_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) -INC_PATH += -I../../i86pc +INC_PATH += -I$(UTSBASE)/i86pc # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -91,4 +91,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/pcic/Makefile b/usr/src/uts/intel/pcic/Makefile index d910a5860c..4c917534ec 100644 --- a/usr/src/uts/i86pc/pcic/Makefile +++ b/usr/src/uts/intel/pcic/Makefile @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -29,7 +29,7 @@ # This makefile drives the PCIC style PCMCIA adapter # It is mostly a standard driver # -# i86pc architecture dependent +# intel architecture dependent # # @@ -49,7 +49,7 @@ CONF_SRCDIR = $(UTSBASE)/common/io # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -98,4 +98,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/pcie_pci/Makefile b/usr/src/uts/intel/pcie_pci/Makefile index 1a7bcef5b9..51a4ba8a6d 100644 --- a/usr/src/uts/i86pc/pcie_pci/Makefile +++ b/usr/src/uts/intel/pcie_pci/Makefile @@ -19,9 +19,9 @@ # CDDL HEADER END # # -# uts/i86pc/pcie_pci/Makefile +# uts/intel/pcie_pci/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -41,13 +41,13 @@ UTSBASE = ../.. MODULE = pcie_pci OBJECTS = $(PCI_E_PCINEXUS_OBJS:%=$(OBJS_DIR)/%) LINTS = $(PCI_E_PCINEXUS_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/i86pc/io/pciex +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) +CONF_SRCDIR = $(UTSBASE)/intel/io/pciex # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -106,5 +106,5 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/pciehpc/Makefile b/usr/src/uts/intel/pciehpc/Makefile index c1515fca13..c457d0cfd1 100644 --- a/usr/src/uts/i86pc/pciehpc/Makefile +++ b/usr/src/uts/intel/pciehpc/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -27,7 +27,7 @@ # This makefile drives the production of the kernel/misc/pciehpc module # for PCI-E hotplug controller support in PCI-E nexus drivers. # -# i86pc implementation architecture dependent +# intel architecture dependent # # @@ -41,12 +41,12 @@ UTSBASE = ../.. MODULE = pciehpc OBJECTS = $(PCIEHPCNEXUS_OBJS:%=$(OBJS_DIR)/%) LINTS = $(PCIEHPCNEXUS_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_MISC_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE) # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -101,4 +101,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/power/Makefile b/usr/src/uts/intel/power/Makefile index e058e6d525..a61c18049a 100644 --- a/usr/src/uts/i86pc/power/Makefile +++ b/usr/src/uts/intel/power/Makefile @@ -19,15 +19,15 @@ # CDDL HEADER END # # -# uts/i86pc/power/Makefile -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# uts/intel/power/Makefile +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" # # This makefile drives the production of the power driver # -# sun4u implementation architecture dependent +# intel architecture dependent # # @@ -41,13 +41,13 @@ UTSBASE = ../.. MODULE = power OBJECTS = $(POWER_OBJS:%=$(OBJS_DIR)/%) LINTS = $(POWER_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) CONF_SRCDIR = $(UTSBASE)/common/io # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -101,4 +101,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/intel/swrand/Makefile b/usr/src/uts/intel/swrand/Makefile index 80a04fd6cb..05b1533808 100644 --- a/usr/src/uts/intel/swrand/Makefile +++ b/usr/src/uts/intel/swrand/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -41,6 +41,7 @@ MODULE = swrand OBJECTS = $(SWRANDPROV_OBJS:%=$(OBJS_DIR)/%) LINTS = $(SWRANDPROV_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(ROOT_CRYPTO_DIR)/$(MODULE) +INC_PATH += -I../../i86pc # # Include common rules. diff --git a/usr/src/uts/intel/sys/Makefile b/usr/src/uts/intel/sys/Makefile index 491f4d3224..655ec9b54f 100644 --- a/usr/src/uts/intel/sys/Makefile +++ b/usr/src/uts/intel/sys/Makefile @@ -46,10 +46,10 @@ HDRS = \ fasttrap_isa.h \ fp.h \ frame.h \ - immu.h \ inline.h \ kd.h \ kdi_machimpl.h \ + kdi_regs.h \ machelf.h \ machlock.h \ machsig.h \ @@ -61,11 +61,11 @@ HDRS = \ memtest.h \ mii.h \ miipriv.h \ - mmu.h \ mutex_impl.h \ obpdefs.h \ old_procfs.h \ pcb.h \ + pmem.h \ privregs.h \ procfs_isa.h \ prom_emul.h \ diff --git a/usr/src/uts/intel/sys/archsystm.h b/usr/src/uts/intel/sys/archsystm.h index 1eed79d0ae..f6665f6565 100644 --- a/usr/src/uts/intel/sys/archsystm.h +++ b/usr/src/uts/intel/sys/archsystm.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -51,14 +51,22 @@ extern ulong_t getcr2(void); #if defined(__i386) extern uint16_t getgs(void); extern void setgs(uint16_t); + +extern void patch_sse(void); +extern void patch_sse2(void); #endif +extern void cli(void); extern void sti(void); extern void tenmicrosec(void); -extern void restore_int_flag(int); -extern int clear_int_flag(void); +extern void restore_int_flag(ulong_t); +extern void intr_restore(ulong_t); +extern ulong_t clear_int_flag(void); +extern ulong_t intr_clear(void); +extern ulong_t getflags(void); +extern int interrupts_enabled(void); extern void int3(void); extern void int18(void); @@ -72,6 +80,7 @@ extern void sys_syscall_int(); extern void brand_sys_syscall(); extern void brand_sys_syscall32(); extern void brand_sys_syscall_int(); +extern int update_sregs(); #elif defined(__i386) extern void sys_call(); extern void brand_sys_call(); @@ -85,10 +94,8 @@ extern void dosyscall(void); extern void bind_hwcap(void); -extern uint8_t inb(int port); extern uint16_t inw(int port); extern uint32_t inl(int port); -extern void outb(int port, uint8_t value); extern void outw(int port, uint16_t value); extern void outl(int port, uint32_t value); @@ -134,34 +141,52 @@ extern uint_t cpu_hwcap_flags; extern uint_t cpu_freq; extern uint64_t cpu_freq_hz; +extern int use_sse_pagecopy; +extern int use_sse_pagezero; +extern int use_sse_copy; + extern caddr_t i86devmap(pfn_t, pgcnt_t, uint_t); extern page_t *page_numtopp_alloc(pfn_t pfnum); extern void hwblkclr(void *, size_t); extern void hwblkpagecopy(const void *, void *); +extern void page_copy_no_xmm(void *dst, void *src); +extern void block_zero_no_xmm(void *dst, int len); +#define BLOCKZEROALIGN (4 * sizeof (void *)) extern void (*kcpc_hw_enable_cpc_intr)(void); -extern void setup_mca(void); -extern void setup_mtrr(void); extern void patch_tsc(void); +extern void init_desctbls(void); extern user_desc_t *cpu_get_gdt(void); -/* - * Warning: these routines do -not- use normal calling conventions! - */ -extern void setup_121_andcall(void (*)(ulong_t), ulong_t); -extern void enable_big_page_support(ulong_t); -extern void enable_pae(ulong_t); - +extern void switch_sp_and_call(void *, void (*)(uint_t, uint_t), uint_t, + uint_t); extern hrtime_t (*gethrtimef)(void); extern hrtime_t (*gethrtimeunscaledf)(void); extern void (*scalehrtimef)(hrtime_t *); extern void (*gethrestimef)(timestruc_t *); +extern void av_dispatch_softvect(uint_t); +extern void av_dispatch_autovect(uint_t); +extern uint_t atomic_btr32(uint32_t *, uint_t); +extern uint_t bsrw_insn(uint16_t); +extern int sys_rtt_common(struct regs *); +extern void fakesoftint(void); + + +extern void setup_mca(void); +extern void setup_mtrr(void); +#define cpr_dprintf prom_printf + #endif /* _KERNEL */ +#if defined(_KERNEL) || defined(_BOOT) +extern uint8_t inb(int port); +extern void outb(int port, uint8_t value); +#endif + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/intel/sys/bootconf.h b/usr/src/uts/intel/sys/bootconf.h index 2e1ccbf326..0cde010b88 100644 --- a/usr/src/uts/intel/sys/bootconf.h +++ b/usr/src/uts/intel/sys/bootconf.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -219,11 +219,29 @@ extern int netboot; extern int swaploaded; extern int modrootloaded; extern char kern_bootargs[]; +extern char *kobj_module_path; extern char *default_path; extern char *dhcack; extern int dhcacklen; extern char *netdev_path; +extern void bop_no_more_mem(void); + +/*PRINTFLIKE2*/ +extern void bop_printf(struct bootops *, char *, ...) + __KPRINTFLIKE(2); +/*PRINTFLIKE1*/ +extern void bop_panic(char *, ...) + __KPRINTFLIKE(1); +extern void boot_prop_finish(void); + +/* + * Back door to fakebop.c to get physical memory allocated. + * 64 bit data types are fixed for 32 bit PAE use. + */ +extern paddr_t do_bop_phys_alloc(uint64_t, uint64_t); + + #endif /* _KERNEL && !_BOOT */ #ifdef __cplusplus diff --git a/usr/src/uts/intel/sys/bootinfo.h b/usr/src/uts/intel/sys/bootinfo.h new file mode 100644 index 0000000000..6c25d8bcab --- /dev/null +++ b/usr/src/uts/intel/sys/bootinfo.h @@ -0,0 +1,99 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_BOOTINFO_H +#define _SYS_BOOTINFO_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The 32-bit kernel loader code needs to build several structures that the + * kernel is expecting. They will contain native sized pointers for the + * target kernel. + */ + +#if defined(_BOOT_TARGET_amd64) + +typedef uint64_t native_ptr_t; + +#elif defined(_BOOT_TARGET_i386) + +typedef uint32_t native_ptr_t; + +#elif defined(_KERNEL) + +typedef void *native_ptr_t; + +#endif + +struct boot_memlist { + uint64_t addr; + uint64_t size; + native_ptr_t next; + native_ptr_t prev; +}; + +/* + * The kernel needs to know how to find its modules. + */ +struct boot_modules { + native_ptr_t bm_addr; + uint32_t bm_size; + uint32_t bm_padding; +}; + +/* + * + */ +#pragma pack(1) +struct xboot_info { + uint64_t bi_next_paddr; /* next physical address not used */ + native_ptr_t bi_next_vaddr; /* next virtual address not used */ + native_ptr_t bi_cmdline; + native_ptr_t bi_phys_install; + native_ptr_t bi_modules; + uint32_t bi_module_cnt; + uint32_t bi_use_largepage; /* MMU uses large pages */ + uint32_t bi_use_pae; /* MMU uses PAE mode (8 byte PTES) */ + uint32_t bi_use_nx; /* MMU uses NX bit in PTEs */ + uint32_t bi_use_pge; /* MMU uses Page Global Enable */ + native_ptr_t bi_pt_window; + native_ptr_t bi_pte_to_pt_window; + native_ptr_t bi_kseg_size; /* size used for kernel nucleus pages */ + uint64_t bi_top_page_table; + native_ptr_t bi_mb_info; +}; +#pragma pack() + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_BOOTINFO_H */ diff --git a/usr/src/uts/intel/sys/controlregs.h b/usr/src/uts/intel/sys/controlregs.h index cea4e712d9..385a89fe07 100644 --- a/usr/src/uts/intel/sys/controlregs.h +++ b/usr/src/uts/intel/sys/controlregs.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -66,6 +66,26 @@ extern "C" { #define FMT_CR0 \ "\20\40pg\37cd\36nw\35am\21wp\6ne\5et\4ts\3em\2mp\1pe" +/* + * Set the FPU-related control bits to explain to the processor that + * we're managing FPU state: + * - set monitor coprocessor (allow TS bit to control FPU) + * - set numeric exception (disable IGNNE# mechanism) + * - set task switch (#nm on first fp instruction) + * - clear emulate math bit (cause we're not emulating!) + */ +#define CR0_ENABLE_FPU_FLAGS(cr) \ + (((cr) | CR0_MP | CR0_NE | CR0_TS) & (uint32_t)~CR0_EM) + +/* + * Set the FPU-related control bits to explain to the processor that + * we're -not- managing FPU state: + * - set emulate (all fp instructions cause #nm) + * - clear monitor coprocessor (so fwait/wait doesn't #nm) + */ +#define CR0_DISABLE_FPU_FLAGS(cr) \ + (((cr) | CR0_EM) & (uint32_t)~CR0_MP) + /* CR3 Register */ #define CR3_PCD 0x00000010 /* cache disable */ @@ -86,9 +106,28 @@ extern "C" { #define CR4_PCE 0x0100 /* perf-monitoring counter enable */ #define CR4_OSFXSR 0x0200 /* OS fxsave/fxrstor support */ #define CR4_OSXMMEXCPT 0x0400 /* OS unmasked exception support */ + /* 0x0800 reserved */ + /* 0x1000 reserved */ +#define CR4_VMXE 0x2000 +#define CR4_SMXE 0x4000 -#define FMT_CR4 \ - "\20\13xmme\12fxsr\11pce\10pge\7mce\6pae\5pse\4de\3tsd\2pvi\1vme" +#define FMT_CR4 \ + "\20\17smxe\16vmxe\13xmme\12fxsr\11pce\10pge" \ + "\7mce\6pae\5pse\4de\3tsd\2pvi\1vme" + +/* + * Enable the SSE-related control bits to explain to the processor that + * we're managing XMM state and exceptions + */ +#define CR4_ENABLE_SSE_FLAGS(cr) \ + ((cr) | CR4_OSFXSR | CR4_OSXMMEXCPT) + +/* + * Disable the SSE-related control bits to explain to the processor + * that we're NOT managing XMM state + */ +#define CR4_DISABLE_SSE_FLAGS(cr) \ + ((cr) & ~(uint32_t)(CR4_OSFXSR | CR4_OSXMMEXCPT)) /* Intel's SYSENTER configuration registers */ @@ -100,13 +139,15 @@ extern "C" { #define MSR_AMD_EFER 0xc0000080 /* extended feature enable MSR */ -#define AMD_EFER_NXE 0x800 /* no-execute enable */ -#define AMD_EFER_LMA 0x400 /* long mode active (read-only) */ -#define AMD_EFER_LME 0x100 /* long mode enable */ -#define AMD_EFER_SCE 0x001 /* system call extensions */ +#define AMD_EFER_FFXSR 0x4000 /* fast fxsave/fxrstor */ +#define AMD_EFER_SVME 0x1000 /* svm enable */ +#define AMD_EFER_NXE 0x0800 /* no-execute enable */ +#define AMD_EFER_LMA 0x0400 /* long mode active (read-only) */ +#define AMD_EFER_LME 0x0100 /* long mode enable */ +#define AMD_EFER_SCE 0x0001 /* system call extensions */ #define FMT_AMD_EFER \ - "\20\14nxe\13lma\11lme\1sce" + "\20\17ffxsr\15svme\14nxe\13lma\11lme\1sce" /* AMD's SYSCFG register */ @@ -132,6 +173,7 @@ extern "C" { #define MSR_AMD_FSBASE 0xc0000100 /* 64-bit base address for %fs */ #define MSR_AMD_GSBASE 0xc0000101 /* 64-bit base address for %gs */ #define MSR_AMD_KGSBASE 0xc0000102 /* swapgs swaps this with gsbase */ +#define MSR_AMD_TSCAUX 0xc0000103 /* %ecx value on rdtscp insn */ /* AMD's configuration MSRs, weakly documented in the revision guide */ diff --git a/usr/src/uts/intel/sys/fp.h b/usr/src/uts/intel/sys/fp.h index 133499a3ae..02fb34fc65 100644 --- a/usr/src/uts/intel/sys/fp.h +++ b/usr/src/uts/intel/sys/fp.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -97,7 +96,7 @@ extern "C" { */ #define FPS_IE 0x00000001 /* invalid operation */ #define FPS_DE 0x00000002 /* denormalized operand */ -#define FPS_ZE 0x00000004 /* zero devide */ +#define FPS_ZE 0x00000004 /* zero divide */ #define FPS_OE 0x00000008 /* overflow */ #define FPS_UE 0x00000010 /* underflow */ #define FPS_PE 0x00000020 /* precision */ @@ -164,14 +163,22 @@ extern int fpu_exists; /* FPU hw exists */ #ifdef _KERNEL +extern int fpu_ignored; +extern int fpu_pentium_fdivbug; + extern uint32_t sse_mxcsr_mask; extern void fpu_probe(void); +extern uint_t fpu_initial_probe(void); +extern int fpu_probe_pentium_fdivbug(void); -extern void fpnsave_begin(void *); -extern void fpxsave_begin(void *); -extern void (*fpsave_begin)(void *); +extern void fpnsave_ctxt(void *); +extern void fpxsave_ctxt(void *); +extern void (*fpsave_ctxt)(void *); +struct fnsave_state; +struct fxsave_state; +extern void fxsave_insn(struct fxsave_state *); extern void fpsave(struct fnsave_state *); extern void fprestore(struct fnsave_state *); extern void fpxsave(struct fxsave_state *); diff --git a/usr/src/uts/intel/sys/immu.h b/usr/src/uts/intel/sys/immu.h deleted file mode 100644 index ac9af15bf6..0000000000 --- a/usr/src/uts/intel/sys/immu.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1990-1997,1999 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _SYS_IMMU_H -#define _SYS_IMMU_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * XXX - following stuff from 3b2 immu.h. this really belongs elsewhere. - */ - -/* - * The following variables describe the memory managed by - * the kernel. This includes all memory above the kernel - * itself. - */ - -extern pgcnt_t maxmem; /* Maximum available free memory. */ -extern pgcnt_t freemem; /* Current free memory. */ -extern pgcnt_t availrmem; /* Available resident (not */ - /* swapable) memory in pages. */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_IMMU_H */ diff --git a/usr/src/uts/intel/sys/kdi_machimpl.h b/usr/src/uts/intel/sys/kdi_machimpl.h index f34501385d..5ded8b44c2 100644 --- a/usr/src/uts/intel/sys/kdi_machimpl.h +++ b/usr/src/uts/intel/sys/kdi_machimpl.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -35,61 +34,89 @@ * and are to be used only when the system has been stopped. */ -/* The VA range reserved for the debugger. */ - #include <sys/modctl.h> #include <sys/types.h> +#include <sys/cpuvar.h> +#include <sys/kdi_regs.h> #ifdef __cplusplus extern "C" { #endif +typedef void (*kdi_main_t)(kdi_cpusave_t *); + +typedef struct kdi_memrange { + caddr_t mr_base; + caddr_t mr_lim; +} kdi_memrange_t; + +#define KDI_MEMRANGES_MAX 2 + typedef struct kdi_mach { - int (*mkdi_get_cpuinfo)(uint_t *, uint_t *, uint_t *); + void (*mkdi_activate)(kdi_main_t, kdi_cpusave_t *, uint_t); + void (*mkdi_deactivate)(void); + + void (*mkdi_idt_switch)(kdi_cpusave_t *); - int (*mkdi_xc_initialized)(void); - void (*mkdi_xc_others)(int, void (*)()); + void (*mkdi_update_drreg)(kdi_drreg_t *); + void (*mkdi_set_debug_msrs)(kdi_msr_t *); uintptr_t (*mkdi_get_userlimit)(void); - void (*mkdi_idt_init_gate)(struct gate_desc *, void (*)(void), uint_t, - int); - void (*mkdi_idt_read)(struct gate_desc *, struct gate_desc *, uint_t); - void (*mkdi_idt_write)(struct gate_desc *, struct gate_desc *, uint_t); - struct gate_desc *(*mkdi_cpu2idt)(struct cpu *); + int (*mkdi_get_cpuinfo)(uint_t *, uint_t *, uint_t *); + + void (*mkdi_stop_slaves)(int, int); - void (**mkdi_shutdownp)(int, int); + void (*mkdi_start_slaves)(void); -#if defined(__amd64) - uintptr_t (*mkdi_gdt2gsbase)(uintptr_t); -#endif + void (*mkdi_slave_wait)(void); - /* for use only when the kernel is running */ - void (*mkdi_cpu_iter)(void (*)(struct cpu *, uint_t), - uint_t); + void (*mkdi_memrange_add)(caddr_t, size_t); + + void (*mkdi_reboot)(void); } kdi_mach_t; -#define mkdi_get_cpuinfo kdi_mach.mkdi_get_cpuinfo -#define mkdi_xc_initialized kdi_mach.mkdi_xc_initialized -#define mkdi_xc_others kdi_mach.mkdi_xc_others +#define mkdi_activate kdi_mach.mkdi_activate +#define mkdi_deactivate kdi_mach.mkdi_deactivate +#define mkdi_idt_switch kdi_mach.mkdi_idt_switch +#define mkdi_update_drreg kdi_mach.mkdi_update_drreg +#define mkdi_set_debug_msrs kdi_mach.mkdi_set_debug_msrs #define mkdi_get_userlimit kdi_mach.mkdi_get_userlimit -#define mkdi_idt_init_gate kdi_mach.mkdi_idt_init_gate -#define mkdi_idt_read kdi_mach.mkdi_idt_read -#define mkdi_idt_write kdi_mach.mkdi_idt_write -#define mkdi_cpu2idt kdi_mach.mkdi_cpu2idt -#define mkdi_shutdownp kdi_mach.mkdi_shutdownp -#if defined(__amd64) -#define mkdi_gdt2gsbase kdi_mach.mkdi_gdt2gsbase -#endif -#define mkdi_cpu_iter kdi_mach.mkdi_cpu_iter - -extern int kdi_xc_initialized(void); -extern void kdi_xc_others(int, void (*)()); +#define mkdi_get_cpuinfo kdi_mach.mkdi_get_cpuinfo +#define mkdi_stop_slaves kdi_mach.mkdi_stop_slaves +#define mkdi_start_slaves kdi_mach.mkdi_start_slaves +#define mkdi_slave_wait kdi_mach.mkdi_slave_wait +#define mkdi_memrange_add kdi_mach.mkdi_memrange_add +#define mkdi_reboot kdi_mach.mkdi_reboot extern void hat_kdi_init(void); -extern void hat_kdi_fini(void); -extern uintptr_t kdi_get_userlimit(void); +extern ulong_t kdi_getdr0(void), kdi_getdr1(void), kdi_getdr2(void); +extern ulong_t kdi_getdr3(void), kdi_getdr6(void), kdi_getdr7(void); +extern void kdi_setdr0(ulong_t), kdi_setdr1(ulong_t), kdi_setdr2(ulong_t); +extern void kdi_setdr3(ulong_t), kdi_setdr6(ulong_t), kdi_setdr7(ulong_t); +extern ulong_t kdi_dreg_get(int); +extern void kdi_dreg_set(int, ulong_t); +extern void kdi_update_drreg(kdi_drreg_t *); +extern void kdi_set_debug_msrs(kdi_msr_t *); +extern void kdi_cpu_debug_init(kdi_cpusave_t *); + +extern void kdi_cpu_init(void); +extern void kdi_xc_others(int, void (*)(void)); +extern void kdi_start_slaves(void); +extern void kdi_slave_wait(void); + +extern void kdi_idtr_set(gate_desc_t *, size_t); +extern void kdi_idt_write(struct gate_desc *, uint_t); +extern void kdi_idt_sync(void); +extern void kdi_idt_switch(kdi_cpusave_t *); +#define kdi_idtr_write(idtr) wr_idtr(idtr) + +extern void kdi_activate(kdi_main_t, kdi_cpusave_t *, uint_t); +extern void kdi_deactivate(void); +extern void kdi_stop_slaves(int, int); +extern void kdi_memrange_add(caddr_t, size_t); +extern void kdi_reboot(void); #ifdef __cplusplus } diff --git a/usr/src/uts/intel/sys/kdi_regs.h b/usr/src/uts/intel/sys/kdi_regs.h new file mode 100644 index 0000000000..e896e29a64 --- /dev/null +++ b/usr/src/uts/intel/sys/kdi_regs.h @@ -0,0 +1,135 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_KDI_REGS_H +#define _SYS_KDI_REGS_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef _ASM +#include <sys/types.h> +#include <sys/segments.h> +#include <sys/regset.h> +#include <sys/privregs.h> +#endif + +#if defined(__amd64) +#include <amd64/sys/kdi_regs.h> +#elif defined(__i386) +#include <ia32/sys/kdi_regs.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define KDI_NCRUMBS 5 + +#define KDI_RESUME 0 +#define KDI_RESUME_PASS_TO_KERNEL 1 + +#define KDI_CPU_STATE_NONE 0 +#define KDI_CPU_STATE_MASTER 1 +#define KDI_CPU_STATE_SLAVE 2 + +#define KDIREG_DRCTL_WPALLEN_MASK 0x000000ff +#define KDIREG_DRSTAT_RESERVED 0xffff0ff0 +#define KDIREG_DRCTL_RESERVED 0x00000700 + +#define KDI_MSR_READ 0x1 /* read during entry (unlimited) */ +#define KDI_MSR_WRITE 0x2 /* write during exit (unlimited) */ +#define KDI_MSR_WRITEDELAY 0x4 /* write after last branch (<= 1) */ +#define KDI_MSR_CLEARENTRY 0x3 /* clear before 1st branch (<= 1) */ + +#ifndef _ASM + +/* + * We maintain a ring buffer of bread crumbs for debugging purposes. The + * current buffer pointer is advanced along the ring with each intercepted + * trap (debugger entry, invalid memory access, fault during step, etc). + */ +typedef struct kdi_crumb { + greg_t krm_cpu_state; /* This CPU's state at last entry */ + greg_t krm_pc; /* Instruction pointer at trap */ + greg_t krm_sp; /* Stack pointer at trap */ + greg_t krm_trapno; /* The last trap number */ + greg_t krm_flag; /* KAIF_CRUMB_F_* */ +} kdi_crumb_t; + +#define KDI_MAXWPIDX 3 + +/* + * Storage for %dr0-3, %dr6, and %dr7. + */ +typedef struct kdi_drreg { + greg_t dr_ctl; + greg_t dr_stat; + greg_t dr_addr[KDI_MAXWPIDX + 1]; +} kdi_drreg_t; + +typedef struct kdi_msr { + uint_t msr_num; + uint_t msr_type; + union { + uint64_t *_msr_valp; + uint64_t _msr_val; + } _u; +} kdi_msr_t; + +#define kdi_msr_val _u._msr_val +#define kdi_msr_valp _u._msr_valp + +/* + * Data structure used to hold all of the state for a given CPU. + */ +typedef struct kdi_cpusave { + greg_t *krs_gregs; /* saved registers */ + + kdi_drreg_t krs_dr; /* saved debug registers */ + + user_desc_t *krs_gdt; /* GDT address */ + gate_desc_t *krs_idt; /* IDT address */ + + greg_t krs_cr0; /* saved %cr0 */ + + kdi_msr_t *krs_msr; /* ptr to MSR save area */ + + uint_t krs_cpu_state; /* KDI_CPU_STATE_* mstr/slv */ + uint_t krs_cpu_flushed; /* Have caches been flushed? */ + uint_t krs_cpu_id; /* this CPU's ID */ + + /* Bread crumb ring buffer */ + ulong_t krs_curcrumbidx; /* Current krs_crumbs idx */ + kdi_crumb_t *krs_curcrumb; /* Pointer to current crumb */ + kdi_crumb_t krs_crumbs[KDI_NCRUMBS]; /* Crumbs */ +} kdi_cpusave_t; + +#endif /* !_ASM */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_KDI_REGS_H */ diff --git a/usr/src/uts/i86pc/sys/pmem.h b/usr/src/uts/intel/sys/pmem.h index 068ea349b2..068ea349b2 100644 --- a/usr/src/uts/i86pc/sys/pmem.h +++ b/usr/src/uts/intel/sys/pmem.h diff --git a/usr/src/uts/intel/sys/segments.h b/usr/src/uts/intel/sys/segments.h index fe65db8575..b15131279f 100644 --- a/usr/src/uts/intel/sys/segments.h +++ b/usr/src/uts/intel/sys/segments.h @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -80,7 +80,7 @@ extern "C" { #endif #define SELTOIDX(s) ((s) >> 3) /* selector to index */ -#define SEL_KPL 0 /* kernel priority level */ +#define SEL_KPL 0 /* kernel privilege level */ #define SEL_UPL 3 /* user priority level */ #define SEL_TI_LDT 4 /* local descriptor table */ #define SEL_LDT(s) (IDXTOSEL(s) | SEL_TI_LDT | SEL_UPL) /* local sel */ @@ -126,10 +126,28 @@ extern void wr_gdtr(desctbr_t *); extern void wr_ldtr(selector_t); extern selector_t rd_ldtr(void); extern void wr_tsr(selector_t); +extern void kmdb_enter(void); #if defined(__amd64) extern void clr_ldt_sregs(void); -#endif + +/* + * inlines for update_segregs + */ +extern void __set_ds(selector_t); +extern void __set_es(selector_t); +extern void __set_fs(selector_t); +extern void __set_gs(selector_t); +extern void __swapgs(void); +#endif /* __amd64 */ + +#if defined(__amd64) +extern void load_segment_registers(selector_t, selector_t, selector_t, + selector_t); /* (alphabetical) */ +#elif defined(__i386) +extern void load_segment_registers(selector_t, selector_t, selector_t, + selector_t, selector_t, selector_t); /* (alphabetical) */ +#endif /* __i386 */ #if !defined(__amd64) @@ -329,20 +347,21 @@ typedef struct gate_desc { extern void set_usegd(user_desc_t *, uint_t, void *, size_t, uint_t, uint_t, uint_t, uint_t); -extern void set_gatesegd(gate_desc_t *, void (*)(void), selector_t, uint_t, - uint_t, uint_t); #elif defined(__i386) extern void set_usegd(user_desc_t *, void *, size_t, uint_t, uint_t, uint_t, uint_t); -extern void set_gatesegd(gate_desc_t *, void (*)(void), selector_t, - uint_t, uint_t, uint_t); #endif /* __i386 */ +extern void set_gatesegd(gate_desc_t *, void (*)(void), selector_t, + uint_t, uint_t); + void set_syssegd(system_desc_t *, void *, size_t, uint_t, uint_t); +void init_boot_gdt(user_desc_t *); + #endif /* _ASM */ /* @@ -433,26 +452,31 @@ void set_syssegd(system_desc_t *, void *, size_t, uint_t, uint_t); * in long mode system segment decriptors expand to 128 bits. * * GDT_LWPFS and GDT_LWPGS must be the same for both 32 and 64-bit - * kernels. See setup_context in libc. + * kernels. See setup_context in libc. 64-bit processes must set + * %fs or %gs to null selector to use 64-bit fsbase or gsbase + * respectively. */ +#define GDT_NULL 0 /* null */ +#define GDT_B32DATA 1 /* dboot 32 bit data descriptor */ +#define GDT_B32CODE 2 /* dboot 32 bit code descriptor */ +#define GDT_B16CODE 3 /* bios call 16 bit code descriptor */ +#define GDT_B16DATA 4 /* bios call 16 bit data descriptor */ +#define GDT_B64CODE 5 /* dboot 64 bit code descriptor */ +#define GDT_BGSTMP 7 /* kmdb descriptor only used early in boot */ + #if defined(__amd64) -#define GDT_NULL 0 /* null */ -#define GDT_B32DATA 1 /* copied from boot */ -#define GDT_B32CODE 2 /* copied from boot */ -#define GDT_B64DATA 3 /* copied from boot */ -#define GDT_B64CODE 4 /* copied from boot */ -#define GDT_KCODE 5 /* kernel code seg %cs */ -#define GDT_KDATA 6 /* kernel data seg %ds */ -#define GDT_U32CODE 7 /* 32-bit process on 64-bit kernel %cs */ -#define GDT_UDATA 8 /* user data seg %ds (32 and 64 bit) */ -#define GDT_UCODE 9 /* native user code seg %cs */ -#define GDT_LDT 10 /* LDT for current process */ -#define GDT_KTSS 12 /* kernel tss */ +#define GDT_KCODE 6 /* kernel code seg %cs */ +#define GDT_KDATA 7 /* kernel data seg %ds */ +#define GDT_U32CODE 8 /* 32-bit process on 64-bit kernel %cs */ +#define GDT_UDATA 9 /* user data seg %ds (32 and 64 bit) */ +#define GDT_UCODE 10 /* native user code seg %cs */ +#define GDT_LDT 12 /* LDT for current process */ +#define GDT_KTSS 14 /* kernel tss */ #define GDT_FS GDT_NULL /* kernel %fs segment selector */ #define GDT_GS GDT_NULL /* kernel %gs segment selector */ -#define GDT_LWPFS 55 /* lwp private %fs segment selector */ -#define GDT_LWPGS 56 /* lwp private %gs segment selector */ +#define GDT_LWPFS 55 /* lwp private %fs segment selector (32-bit) */ +#define GDT_LWPGS 56 /* lwp private %gs segment selector (32-bit) */ #define GDT_BRANDMIN 57 /* first entry in GDT for brand usage */ #define GDT_BRANDMAX 61 /* last entry in GDT for brand usage */ #define NGDT 62 /* number of entries in GDT */ @@ -465,11 +489,6 @@ void set_syssegd(system_desc_t *, void *, size_t, uint_t, uint_t); #elif defined(__i386) -#define GDT_NULL 0 /* null */ -#define GDT_BOOTFLAT 1 /* copied from boot */ -#define GDT_BOOTCODE 2 /* copied from boot */ -#define GDT_BOOTCODE16 3 /* copied from boot */ -#define GDT_BOOTDATA 4 /* copied from boot */ #define GDT_LDT 40 /* LDT for current process */ #define GDT_KTSS 42 /* kernel tss */ #define GDT_KCODE 43 /* kernel code seg %cs */ @@ -501,17 +520,32 @@ void set_syssegd(system_desc_t *, void *, size_t, uint_t, uint_t); #define ULDT_SEL SEL_GDT(GDT_LDT, SEL_KPL) #define KTSS_SEL SEL_GDT(GDT_KTSS, SEL_KPL) #define DFTSS_SEL SEL_GDT(GDT_DBFLT, SEL_KPL) -#define KFS_SEL SEL_GDT(GDT_NULL, SEL_KPL) +#define KFS_SEL 0 #define KGS_SEL SEL_GDT(GDT_GS, SEL_KPL) #define LWPFS_SEL SEL_GDT(GDT_LWPFS, SEL_UPL) #define LWPGS_SEL SEL_GDT(GDT_LWPGS, SEL_UPL) #define BRANDMIN_SEL SEL_GDT(GDT_BRANDMIN, SEL_UPL) #define BRANDMAX_SEL SEL_GDT(GDT_BRANDMAX, SEL_UPL) -#if defined(__amd64) + #define B64CODE_SEL SEL_GDT(GDT_B64CODE, SEL_KPL) +#define B32CODE_SEL SEL_GDT(GDT_B32CODE, SEL_KPL) +#define B32DATA_SEL SEL_GDT(GDT_B32DATA, SEL_KPL) +#define B16CODE_SEL SEL_GDT(GDT_B16CODE, SEL_KPL) +#define B16DATA_SEL SEL_GDT(GDT_B16DATA, SEL_KPL) + +/* + * Temporary %gs descriptor used by kmdb with -d option. Only lives + * in boot's GDT and is not copied into kernel's GDT from boot. + */ +#define KMDBGS_SEL SEL_GDT(GDT_BGSTMP, SEL_KPL) + +/* + * Selector used for kdi_idt when kmdb has taken over the IDT. + */ +#if defined(__amd64) +#define KMDBCODE_SEL B64CODE_SEL #else -#define BOOTCODE_SEL SEL_GDT(GDT_BOOTCODE, SEL_KPL) -#define BOOTFLAT_SEL SEL_GDT(GDT_BOOTFLAT, SEL_KPL) +#define KMDBCODE_SEL B32CODE_SEL #endif /* @@ -532,7 +566,7 @@ void set_syssegd(system_desc_t *, void *, size_t, uint_t, uint_t); #pragma align 16(idt0) extern gate_desc_t idt0[NIDT]; extern desctbr_t idt0_default_reg; -extern user_desc_t gdt0[NGDT]; +extern user_desc_t *gdt0; extern user_desc_t zero_udesc; extern system_desc_t zero_sdesc; diff --git a/usr/src/uts/intel/sys/x86_archext.h b/usr/src/uts/intel/sys/x86_archext.h index af06a50a92..d637f9b284 100644 --- a/usr/src/uts/intel/sys/x86_archext.h +++ b/usr/src/uts/intel/sys/x86_archext.h @@ -73,14 +73,14 @@ extern "C" { #define CPUID_INTC_EDX_SS 0x08000000 /* self-snoop */ #define CPUID_INTC_EDX_HTT 0x10000000 /* Hyper Thread Technology */ #define CPUID_INTC_EDX_TM 0x20000000 /* thermal monitoring */ - /* 0x40000000 - reserved */ +#define CPUID_INTC_EDX_IA64 0x40000000 /* Itanium emulating IA32 */ #define CPUID_INTC_EDX_PBE 0x80000000 /* Pending Break Enable */ -#define FMT_CPUID_INTC_EDX \ - "\20" \ - "\40pbe\36tm\35htt\34ss\33sse2\32sse\31fxsr" \ - "\30mmx\27acpi\26ds\24clfsh\23psn\22pse36\21pat"\ - "\20cmov\17mca\16pge\15mtrr\14sep\12apic\11cx8" \ +#define FMT_CPUID_INTC_EDX \ + "\20" \ + "\40pbe\37ia64\36tm\35htt\34ss\33sse2\32sse\31fxsr" \ + "\30mmx\27acpi\26ds\24clfsh\23psn\22pse36\21pat" \ + "\20cmov\17mca\16pge\15mtrr\14sep\12apic\11cx8" \ "\10mce\7pae\6msr\5tsc\4pse\3de\2vme\1fpu" /* @@ -92,22 +92,26 @@ extern "C" { /* 0x00000004 - reserved */ #define CPUID_INTC_ECX_MON 0x00000008 /* MONITOR/MWAIT */ #define CPUID_INTC_ECX_DSCPL 0x00000010 /* CPL-qualified debug store */ - /* 0x00000020 - reserved */ - /* 0x00000040 - reserved */ +#define CPUID_INTC_ECX_VMX 0x00000020 /* Hardware VM extensions */ +#define CPUID_INTC_ECX_SMX 0x00000040 /* Secure mode extensions */ #define CPUID_INTC_ECX_EST 0x00000080 /* enhanced SpeedStep */ #define CPUID_INTC_ECX_TM2 0x00000100 /* thermal monitoring */ - /* 0x00000200 - reserved */ +#define CPUID_INTC_ECX_SSSE3 0x00000200 /* Supplemental SSE3 insns */ #define CPUID_INTC_ECX_CID 0x00000400 /* L1 context ID */ /* 0x00000800 - reserved */ /* 0x00001000 - reserved */ - /* 0x00002000 - reserved */ -#define CPUID_INTC_ECX_CX16 0x00002000 /* CMPXCHG16B */ -#define CPUID_INTC_ECX_XTPR 0x00004000 /* disable task pri messages */ - -#define FMT_CPUID_INTC_ECX \ - "\20" \ - "\20\17xtpr\16cx16\13cid\11tm2" \ - "\10est\5dscpl\4monitor\1sse3" +#define CPUID_INTC_ECX_CX16 0x00002000 /* cmpxchg16 */ +#define CPUID_INTC_ECX_ETPRD 0x00004000 /* extended task pri messages */ + /* 0x00008000 - reserved */ + /* 0x00010000 - reserved */ + /* 0x00020000 - reserved */ +#define CPUID_INTC_ECX_DCA 0x00040000 /* direct cache access */ + +#define FMT_CPUID_INTC_ECX \ + "\20" \ + "\30\23dca" \ + "\20\17etprd\16cx16\13cid\12ssse3\11tm2" \ + "\10est\7smx\6vmx\5dscpl\4mon\1sse3" /* * cpuid instruction feature flags in %edx (extended function 0x80000001) @@ -129,7 +133,8 @@ extern "C" { #define CPUID_AMD_EDX_PGE 0x00002000 /* page global enable */ #define CPUID_AMD_EDX_MCA 0x00004000 /* machine check arch */ #define CPUID_AMD_EDX_CMOV 0x00008000 /* conditional move insns */ -#define CPUID_AMD_EDX_PAT 0x00010000 /* page attribute table */ +#define CPUID_AMD_EDX_PAT 0x00010000 /* K7: page attribute table */ +#define CPUID_AMD_EDX_FCMOV 0x00010000 /* FCMOVcc etc. */ #define CPUID_AMD_EDX_PSE36 0x00020000 /* 36-bit pagesize extension */ /* 0x00040000 - reserved */ /* 0x00080000 - reserved */ @@ -138,9 +143,9 @@ extern "C" { #define CPUID_AMD_EDX_MMXamd 0x00400000 /* AMD: MMX extensions */ #define CPUID_AMD_EDX_MMX 0x00800000 /* MMX instructions */ #define CPUID_AMD_EDX_FXSR 0x01000000 /* fxsave and fxrstor */ - /* 0x02000000 - reserved */ +#define CPUID_AMD_EDX_FFXSR 0x02000000 /* fast fxsave/fxrstor */ /* 0x04000000 - reserved */ - /* 0x08000000 - reserved */ +#define CPUID_AMD_EDX_TSCP 0x08000000 /* rdtscp instruction */ /* 0x10000000 - reserved */ #define CPUID_AMD_EDX_LM 0x20000000 /* AMD: long mode */ #define CPUID_AMD_EDX_3DNowx 0x40000000 /* AMD: extensions to 3DNow! */ @@ -148,16 +153,30 @@ extern "C" { #define FMT_CPUID_AMD_EDX \ "\20" \ - "\40a3d\37a3d+\36lm\31fxsr" \ + "\40a3d\37a3d+\36lm\34tscp\32ffxsr\31fxsr" \ "\30mmx\27mmxext\25nx\22pse\21pat" \ "\20cmov\17mca\16pge\15mtrr\14syscall\12apic\11cx8" \ "\10mce\7pae\6msr\5tsc\4pse\3de\2vme\1fpu" -#define CPUID_AMD_ECX_CMP_LEGACY 0x00000002 /* AMD: multi-core chip */ +#define CPUID_AMD_ECX_AHF64 0x00000001 /* LAHF and SAHF in long mode */ +#define CPUID_AMD_ECX_CMP_LGCY 0x00000002 /* AMD: multicore chip */ +#define CPUID_AMD_ECX_SVM 0x00000004 /* AMD: secure VM */ +#define CPUID_AMD_ECX_EAS 0x00000008 /* extended apic space */ +#define CPUID_AMD_ECX_CR8D 0x00000010 /* AMD: 32-bit mov %cr8 */ #define FMT_CPUID_AMD_ECX \ "\20" \ - "\1htvalid" + "\5cr8d\3svm\2lcmplgcy\1ahf64" + +/* + * Intel now seems to have claimed part of the "extended" function + * space that we previously for non-Intel implementors to use. + * More excitingly still, they've claimed bit 20 to mean LAHF/SAHF + * is available in long mode i.e. what AMD indicate using bit 0. + * On the other hand, everything else is labelled as reserved. + */ +#define CPUID_INTC_ECX_AHF64 0x00100000 /* LAHF and SAHF in long mode */ + #define P5_MCHADDR 0x0 #define P5_CESR 0x11 @@ -329,6 +348,7 @@ typedef struct mtrrvar { #define X86_MSR 0x00000004 #define X86_MTRR 0x00000008 #define X86_PGE 0x00000010 +#define X86_DE 0x00000020 #define X86_CMOV 0x00000040 #define X86_MMX 0x00000080 #define X86_MCA 0x00000100 @@ -344,14 +364,15 @@ typedef struct mtrrvar { #define X86_SSE3 0x00040000 #define X86_CX16 0x00080000 #define X86_CMP 0x00100000 +#define X86_TSCP 0x00200000 #define X86_CPUID 0x01000000 #define FMT_X86_FEATURE \ "\20" \ "\31cpuid" \ - "\25cmp\24cx16\23sse3\22nx\21asysc" \ + "\26tscp\25cmp\24cx16\23sse3\22nx\21asysc" \ "\20htt\17sse2\16sse\15sep\14pat\13cx8\12pae\11mca" \ - "\10mmx\7cmov\5pge\4mtrr\3msr\2tsc\1lgpg" + "\10mmx\7cmov\6de\5pge\4mtrr\3msr\2tsc\1lgpg" /* * x86_type is a legacy concept; this is supplanted @@ -482,7 +503,6 @@ extern uint_t x86_feature; extern uint_t x86_type; extern uint_t x86_vendor; -extern ulong_t cr4_value; extern uint_t pentiumpro_bug4046376; extern uint_t pentiumpro_bug4064495; @@ -509,9 +529,13 @@ extern uint64_t rdmsr(uint_t); extern void wrmsr(uint_t, const uint64_t); extern uint64_t xrdmsr(uint_t); extern void xwrmsr(uint_t, const uint64_t); +extern int checked_rdmsr(uint_t, uint64_t *); +extern int checked_wrmsr(uint_t, uint64_t); + extern void invalidate_cache(void); extern ulong_t getcr4(void); extern void setcr4(ulong_t); + extern void mtrr_sync(void); extern void cpu_fast_syscall_enable(void *); @@ -547,6 +571,8 @@ extern int cpuid_opteron_erratum(struct cpu *, uint_t); struct cpuid_info; extern void setx86isalist(void); +extern void cpuid_alloc_space(struct cpu *); +extern void cpuid_free_space(struct cpu *); extern uint_t cpuid_pass1(struct cpu *); extern void cpuid_pass2(struct cpu *); extern void cpuid_pass3(struct cpu *); diff --git a/usr/src/uts/i86pc/vuid2ps2/Makefile b/usr/src/uts/intel/vuid2ps2/Makefile index 05397b2344..39d2380998 100644 --- a/usr/src/uts/i86pc/vuid2ps2/Makefile +++ b/usr/src/uts/intel/vuid2ps2/Makefile @@ -19,9 +19,9 @@ # CDDL HEADER END # # -# uts/i86pc/vuid2ps2/Makefile +# uts/intel/vuid2ps2/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -29,7 +29,7 @@ # This makefile drives the production of the vuid2ps2 streams kernel # module. # -# i86pc implementation architecture dependent +# intel architecture dependent # # @@ -43,12 +43,12 @@ UTSBASE = ../.. MODULE = vuid2ps2 OBJECTS = $(VUIDPS2_OBJS:%=$(OBJS_DIR)/%) LINTS = $(VUIDPS2_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_STRMOD_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_STRMOD_DIR)/$(MODULE) # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -94,4 +94,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/vuid3ps2/Makefile b/usr/src/uts/intel/vuid3ps2/Makefile index d45bc1f8e1..7fad683d16 100644 --- a/usr/src/uts/i86pc/vuid3ps2/Makefile +++ b/usr/src/uts/intel/vuid3ps2/Makefile @@ -19,9 +19,9 @@ # CDDL HEADER END # # -# uts/i86pc/vuid3ps2/Makefile +# uts/intel/vuid3ps2/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -29,7 +29,7 @@ # This makefile drives the production of the vuid3ps2 streams kernel # module. # -# i86pc implementation architecture dependent +# intel architecture dependent # # @@ -43,12 +43,12 @@ UTSBASE = ../.. MODULE = vuid3ps2 OBJECTS = $(VUIDPS2_OBJS:%=$(OBJS_DIR)/%) LINTS = $(VUIDPS2_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_STRMOD_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_STRMOD_DIR)/$(MODULE) # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -94,4 +94,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/vuidm3p/Makefile b/usr/src/uts/intel/vuidm3p/Makefile index 925dd01173..64111cb269 100644 --- a/usr/src/uts/i86pc/vuidm3p/Makefile +++ b/usr/src/uts/intel/vuidm3p/Makefile @@ -19,9 +19,9 @@ # CDDL HEADER END # # -# uts/i86pc/vuidm3p/Makefile +# uts/intel/vuidm3p/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -29,7 +29,7 @@ # This makefile drives the production of the vuidm3p streams kernel # module. # -# i86pc implementation architecture dependent +# intel architecture dependent # # @@ -43,12 +43,12 @@ UTSBASE = ../.. MODULE = vuidm3p OBJECTS = $(VUIDM3P_OBJS:%=$(OBJS_DIR)/%) LINTS = $(VUIDM3P_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_STRMOD_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_STRMOD_DIR)/$(MODULE) # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -94,4 +94,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/vuidm4p/Makefile b/usr/src/uts/intel/vuidm4p/Makefile index adc5a92015..c9ace852f8 100644 --- a/usr/src/uts/i86pc/vuidm4p/Makefile +++ b/usr/src/uts/intel/vuidm4p/Makefile @@ -19,9 +19,9 @@ # CDDL HEADER END # # -# uts/i86pc/vuidm4p/Makefile +# uts/intel/vuidm4p/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -29,7 +29,7 @@ # This makefile drives the production of the vuidm4p streams kernel # module. # -# i86pc implementation architecture dependent +# intel architecture dependent # # @@ -43,12 +43,12 @@ UTSBASE = ../.. MODULE = vuidm4p OBJECTS = $(VUIDM4P_OBJS:%=$(OBJS_DIR)/%) LINTS = $(VUIDM4P_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_STRMOD_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_STRMOD_DIR)/$(MODULE) # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -94,4 +94,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/i86pc/vuidm5p/Makefile b/usr/src/uts/intel/vuidm5p/Makefile index bf7ac45670..042d369814 100644 --- a/usr/src/uts/i86pc/vuidm5p/Makefile +++ b/usr/src/uts/intel/vuidm5p/Makefile @@ -19,9 +19,9 @@ # CDDL HEADER END # # -# uts/i86pc/vuidm5p/Makefile +# uts/intel/vuidm5p/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -29,7 +29,7 @@ # This makefile drives the production of the vuidm5p streams kernel # module. # -# i86pc implementation architecture dependent +# intel architecture dependent # # @@ -43,12 +43,12 @@ UTSBASE = ../.. MODULE = vuidm5p OBJECTS = $(VUIDM5P_OBJS:%=$(OBJS_DIR)/%) LINTS = $(VUIDM5P_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_STRMOD_DIR)/$(MODULE) +ROOTMODULE = $(ROOT_STRMOD_DIR)/$(MODULE) # # Include common rules. # -include $(UTSBASE)/i86pc/Makefile.i86pc +include $(UTSBASE)/intel/Makefile.intel # # Define targets @@ -91,4 +91,4 @@ install: $(INSTALL_DEPS) # # Include common targets. # -include $(UTSBASE)/i86pc/Makefile.targ +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/intel/zmod/Makefile b/usr/src/uts/intel/zmod/Makefile deleted file mode 100644 index 267187911e..0000000000 --- a/usr/src/uts/intel/zmod/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -UTSBASE = ../.. - -MODULE = zmod -OBJECTS = $(ZMOD_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(ZMOD_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE) - -include $(UTSBASE)/intel/Makefile.intel - -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -LDFLAGS += -B reduce -M $(UTSBASE)/common/zmod/mapfile - -# -# For now, disable these lint checks; maintainers should endeavor -# to investigate and remove these for maximum lint coverage. -# Please do not carry these forward to new Makefiles. -# -LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW -LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV - -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/sparc/Makefile b/usr/src/uts/sparc/Makefile index c597432d5c..a551f117e0 100644 --- a/usr/src/uts/sparc/Makefile +++ b/usr/src/uts/sparc/Makefile @@ -21,7 +21,7 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # uts/sparc/Makefile @@ -80,8 +80,8 @@ install_h := TARGET= install_h .KEEP_STATE: -.PARALLEL: $(KMODS) $(CLOSED_KMODS) $(SVVS) $(XMODS) $(CLOSED_XMODS) \ - config $(LINT_DEPS) +.PARALLEL: $(PARALLEL_KMODS) $(CLOSED_KMODS) $(SVVS) $(XMODS) \ + $(CLOSED_XMODS) config $(LINT_DEPS) def all install clean clobber modlist: $(KMODS) $(CLOSED_KMODS) $(SVVS) \ $(XMODS) $(CLOSED_XMODS) config diff --git a/usr/src/uts/sparc/Makefile.files b/usr/src/uts/sparc/Makefile.files index 96d0b63d68..240a348a59 100644 --- a/usr/src/uts/sparc/Makefile.files +++ b/usr/src/uts/sparc/Makefile.files @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -36,6 +36,12 @@ CORE_OBJS += ddi_arch.o \ polled_io.o \ sparc_ddi.o +# +# decompression support +# +CORE_OBJS += adler32.o infblock.o infcodes.o inffast.o \ + inflate.o inftrees.o infutil.o zutil.o zmod.o + # # generic-unix module diff --git a/usr/src/uts/sparc/Makefile.sparc.shared b/usr/src/uts/sparc/Makefile.sparc.shared index a055072202..7df1a468aa 100644 --- a/usr/src/uts/sparc/Makefile.sparc.shared +++ b/usr/src/uts/sparc/Makefile.sparc.shared @@ -376,7 +376,6 @@ MISC_KMODS += ibtl MISC_KMODS += hook MISC_KMODS += neti MISC_KMODS += ctf -MISC_KMODS += zmod MISC_KMODS += mac dls MISC_KMODS += cmlb MISC_KMODS += tem diff --git a/usr/src/uts/sparc/ctf/Makefile b/usr/src/uts/sparc/ctf/Makefile index 16a3f005ad..e97e20fbe1 100644 --- a/usr/src/uts/sparc/ctf/Makefile +++ b/usr/src/uts/sparc/ctf/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -39,7 +39,7 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE) CFLAGS += $(CCVERBOSE) CPPFLAGS += -I$(SRC)/common/ctf -DCTF_OLD_VERSIONS -LDFLAGS += -Breduce -M$(UTSBASE)/common/ctf/mapfile -dy -Nmisc/zmod +LDFLAGS += -Breduce -M$(UTSBASE)/common/ctf/mapfile -dy # # For now, disable these lint checks; maintainers should endeavor diff --git a/usr/src/uts/sparc/dtrace/fbt.c b/usr/src/uts/sparc/dtrace/fbt.c index 91adbfe22a..f4224a6fdb 100644 --- a/usr/src/uts/sparc/dtrace/fbt.c +++ b/usr/src/uts/sparc/dtrace/fbt.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1636,16 +1636,19 @@ fbt_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc) * If we have a parent container, we must manually import it. */ if ((parent = ctf_parent_name(fp)) != NULL) { - struct modctl *mod; + struct modctl *mp = &modules; + struct modctl *mod = NULL; /* * We must iterate over all modules to find the module that * is our parent. */ - for (mod = &modules; mod != NULL; mod = mod->mod_next) { - if (strcmp(mod->mod_filename, parent) == 0) + do { + if (strcmp(mp->mod_modname, parent) == 0) { + mod = mp; break; - } + } + } while ((mp = mp->mod_next) != &modules); if (mod == NULL) goto err; diff --git a/usr/src/uts/sparc/krtld/mapfile b/usr/src/uts/sparc/krtld/mapfile index 6d40dc91c1..708305072d 100644 --- a/usr/src/uts/sparc/krtld/mapfile +++ b/usr/src/uts/sparc/krtld/mapfile @@ -1,5 +1,5 @@ # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # CDDL HEADER START @@ -44,6 +44,7 @@ kobj_load_primary_module; kobj_lookup; kobj_lookup_all; + kobj_module_path; kobj_notify_add; kobj_notify_remove; kobj_open; diff --git a/usr/src/uts/sparc/os/sundep.c b/usr/src/uts/sparc/os/sundep.c index 1c64e705c1..42859211d9 100644 --- a/usr/src/uts/sparc/os/sundep.c +++ b/usr/src/uts/sparc/os/sundep.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -135,7 +134,7 @@ kern_setup1(void) /* * We assume that the u-area is zeroed out. */ - u.u_cmask = (mode_t)CMASK; + PTOU(curproc)->u_cmask = (mode_t)CMASK; thread_init(); /* init thread_free list */ pid_init(); /* initialize pid (proc) table */ diff --git a/usr/src/uts/sparc/sys/archsystm.h b/usr/src/uts/sparc/sys/archsystm.h index 23e9797e78..921a7f4c1a 100644 --- a/usr/src/uts/sparc/sys/archsystm.h +++ b/usr/src/uts/sparc/sys/archsystm.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -88,10 +88,10 @@ extern u_longlong_t gettick(void); extern uint64_t gettick_counter(void); extern int xcopyin_little(const void *, void *, size_t); extern int xcopyout_little(const void *, void *, size_t); -extern void xregs_getgfiller(klwp_id_t lwp, caddr_t xrp); -extern void xregs_setgfiller(klwp_id_t lwp, caddr_t xrp); -extern void xregs_getfpfiller(klwp_id_t lwp, caddr_t xrp); -extern void xregs_setfpfiller(klwp_id_t lwp, caddr_t xrp); +extern void xregs_getgfiller(struct _klwp *lwp, caddr_t xrp); +extern void xregs_setgfiller(struct _klwp *lwp, caddr_t xrp); +extern void xregs_getfpfiller(struct _klwp *lwp, caddr_t xrp); +extern void xregs_setfpfiller(struct _klwp *lwp, caddr_t xrp); struct ucontext; extern void xregs_clrptr(struct _klwp *, struct ucontext *); @@ -119,6 +119,8 @@ extern void doflush(void *); extern uint_t cpu_hwcap_flags; +#define cpr_dprintf prom_printf + #endif /* _KERNEL && !_ASM */ diff --git a/usr/src/uts/sparc/sys/kdi_machimpl.h b/usr/src/uts/sparc/sys/kdi_machimpl.h index a9c973ba7f..c4eff32875 100644 --- a/usr/src/uts/sparc/sys/kdi_machimpl.h +++ b/usr/src/uts/sparc/sys/kdi_machimpl.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -97,6 +96,8 @@ extern void kdi_watchdog_restore(void); extern void kdi_tlb_page_lock(caddr_t, int); extern void kdi_tlb_page_unlock(caddr_t, int); +extern void kmdb_enter(void); + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/sparc/v9/os/v9dep.c b/usr/src/uts/sparc/v9/os/v9dep.c index 009621abdc..a22cadb54a 100644 --- a/usr/src/uts/sparc/v9/os/v9dep.c +++ b/usr/src/uts/sparc/v9/os/v9dep.c @@ -23,7 +23,7 @@ /* All Rights Reserved */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -961,7 +961,7 @@ sendsig(int sig, k_siginfo_t *sip, void (*hdlr)()) * and validate the stack requirements for the signal handler * context. on_fault will catch any faults. */ - newstack = (sigismember(&u.u_sigonstack, sig) && + newstack = (sigismember(&PTOU(curproc)->u_sigonstack, sig) && !(lwp->lwp_sigaltstack.ss_flags & (SS_ONSTACK|SS_DISABLE))); tos = (caddr_t)rp->r_sp + STACK_BIAS; @@ -1290,7 +1290,7 @@ sendsig32(int sig, k_siginfo_t *sip, void (*hdlr)()) * and validate the stack requirements for the signal handler * context. on_fault will catch any faults. */ - newstack = (sigismember(&u.u_sigonstack, sig) && + newstack = (sigismember(&PTOU(curproc)->u_sigonstack, sig) && !(lwp->lwp_sigaltstack.ss_flags & (SS_ONSTACK|SS_DISABLE))); tos = (void *)(uintptr_t)(uint32_t)rp->r_sp; diff --git a/usr/src/uts/sparc/zmod/Makefile b/usr/src/uts/sparc/zmod/Makefile deleted file mode 100644 index 2cd46b6a11..0000000000 --- a/usr/src/uts/sparc/zmod/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -UTSBASE = ../.. - -MODULE = zmod -OBJECTS = $(ZMOD_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(ZMOD_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE) - -include $(UTSBASE)/sparc/Makefile.sparc - -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -CFLAGS += $(CCVERBOSE) -LDFLAGS += -B reduce -M $(UTSBASE)/common/zmod/mapfile - -# -# For now, disable these lint checks; maintainers should endeavor -# to investigate and remove these for maximum lint coverage. -# Please do not carry these forward to new Makefiles. -# -LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW -LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV - -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -include $(UTSBASE)/sparc/Makefile.targ diff --git a/usr/src/uts/sun/sys/bootconf.h b/usr/src/uts/sun/sys/bootconf.h index c96f8aa90b..8d8c361139 100644 --- a/usr/src/uts/sun/sys/bootconf.h +++ b/usr/src/uts/sun/sys/bootconf.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -241,6 +241,7 @@ extern int netboot; extern int swaploaded; extern int modrootloaded; extern char kern_bootargs[]; +extern char *kobj_module_path; extern char *default_path; extern char *dhcack; extern char *netdev_path; diff --git a/usr/src/uts/sun4/ml/subr_asm.s b/usr/src/uts/sun4/ml/subr_asm.s index 7055aeed25..acfa423775 100644 --- a/usr/src/uts/sun4/ml/subr_asm.s +++ b/usr/src/uts/sun4/ml/subr_asm.s @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -445,6 +445,22 @@ kdi_cpu_index(void) #endif /* lint */ +#if defined(lint) || defined(__lint) +void +kmdb_enter(void) +{ +} + +#else /* lint */ + + ENTRY_NP(kmdb_enter) + t ST_KMDB_TRAP + retl + nop + SET_SIZE(kmdb_enter) + +#endif /* lint */ + /* * The Spitfire floating point code has been changed not to use install/ * save/restore/fork/freectx() because of the special memcpy library diff --git a/usr/src/uts/sun4/os/cpu_states.c b/usr/src/uts/sun4/os/cpu_states.c index d45a547443..d7d5e659dd 100644 --- a/usr/src/uts/sun4/os/cpu_states.c +++ b/usr/src/uts/sun4/os/cpu_states.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -35,6 +35,7 @@ #include <sys/cpu_sgnblk_defs.h> #include <sys/ivintr.h> #include <sys/kdi.h> +#include <sys/kdi_machimpl.h> #include <sys/callb.h> #include <sys/wdt.h> @@ -259,7 +260,7 @@ debug_enter(char *msg) (void) setjmp(&curthread->t_pcb); if (boothowto & RB_DEBUG) - kdi_dvec_enter(); + kmdb_enter(); else prom_enter_mon(); diff --git a/usr/src/uts/sun4/os/dtrace_subr.c b/usr/src/uts/sun4/os/dtrace_subr.c index d1afbe29b0..58c789f43d 100644 --- a/usr/src/uts/sun4/os/dtrace_subr.c +++ b/usr/src/uts/sun4/os/dtrace_subr.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -227,3 +227,13 @@ dtrace_safe_defer_signal(void) return (1); } + +/* + * Additional artificial frames for the machine type. For SPARC, we're already + * accounted for, so return 0. + */ +int +dtrace_mach_aframes(void) +{ + return (0); +} diff --git a/usr/src/uts/sun4/os/machdep.c b/usr/src/uts/sun4/os/machdep.c index 821999a3c0..2dd3544868 100644 --- a/usr/src/uts/sun4/os/machdep.c +++ b/usr/src/uts/sun4/os/machdep.c @@ -56,7 +56,11 @@ #include <sys/sysmacros.h> #include <sys/promif.h> #include <sys/pool_pset.h> +#include <sys/mem.h> +#include <sys/dumphdr.h> #include <vm/seg_kmem.h> +#include <sys/hold_page.h> +#include <sys/cpu.h> int maxphys = MMU_PAGESIZE * 16; /* 128k */ int klustsize = MMU_PAGESIZE * 16; /* 128k */ @@ -676,6 +680,7 @@ void mach_kdi_init(kdi_t *kdi) { kdi->kdi_plat_call = kdi_plat_call; + kdi->kdi_kmdb_enter = kmdb_enter; kdi->mkdi_cpu_index = kdi_cpu_index; kdi->mkdi_trap_vatotte = kdi_trap_vatotte; kdi->mkdi_kernpanic = kdi_kernpanic; @@ -774,3 +779,58 @@ get_cpu_mstate(cpu_t *cpu, hrtime_t *times) times[CMS_SYSTEM] += intracct[i]; } } + +void +mach_cpu_pause(volatile char *safe) +{ + /* + * This cpu is now safe. + */ + *safe = PAUSE_WAIT; + membar_enter(); /* make sure stores are flushed */ + + /* + * Now we wait. When we are allowed to continue, safe + * will be set to PAUSE_IDLE. + */ + while (*safe != PAUSE_IDLE) + SMT_PAUSE(); +} + +/*ARGSUSED*/ +int +plat_mem_valid_page(uintptr_t pageaddr, uio_rw_t rw) +{ + return (0); +} + +int +dump_plat_addr() +{ + return (0); +} + +void +dump_plat_pfn() +{ +} + +/* ARGSUSED */ +int +dump_plat_data(void *dump_cdata) +{ + return (0); +} + +/* ARGSUSED */ +int +plat_hold_page(pfn_t pfn, int lock, page_t **pp_ret) +{ + return (PLAT_HOLD_OK); +} + +/* ARGSUSED */ +void +plat_release_page(page_t *pp) +{ +} diff --git a/usr/src/uts/sun4/os/mlsetup.c b/usr/src/uts/sun4/os/mlsetup.c index d66c6c13c1..227127092c 100644 --- a/usr/src/uts/sun4/os/mlsetup.c +++ b/usr/src/uts/sun4/os/mlsetup.c @@ -191,7 +191,7 @@ mlsetup(struct regs *rp, void *cif, kfpu_t *fp) CPU->cpu_dispatch_pri = t0.t_pri; /* - * Initialize thread/cpu microstate accounting here + * Initialize thread/cpu microstate accounting */ init_mstate(&t0, LMS_SYSTEM); init_cpu_mstate(CPU, CMS_SYSTEM); diff --git a/usr/src/uts/sun4/os/prom_subr.c b/usr/src/uts/sun4/os/prom_subr.c index 46bafd606a..f3781a1c52 100644 --- a/usr/src/uts/sun4/os/prom_subr.c +++ b/usr/src/uts/sun4/os/prom_subr.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -44,6 +43,7 @@ #include <sys/rwlock.h> #include <sys/reboot.h> #include <sys/kdi.h> +#include <sys/kdi_machimpl.h> /* * We are called with a pointer to a cell-sized argument array. @@ -349,7 +349,7 @@ kern_postprom(void) return; /* prom lock is held recursively by this CPU */ if ((boothowto & RB_DEBUG) && prom_exit_enter_debugger) - kdi_dvec_enter(); + kmdb_enter(); prom_thread = NULL; membar_producer(); diff --git a/usr/src/uts/sun4/os/startup.c b/usr/src/uts/sun4/os/startup.c index b91dab8ac7..af968271e9 100644 --- a/usr/src/uts/sun4/os/startup.c +++ b/usr/src/uts/sun4/os/startup.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -202,6 +202,12 @@ pgcnt_t segziosize = 0; /* size of zio segment in pages */ struct vnode kdebugvp; /* + * VA range available to the debugger + */ +const caddr_t kdi_segdebugbase = (const caddr_t)SEGDEBUGBASE; +const size_t kdi_segdebugsize = SEGDEBUGSIZE; + +/* * Segment for relocated kernel structures in 64-bit large RAM kernels */ struct seg kmem64; @@ -1610,8 +1616,8 @@ startup_modules(void) maxmem = physmem; /* Set segkp limits. */ - ncbase = (caddr_t)SEGDEBUGBASE; - ncend = (caddr_t)SEGDEBUGBASE; + ncbase = kdi_segdebugbase; + ncend = kdi_segdebugbase; /* * Initialize the hat layer. @@ -2710,8 +2716,7 @@ kvm_init(void) /* * Create a segment for the debugger. */ - (void) seg_attach(&kas, (caddr_t)SEGDEBUGBASE, (size_t)SEGDEBUGSIZE, - &kdebugseg); + (void) seg_attach(&kas, kdi_segdebugbase, kdi_segdebugsize, &kdebugseg); (void) segkmem_create(&kdebugseg); rw_exit(&kas.a_lock); diff --git a/usr/src/uts/sun4u/Makefile b/usr/src/uts/sun4u/Makefile index 0c849ab7d2..df4e9677cd 100644 --- a/usr/src/uts/sun4u/Makefile +++ b/usr/src/uts/sun4u/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -83,7 +82,7 @@ check := TARGET= check .KEEP_STATE: -.PARALLEL: $(KMODS) $(CLOSED_KMODS) $(XMODS) $(CLOSED_XMODS) \ +.PARALLEL: $(PARALLEL_KMODS) $(CLOSED_KMODS) $(XMODS) $(CLOSED_XMODS) \ $(IMPLEMENTATIONS) $(CLOSED_IMPLEMENTATIONS) \ modlist modlist.sparc diff --git a/usr/src/uts/sun4u/Makefile.sun4u.shared b/usr/src/uts/sun4u/Makefile.sun4u.shared index 3a2f922f5c..c1398f6afc 100644 --- a/usr/src/uts/sun4u/Makefile.sun4u.shared +++ b/usr/src/uts/sun4u/Makefile.sun4u.shared @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -37,6 +37,11 @@ PROMIF = ieee1275 PSMBASE = $(UTSBASE)/../psm # +# uname -m value +# +UNAME_M = $(PLATFORM) + +# # Definitions for the platform-specific /platform directories. # # PLATFORMS designates those sun4u machines which have no platform diff --git a/usr/src/uts/sun4u/boston/Makefile b/usr/src/uts/sun4u/boston/Makefile index d791410b70..5b9dd24fa8 100644 --- a/usr/src/uts/sun4u/boston/Makefile +++ b/usr/src/uts/sun4u/boston/Makefile @@ -20,7 +20,7 @@ # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -77,7 +77,6 @@ BOSTON_CRYPTO_LINKS += aes256 install: $(ROOT_BOSTON_DIR) \ $(USR_BOSTON_DIR) \ $(USR_BOSTON_INC_DIR) \ - $(USR_BOSTON_SBIN_EEPROM) \ $(USR_BOSTON_SBIN_PRTDIAG) \ $(USR_BOSTON_SBIN_FRUADM) \ $(USR_BOSTON_SBIN_TRAPSTAT) \ diff --git a/usr/src/uts/sun4u/boston/Makefile.boston b/usr/src/uts/sun4u/boston/Makefile.boston index 5750bfa08e..d43099f1af 100644 --- a/usr/src/uts/sun4u/boston/Makefile.boston +++ b/usr/src/uts/sun4u/boston/Makefile.boston @@ -20,7 +20,7 @@ # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -53,7 +53,6 @@ USR_BOSTON_LINKED_DIR = $(USR_PLAT_DIR)/$(LINKED_PLATFORM) USR_BOSTON_INC_DIR = $(USR_BOSTON_DIR)/include USR_BOSTON_ISYS_DIR = $(USR_BOSTON_INC_DIR)/sys USR_BOSTON_SBIN_DIR = $(USR_BOSTON_DIR)/sbin -USR_BOSTON_SBIN_EEPROM = $(USR_BOSTON_SBIN_DIR)/eeprom USR_BOSTON_SBIN_PRTDIAG = $(USR_BOSTON_SBIN_DIR)/prtdiag USR_BOSTON_SBIN_FRUADM = $(USR_BOSTON_SBIN_DIR)/fruadm USR_BOSTON_SBIN_TRAPSTAT = $(USR_BOSTON_SBIN_DIR)/trapstat diff --git a/usr/src/uts/sun4u/boston/Makefile.targ b/usr/src/uts/sun4u/boston/Makefile.targ index baecde5a8a..ece1ba33e1 100644 --- a/usr/src/uts/sun4u/boston/Makefile.targ +++ b/usr/src/uts/sun4u/boston/Makefile.targ @@ -20,7 +20,7 @@ # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -67,9 +67,6 @@ $(USR_BOSTON_INC_DIR): $(USR_BOSTON_DIR) $(USR_BOSTON_SBIN_DIR): $(USR_BOSTON_DIR) $(INS.dir.root.bin) -$(USR_BOSTON_SBIN_EEPROM): $(USR_BOSTON_SBIN_DIR) - $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/sbin/eeprom $@ $(CHOWNLINK) $(CHGRPLINK) - $(USR_BOSTON_SBIN_PRTDIAG): $(USR_BOSTON_SBIN_DIR) $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/sbin/prtdiag $@ $(CHOWNLINK) $(CHGRPLINK) diff --git a/usr/src/uts/sun4u/mpxu/Makefile b/usr/src/uts/sun4u/mpxu/Makefile index a5749ac140..371dc0a151 100644 --- a/usr/src/uts/sun4u/mpxu/Makefile +++ b/usr/src/uts/sun4u/mpxu/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ # # # uts/sun4u/mpxu/Makefile -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -86,7 +85,6 @@ MPXU_CRYPTO_LINKS += aes256 install: $(ROOT_MPXU_DIR) $(USR_MPXU_DIR) \ $(USR_MPXU_INC_DIR) \ - $(USR_MPXU_SBIN_EEPROM) \ $(USR_MPXU_SBIN_PRTDIAG) \ $(USR_MPXU_SBIN_TRAPSTAT) \ $(USR_MPXU_SBIN_FRUADM) \ diff --git a/usr/src/uts/sun4u/mpxu/Makefile.mpxu.shared b/usr/src/uts/sun4u/mpxu/Makefile.mpxu.shared index 3bb083b7e1..24c701e48c 100644 --- a/usr/src/uts/sun4u/mpxu/Makefile.mpxu.shared +++ b/usr/src/uts/sun4u/mpxu/Makefile.mpxu.shared @@ -20,7 +20,7 @@ # # # uts/sun4u/mpxu/Makefile.mpxu -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -56,7 +56,6 @@ USR_MPXU_DIR = $(USR_PLAT_DIR)/SUNW,Sun-Fire-V240 USR_MPXU_INC_DIR = $(USR_MPXU_DIR)/include USR_MPXU_ISYS_DIR = $(USR_MPXU_INC_DIR)/sys USR_MPXU_SBIN_DIR = $(USR_MPXU_DIR)/sbin -USR_MPXU_SBIN_EEPROM = $(USR_MPXU_SBIN_DIR)/eeprom USR_MPXU_SBIN_PRTDIAG = $(USR_MPXU_SBIN_DIR)/prtdiag USR_MPXU_SBIN_TRAPSTAT = $(USR_MPXU_SBIN_DIR)/trapstat USR_MPXU_SBIN_FRUADM = $(USR_MPXU_SBIN_DIR)/fruadm diff --git a/usr/src/uts/sun4u/mpxu/Makefile.targ.shared b/usr/src/uts/sun4u/mpxu/Makefile.targ.shared index fb5225c2c1..f9c46c5176 100644 --- a/usr/src/uts/sun4u/mpxu/Makefile.targ.shared +++ b/usr/src/uts/sun4u/mpxu/Makefile.targ.shared @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -71,9 +70,6 @@ $(USR_MPXU_ISYS_DIR): $(USR_MPXU_INC_DIR) $(USR_MPXU_SBIN_DIR): $(USR_MPXU_DIR) $(INS.dir.root.bin) -$(USR_MPXU_SBIN_EEPROM): $(USR_MPXU_SBIN_DIR) - $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/sbin/eeprom $@ $(CHOWNLINK) $(CHGRPLINK) - $(USR_MPXU_SBIN_PRTDIAG): $(USR_MPXU_SBIN_DIR) $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/sbin/prtdiag $@ $(CHOWNLINK) $(CHGRPLINK) diff --git a/usr/src/uts/sun4u/opl/Makefile b/usr/src/uts/sun4u/opl/Makefile index f4f3831a43..5a739329d4 100644 --- a/usr/src/uts/sun4u/opl/Makefile +++ b/usr/src/uts/sun4u/opl/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -82,7 +82,6 @@ OPL_CRYPTO_LINKS += aes256 install: $(ROOT_OPL_DIR) $(USR_OPL_DIR) \ $(USR_OPL_INC_DIR) \ $(USR_OPL_SBIN_DIR) \ - $(USR_OPL_SBIN_EEPROM) \ $(USR_OPL_SBIN_PRTDIAG) \ $(USR_OPL_SBIN_TRAPSTAT) \ $(USR_OPL_SBIN_FRUADM) \ diff --git a/usr/src/uts/sun4u/opl/Makefile.opl.shared b/usr/src/uts/sun4u/opl/Makefile.opl.shared index ec5e0a6d2d..b92abb334e 100644 --- a/usr/src/uts/sun4u/opl/Makefile.opl.shared +++ b/usr/src/uts/sun4u/opl/Makefile.opl.shared @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -59,7 +59,6 @@ ROOT_PLAT_MISC_DIRS_32 += $(ROOT_OPL_MISC_DIR_32) USR_OPL_DIR = $(USR_PLAT_DIR)/SUNW,SPARC-Enterprise USR_OPL_LIB_DIR = $(USR_OPL_DIR)/lib USR_OPL_SBIN_DIR = $(USR_OPL_DIR)/sbin -USR_OPL_SBIN_EEPROM = $(USR_OPL_SBIN_DIR)/eeprom USR_OPL_SBIN_PRTDIAG = $(USR_OPL_SBIN_DIR)/prtdiag USR_OPL_SBIN_TRAPSTAT = $(USR_OPL_SBIN_DIR)/trapstat USR_OPL_SBIN_FRUADM = $(USR_OPL_SBIN_DIR)/fruadm diff --git a/usr/src/uts/sun4u/opl/Makefile.targ.shared b/usr/src/uts/sun4u/opl/Makefile.targ.shared index 69191fcf54..629a61110b 100644 --- a/usr/src/uts/sun4u/opl/Makefile.targ.shared +++ b/usr/src/uts/sun4u/opl/Makefile.targ.shared @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -73,9 +73,6 @@ $(USR_OPL_INC_DIR): $(USR_OPL_DIR) $(USR_PSM_INCL_DIR) $(USR_OPL_SBIN_DIR): $(USR_OPL_DIR) $(USR_PSM_SBIN_DIR) $(INS.dir.root.bin) -$(USR_OPL_SBIN_EEPROM): $(USR_OPL_SBIN_DIR) - $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/sbin/eeprom $@ $(CHOWNLINK) $(CHGRPLINK) - $(USR_OPL_SBIN_PRTDIAG): $(USR_OPL_SBIN_DIR) $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/sbin/prtdiag $@ $(CHOWNLINK) $(CHGRPLINK) diff --git a/usr/src/uts/sun4u/os/cpr_impl.c b/usr/src/uts/sun4u/os/cpr_impl.c index 801ef7ba8a..caefea794b 100644 --- a/usr/src/uts/sun4u/os/cpr_impl.c +++ b/usr/src/uts/sun4u/os/cpr_impl.c @@ -253,7 +253,7 @@ i_cpr_mp_setup(void) if (ncpus > 1) { sfmmu_init_tsbs(); - if (cpr_debug & LEVEL1) { + if (cpr_debug & CPR_DEBUG1) { prom_interpret("stdout @ swap l!", (uintptr_t)&tmpout, 0, 0, 0, 0); str = "MP startup...\r\n"; @@ -279,7 +279,7 @@ i_cpr_mp_setup(void) pause_cpus(NULL); mutex_exit(&cpu_lock); - if (cpr_debug & LEVEL1) { + if (cpr_debug & CPR_DEBUG1) { str = "MP paused...\r\n"; (void) prom_write(tmpout, str, strlen(str), 0, 0); } @@ -505,7 +505,7 @@ void i_cpr_machdep_setup(void) { if (ncpus > 1) { - DEBUG1(errp("MP restarted...\n")); + CPR_DEBUG(CPR_DEBUG1, "MP restarted...\n"); mutex_enter(&cpu_lock); start_cpus(); mutex_exit(&cpu_lock); @@ -587,8 +587,8 @@ i_cpr_write_machdep(vnode_t *vp) m_info.ksb = (uint32_t)STACK_BIAS; m_info.kpstate = (uint16_t)getpstate(); m_info.kwstate = (uint16_t)getwstate(); - DEBUG1(errp("stack bias 0x%x, pstate 0x%x, wstate 0x%x\n", - m_info.ksb, m_info.kpstate, m_info.kwstate)); + CPR_DEBUG(CPR_DEBUG1, "stack bias 0x%x, pstate 0x%x, wstate 0x%x\n", + m_info.ksb, m_info.kpstate, m_info.kwstate); ltp = &ttolwp(curthread)->lwp_qsav; m_info.qsav_pc = (cpr_ext)ltp->val[0]; @@ -643,9 +643,9 @@ i_cpr_write_machdep(vnode_t *vp) void i_cpr_save_machdep_info(void) { - DEBUG5(errp("jumpback size = 0x%lx\n", + CPR_DEBUG(CPR_DEBUG5, "jumpback size = 0x%lx\n", (uintptr_t)&i_cpr_end_jumpback - - (uintptr_t)i_cpr_resume_setup)); + (uintptr_t)i_cpr_resume_setup); /* * Verify the jumpback code all falls in one page. @@ -856,7 +856,7 @@ i_cpr_save_sensitive_kpages(void) pages = spages - vpages; str = "i_cpr_save_sensitive_kpages:"; - DEBUG7(errp(pages_fmt, "before", str, spages, vpages, pages)); + CPR_DEBUG(CPR_DEBUG7, pages_fmt, "before", str, spages, vpages, pages); /* * Allocate space to save the clean sensitive kpages @@ -876,9 +876,9 @@ i_cpr_save_sensitive_kpages(void) addr = i_cpr_storage_data_alloc(pages, &i_cpr_storage_data_sz, retry_cnt); if (addr == NULL) { - DEBUG7(errp( + CPR_DEBUG(CPR_DEBUG7, "\n%s can't allocate data storage space!\n", - str)); + str); return (ENOMEM); } i_cpr_storage_data_base = addr; @@ -915,22 +915,22 @@ i_cpr_save_sensitive_kpages(void) i_cpr_count_sensitive_kpages(REGULAR_BITMAP, cpr_setbit); vpages = cpr_count_volatile_pages(REGULAR_BITMAP, cpr_clrbit); - DEBUG7(errp(pages_fmt, "after ", str, - spages, vpages, spages - vpages)); + CPR_DEBUG(CPR_DEBUG7, pages_fmt, "after ", str, + spages, vpages, spages - vpages); /* * Returns 0 on success, -1 if too few descriptors, and * ENOMEM if not enough space to save sensitive pages */ - DEBUG1(errp("compressing pages to storage...\n")); + CPR_DEBUG(CPR_DEBUG1, "compressing pages to storage...\n"); error = i_cpr_save_to_storage(); if (error == 0) { /* Saving to storage succeeded */ - DEBUG1(errp("compressed %d pages\n", - sensitive_pages_saved)); + CPR_DEBUG(CPR_DEBUG1, "compressed %d pages\n", + sensitive_pages_saved); break; } else if (error == -1) - DEBUG1(errp("%s too few descriptors\n", str)); + CPR_DEBUG(CPR_DEBUG1, "%s too few descriptors\n", str); } if (error == -1) error = ENOMEM; @@ -958,9 +958,10 @@ i_cpr_storage_data_alloc(pgcnt_t pages, pgcnt_t *alloc_pages, int retry_cnt) */ alloc_pcnt = INITIAL_ALLOC_PCNT; *alloc_pages = (pages * alloc_pcnt) / INTEGRAL; - DEBUG7(errp("%s sensitive pages: %ld\n", str, pages)); - DEBUG7(errp("%s initial est pages: %ld, alloc %ld%%\n", - str, *alloc_pages, alloc_pcnt)); + CPR_DEBUG(CPR_DEBUG7, "%s sensitive pages: %ld\n", str, pages); + CPR_DEBUG(CPR_DEBUG7, + "%s initial est pages: %ld, alloc %ld%%\n", + str, *alloc_pages, alloc_pcnt); } else { /* * calculate the prior compression percentage (x100) @@ -969,7 +970,7 @@ i_cpr_storage_data_alloc(pgcnt_t pages, pgcnt_t *alloc_pages, int retry_cnt) ASSERT(sensitive_pages_saved != 0); last_pcnt = (mmu_btopr(sensitive_size_saved) * INTEGRAL) / sensitive_pages_saved; - DEBUG7(errp("%s last ratio %ld%%\n", str, last_pcnt)); + CPR_DEBUG(CPR_DEBUG7, "%s last ratio %ld%%\n", str, last_pcnt); /* * new estimated storage size is based on @@ -979,12 +980,12 @@ i_cpr_storage_data_alloc(pgcnt_t pages, pgcnt_t *alloc_pages, int retry_cnt) alloc_pcnt = MAX(last_pcnt, INITIAL_ALLOC_PCNT) + (retry_cnt * 5); *alloc_pages = (pages * alloc_pcnt) / INTEGRAL; - DEBUG7(errp("%s Retry est pages: %ld, alloc %ld%%\n", - str, *alloc_pages, alloc_pcnt)); + CPR_DEBUG(CPR_DEBUG7, "%s Retry est pages: %ld, alloc %ld%%\n", + str, *alloc_pages, alloc_pcnt); } addr = kmem_alloc(mmu_ptob(*alloc_pages), KM_NOSLEEP); - DEBUG7(errp("%s alloc %ld pages\n", str, *alloc_pages)); + CPR_DEBUG(CPR_DEBUG7, "%s alloc %ld pages\n", str, *alloc_pages); return (addr); } @@ -1033,9 +1034,10 @@ i_cpr_compress_and_save(int chunks, pfn_t spfn, pgcnt_t pages) */ descp = i_cpr_storage_desc_base + chunks - 1; if (descp >= i_cpr_storage_desc_end) { - DEBUG1(errp("ran out of descriptors, base 0x%p, chunks %d, " - "end 0x%p, descp 0x%p\n", i_cpr_storage_desc_base, chunks, - i_cpr_storage_desc_end, descp)); + CPR_DEBUG(CPR_DEBUG1, "ran out of descriptors, base 0x%p, " + "chunks %d, end 0x%p, descp 0x%p\n", + i_cpr_storage_desc_base, chunks, + i_cpr_storage_desc_end, descp); return (-1); } ASSERT(descp->csd_dirty_spfn == (uint_t)-1); @@ -1077,9 +1079,9 @@ i_cpr_compress_and_save(int chunks, pfn_t spfn, pgcnt_t pages) sensitive_write_ptr += datalen; } else { remaining = (i_cpr_storage_data_end - sensitive_write_ptr); - DEBUG1(errp("i_cpr_compress_and_save: The storage " + CPR_DEBUG(CPR_DEBUG1, "i_cpr_compress_and_save: The storage " "space is too small!\ngot %d, want %d\n\n", - remaining, (remaining + datalen))); + remaining, (remaining + datalen)); #ifdef DEBUG /* * Check to see if the content of the sensitive pages that we @@ -1088,10 +1090,11 @@ i_cpr_compress_and_save(int chunks, pfn_t spfn, pgcnt_t pages) test_usum = checksum32(CPR->c_mapping_area, mmu_ptob(pages)); descp->csd_usum = cpd.cpd_usum; if (test_usum != descp->csd_usum) { - DEBUG1(errp("\nWARNING: i_cpr_compress_and_save: " + CPR_DEBUG(CPR_DEBUG1, "\nWARNING: " + "i_cpr_compress_and_save: " "Data in the range of pfn 0x%lx to pfn " "0x%lx has changed after they are saved " - "into storage.", spfn, (spfn + pages - 1))); + "into storage.", spfn, (spfn + pages - 1)); } #endif error = ENOMEM; @@ -1135,9 +1138,9 @@ i_cpr_count_sensitive_kpages(int mapflag, bitfunc_t bitfunc) segkmem_cnt += cpr_count_pages(kmem64.s_base, kmem64.s_size, mapflag, bitfunc, DBG_SHOWRANGE); - DEBUG7(errp("\ni_cpr_count_sensitive_kpages:\n" + CPR_DEBUG(CPR_DEBUG7, "\ni_cpr_count_sensitive_kpages:\n" "\tkdata_cnt %ld + segkmem_cnt %ld = %ld pages\n", - kdata_cnt, segkmem_cnt, kdata_cnt + segkmem_cnt)); + kdata_cnt, segkmem_cnt, kdata_cnt + segkmem_cnt); return (kdata_cnt + segkmem_cnt); } @@ -1185,9 +1188,9 @@ i_cpr_storage_desc_alloc(csd_t **basepp, pgcnt_t *pgsp, csd_t **endpp, chunks = cpr_contig_pages(NULL, STORAGE_DESC_ALLOC) + EXTRA_DESCS; npages = mmu_btopr(sizeof (**basepp) * (pgcnt_t)chunks); - DEBUG7(errp("%s chunks %d, ", str, chunks)); + CPR_DEBUG(CPR_DEBUG7, "%s chunks %d, ", str, chunks); } else { - DEBUG7(errp("%s retry %d: ", str, retry)); + CPR_DEBUG(CPR_DEBUG7, "%s retry %d: ", str, retry); npages = *pgsp + 1; } /* Free old descriptors, if any */ @@ -1196,16 +1199,16 @@ i_cpr_storage_desc_alloc(csd_t **basepp, pgcnt_t *pgsp, csd_t **endpp, descp = *basepp = kmem_alloc(mmu_ptob(npages), KM_NOSLEEP); if (descp == NULL) { - DEBUG7(errp("%s no space for descriptors!\n", str)); + CPR_DEBUG(CPR_DEBUG7, "%s no space for descriptors!\n", str); return (ENOMEM); } *pgsp = npages; len = mmu_ptob(npages); end = *endpp = descp + (len / (sizeof (**basepp))); - DEBUG7(errp("npages 0x%lx, len 0x%lx, items 0x%lx\n\t*basepp " + CPR_DEBUG(CPR_DEBUG7, "npages 0x%lx, len 0x%lx, items 0x%lx\n\t*basepp " "%p, *endpp %p\n", npages, len, (len / (sizeof (**basepp))), - *basepp, *endpp)); + *basepp, *endpp); i_cpr_storage_desc_init(descp, npages, end); return (0); } @@ -1252,8 +1255,8 @@ i_cpr_dump_sensitive_kpages(vnode_t *vp) prom_printf(" \b"); } - DEBUG7(errp("\ni_cpr_dump_sensitive_kpages: dumped %ld\n", - i_cpr_sensitive_pgs_dumped)); + CPR_DEBUG(CPR_DEBUG7, "\ni_cpr_dump_sensitive_kpages: dumped %ld\n", + i_cpr_sensitive_pgs_dumped); return (0); } @@ -1326,7 +1329,7 @@ cpr_dump_sensitive(vnode_t *vp, csd_t *descp) /* Write cpr page descriptor */ error = cpr_write(vp, (caddr_t)&cpd, sizeof (cpd)); if (error) { - DEBUG7(errp("descp: %p\n", descp)); + CPR_DEBUG(CPR_DEBUG7, "descp: %p\n", descp); #ifdef DEBUG debug_enter("cpr_dump_sensitive: cpr_write() page " "descriptor failed!\n"); @@ -1339,10 +1342,10 @@ cpr_dump_sensitive(vnode_t *vp, csd_t *descp) /* Write page data */ error = cpr_write(vp, (caddr_t)datap, cpd.cpd_length); if (error) { - DEBUG7(errp("error: %x\n", error)); - DEBUG7(errp("descp: %p\n", descp)); - DEBUG7(errp("cpr_write(%p, %p , %lx)\n", vp, datap, - cpd.cpd_length)); + CPR_DEBUG(CPR_DEBUG7, "error: %x\n", error); + CPR_DEBUG(CPR_DEBUG7, "descp: %p\n", descp); + CPR_DEBUG(CPR_DEBUG7, "cpr_write(%p, %p , %lx)\n", vp, datap, + cpd.cpd_length); #ifdef DEBUG debug_enter("cpr_dump_sensitive: cpr_write() data failed!\n"); #endif @@ -1367,9 +1370,9 @@ i_cpr_check_pgs_dumped(uint_t pgs_expected, uint_t regular_pgs_dumped) total_pgs_dumped = regular_pgs_dumped + i_cpr_sensitive_pgs_dumped; - DEBUG7(errp("\ncheck_pgs: reg %d + sens %ld = %d, expect %d\n\n", - regular_pgs_dumped, i_cpr_sensitive_pgs_dumped, - total_pgs_dumped, pgs_expected)); + CPR_DEBUG(CPR_DEBUG7, "\ncheck_pgs: reg %d + sens %ld = %d, " + "expect %d\n\n", regular_pgs_dumped, i_cpr_sensitive_pgs_dumped, + total_pgs_dumped, pgs_expected); if (pgs_expected == total_pgs_dumped) return (0); @@ -1565,8 +1568,9 @@ i_cpr_find_ppages(void) * (non-page_t pages - seg pages + vnode pages) */ ppage_count = pcnt - scnt + vcnt; - DEBUG1(errp("find_ppages: pcnt %ld - scnt %ld + vcnt %ld = %ld\n", - pcnt, scnt, vcnt, ppage_count)); + CPR_DEBUG(CPR_DEBUG1, + "find_ppages: pcnt %ld - scnt %ld + vcnt %ld = %ld\n", + pcnt, scnt, vcnt, ppage_count); /* * alloc array of pfn_t to store phys page list @@ -1633,7 +1637,7 @@ i_cpr_save_ppages(void) dst += MMU_PAGESIZE; } - DEBUG1(errp("saved %ld prom pages\n", ppage_count)); + CPR_DEBUG(CPR_DEBUG1, "saved %ld prom pages\n", ppage_count); } @@ -1662,7 +1666,7 @@ i_cpr_restore_ppages(void) dcache_flushall(); - DEBUG1(errp("restored %ld prom pages\n", ppage_count)); + CPR_DEBUG(CPR_DEBUG1, "restored %ld prom pages\n", ppage_count); } @@ -1693,7 +1697,8 @@ i_cpr_prom_pages(int action) if (ppage_buf) { ASSERT(ppage_count); kmem_free(ppage_buf, mmu_ptob(ppage_count)); - DEBUG1(errp("freed %ld prom pages\n", ppage_count)); + CPR_DEBUG(CPR_DEBUG1, "freed %ld prom pages\n", + ppage_count); ppage_buf = NULL; ppage_count = 0; } @@ -1836,7 +1841,7 @@ i_cpr_blockzero(char *base, char **bufpp, int *blkno, vnode_t *vp) bcopy(cpr_sector, base, sizeof (cpr_sector)); *bufpp = base + sizeof (cpr_sector); *blkno = cpr_statefile_offset(); - DEBUG1(errp("statefile data size: %ld\n\n", bytes)); + CPR_DEBUG(CPR_DEBUG1, "statefile data size: %ld\n\n", bytes); return (cpr_flush_write(vp)); } } diff --git a/usr/src/uts/sun4u/os/mach_trap.c b/usr/src/uts/sun4u/os/mach_trap.c index 2890d313f6..f6ab0b999e 100644 --- a/usr/src/uts/sun4u/os/mach_trap.c +++ b/usr/src/uts/sun4u/os/mach_trap.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -150,7 +149,7 @@ showregs(uint_t type, struct regs *rp, caddr_t addr, uint_t mmu_fsr) s = spl7(); type &= ~T_USER; - printf("%s: ", u.u_comm); + printf("%s: ", PTOU(curproc)->u_comm); switch (type) { case T_SYS_RTT_ALIGN: diff --git a/usr/src/uts/sun4u/schumacher/Makefile b/usr/src/uts/sun4u/schumacher/Makefile index 893dd0c41f..f44163dc26 100644 --- a/usr/src/uts/sun4u/schumacher/Makefile +++ b/usr/src/uts/sun4u/schumacher/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -19,7 +18,7 @@ # # CDDL HEADER END # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -75,7 +74,6 @@ install: $(ROOT_SCHUMACHER_DIR) \ $(USR_SCHUMACHER_DIR) \ $(USR_SCHUMACHER_INC_DIR) \ $(USR_SCHUMACHER_SBIN_DIR) \ - $(USR_SCHUMACHER_SBIN_EEPROM) \ $(USR_SCHUMACHER_SBIN_PRTDIAG) \ $(USR_SCHUMACHER_SBIN_TRAPSTAT) \ $(USR_SCHUMACHER_SBIN_FRUADM) \ diff --git a/usr/src/uts/sun4u/schumacher/Makefile.schumacher b/usr/src/uts/sun4u/schumacher/Makefile.schumacher index d2e28ea88e..b250779b6d 100644 --- a/usr/src/uts/sun4u/schumacher/Makefile.schumacher +++ b/usr/src/uts/sun4u/schumacher/Makefile.schumacher @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -19,7 +18,7 @@ # # CDDL HEADER END # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -52,7 +51,6 @@ USR_SCHUMACHER_LINKED_DIR = $(USR_PLAT_DIR)/$(LINKED_PLATFORM) USR_SCHUMACHER_INC_DIR = $(USR_SCHUMACHER_DIR)/include USR_SCHUMACHER_ISYS_DIR = $(USR_SCHUMACHER_INC_DIR)/sys USR_SCHUMACHER_SBIN_DIR = $(USR_SCHUMACHER_DIR)/sbin -USR_SCHUMACHER_SBIN_EEPROM = $(USR_SCHUMACHER_SBIN_DIR)/eeprom USR_SCHUMACHER_SBIN_PRTDIAG = $(USR_SCHUMACHER_SBIN_DIR)/prtdiag USR_SCHUMACHER_SBIN_TRAPSTAT = $(USR_SCHUMACHER_SBIN_DIR)/trapstat USR_SCHUMACHER_SBIN_FRUADM = $(USR_SCHUMACHER_SBIN_DIR)/fruadm diff --git a/usr/src/uts/sun4u/schumacher/Makefile.targ b/usr/src/uts/sun4u/schumacher/Makefile.targ index 799d5c596c..2864ec75db 100644 --- a/usr/src/uts/sun4u/schumacher/Makefile.targ +++ b/usr/src/uts/sun4u/schumacher/Makefile.targ @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -19,7 +18,7 @@ # # CDDL HEADER END # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -67,9 +66,6 @@ $(USR_SCHUMACHER_INC_DIR): $(USR_SCHUMACHER_DIR) $(USR_SCHUMACHER_SBIN_DIR): $(USR_SCHUMACHER_DIR) -$(INS.dir.root.bin) -$(USR_SCHUMACHER_SBIN_EEPROM): $(USR_SCHUMACHER_SBIN_DIR) - $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/sbin/eeprom $@ $(CHOWNLINK) $(CHGRPLINK) - $(USR_SCHUMACHER_SBIN_PRTDIAG): $(USR_SCHUMACHER_SBIN_DIR) $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/sbin/prtdiag $@ $(CHOWNLINK) $(CHGRPLINK) diff --git a/usr/src/uts/sun4u/seattle/Makefile b/usr/src/uts/sun4u/seattle/Makefile index c8222eb676..60e3ed6d6a 100644 --- a/usr/src/uts/sun4u/seattle/Makefile +++ b/usr/src/uts/sun4u/seattle/Makefile @@ -20,7 +20,7 @@ # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -79,7 +79,6 @@ SEATTLE_CRYPTO_LINKS += aes256 install: $(ROOT_SEATTLE_DIR) \ $(USR_SEATTLE_DIR) \ $(USR_SEATTLE_INC_DIR) \ - $(USR_SEATTLE_SBIN_EEPROM) \ $(USR_SEATTLE_SBIN_PRTDIAG) \ $(USR_SEATTLE_SBIN_TRAPSTAT) \ $(USR_SEATTLE_SBIN_FRUADM) \ diff --git a/usr/src/uts/sun4u/seattle/Makefile.seattle b/usr/src/uts/sun4u/seattle/Makefile.seattle index 1f0f3305d7..b88d6b4647 100644 --- a/usr/src/uts/sun4u/seattle/Makefile.seattle +++ b/usr/src/uts/sun4u/seattle/Makefile.seattle @@ -20,7 +20,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -53,7 +53,6 @@ USR_SEATTLE_LINKED_DIR = $(USR_PLAT_DIR)/$(LINKED_PLATFORM) USR_SEATTLE_INC_DIR = $(USR_SEATTLE_DIR)/include USR_SEATTLE_ISYS_DIR = $(USR_SEATTLE_INC_DIR)/sys USR_SEATTLE_SBIN_DIR = $(USR_SEATTLE_DIR)/sbin -USR_SEATTLE_SBIN_EEPROM = $(USR_SEATTLE_SBIN_DIR)/eeprom USR_SEATTLE_SBIN_PRTDIAG = $(USR_SEATTLE_SBIN_DIR)/prtdiag USR_SEATTLE_SBIN_TRAPSTAT = $(USR_SEATTLE_SBIN_DIR)/trapstat USR_SEATTLE_SBIN_FRUADM = $(USR_SEATTLE_SBIN_DIR)/fruadm diff --git a/usr/src/uts/sun4u/seattle/Makefile.targ b/usr/src/uts/sun4u/seattle/Makefile.targ index 6c87067a04..bb2a0ce141 100644 --- a/usr/src/uts/sun4u/seattle/Makefile.targ +++ b/usr/src/uts/sun4u/seattle/Makefile.targ @@ -20,7 +20,7 @@ # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -67,9 +67,6 @@ $(USR_SEATTLE_INC_DIR): $(USR_SEATTLE_DIR) $(USR_SEATTLE_SBIN_DIR): $(USR_SEATTLE_DIR) $(INS.dir.root.bin) -$(USR_SEATTLE_SBIN_EEPROM): $(USR_SEATTLE_SBIN_DIR) - $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/sbin/eeprom $@ $(CHOWNLINK) $(CHGRPLINK) - $(USR_SEATTLE_SBIN_PRTDIAG): $(USR_SEATTLE_SBIN_DIR) $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/sbin/prtdiag $@ $(CHOWNLINK) $(CHGRPLINK) diff --git a/usr/src/uts/sun4u/snowbird/Makefile b/usr/src/uts/sun4u/snowbird/Makefile index 3aa31a6e8a..fe7b03ed64 100644 --- a/usr/src/uts/sun4u/snowbird/Makefile +++ b/usr/src/uts/sun4u/snowbird/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ # # # uts/sun4u/snowbird/Makefile -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -71,7 +70,6 @@ def all clean clobber clean.lint modlist: $(SNOWBIRD_KMODS) install: $(ROOT_SNOWBIRD_DIR) $(USR_SNOWBIRD_DIR) \ $(USR_SNOWBIRD_INC_DIR) \ $(USR_SNOWBIRD_SBIN_DIR) \ - $(USR_SNOWBIRD_SBIN_EEPROM) \ $(USR_SNOWBIRD_SBIN_PRTDIAG) \ $(USR_SNOWBIRD_SBIN_TRAPSTAT) \ $(USR_SNOWBIRD_SBIN_FRUADM) \ diff --git a/usr/src/uts/sun4u/snowbird/Makefile.snowbird b/usr/src/uts/sun4u/snowbird/Makefile.snowbird index fd95d912d9..830837e44e 100644 --- a/usr/src/uts/sun4u/snowbird/Makefile.snowbird +++ b/usr/src/uts/sun4u/snowbird/Makefile.snowbird @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -66,7 +66,6 @@ ROOT_SNOWBIRD_DRV_LINK = $(ROOT_SNOWBIRD_DRV_LINK_$(CLASS)) USR_SNOWBIRD_DIR = $(USR_PLAT_DIR)/SUNW,Netra-CP2300 USR_SNOWBIRD_INC_DIR = $(USR_SNOWBIRD_DIR)/include USR_SNOWBIRD_SBIN_DIR = $(USR_SNOWBIRD_DIR)/sbin -USR_SNOWBIRD_SBIN_EEPROM = $(USR_SNOWBIRD_SBIN_DIR)/eeprom USR_SNOWBIRD_SBIN_PRTDIAG = $(USR_SNOWBIRD_SBIN_DIR)/prtdiag USR_SNOWBIRD_SBIN_TRAPSTAT = $(USR_SNOWBIRD_SBIN_DIR)/trapstat USR_SNOWBIRD_SBIN_FRUADM = $(USR_SNOWBIRD_SBIN_DIR)/fruadm diff --git a/usr/src/uts/sun4u/snowbird/Makefile.targ b/usr/src/uts/sun4u/snowbird/Makefile.targ index 652dd06886..9fd2bac81a 100644 --- a/usr/src/uts/sun4u/snowbird/Makefile.targ +++ b/usr/src/uts/sun4u/snowbird/Makefile.targ @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -89,9 +88,6 @@ $(USR_SNOWBIRD_INC_DIR): $(USR_SNOWBIRD_DIR) $(USR_SNOWBIRD_SBIN_DIR): $(USR_SNOWBIRD_DIR) -$(INS.dir.root.bin) -$(USR_SNOWBIRD_SBIN_EEPROM): $(USR_SNOWBIRD_SBIN_DIR) - $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/sbin/eeprom $@ $(CHOWNLINK) $(CHGRPLINK) - $(USR_SNOWBIRD_SBIN_PRTDIAG): $(USR_SNOWBIRD_SBIN_DIR) $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/sbin/prtdiag $@ $(CHOWNLINK) $(CHGRPLINK) diff --git a/usr/src/uts/sun4u/sys/cpr_impl.h b/usr/src/uts/sun4u/sys/cpr_impl.h index 40d36129dd..9f275c3e60 100644 --- a/usr/src/uts/sun4u/sys/cpr_impl.h +++ b/usr/src/uts/sun4u/sys/cpr_impl.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -153,7 +152,7 @@ typedef struct cpr_sun4u_machdep csu_md_t; #define prom_map_plat(addr, pa, size) \ if (prom_map(addr, pa, size) == 0) { \ - errp("PROM_MAP failed: paddr=0x%lx\n", pa); \ + prom_printf("PROM_MAP failed: paddr=0x%lx\n", pa); \ return (-1); \ } diff --git a/usr/src/uts/sun4u/sys/machparam.h b/usr/src/uts/sun4u/sys/machparam.h index 68a993761d..394079a247 100644 --- a/usr/src/uts/sun4u/sys/machparam.h +++ b/usr/src/uts/sun4u/sys/machparam.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -166,6 +166,12 @@ extern "C" { #define KERNELBASE ADDRESS_C(0x01000000) /* + * Virtual address range available to the debugger + */ +#define SEGDEBUGBASE ADDRESS_C(0xedd00000) +#define SEGDEBUGSIZE (ADDRESS_C(0xf0000000) - SEGDEBUGBASE) + +/* * Define the userlimits */ diff --git a/usr/src/uts/sun4u/vm/mach_kpm.c b/usr/src/uts/sun4u/vm/mach_kpm.c index e12883d4af..e39c3a26d2 100644 --- a/usr/src/uts/sun4u/vm/mach_kpm.c +++ b/usr/src/uts/sun4u/vm/mach_kpm.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -299,8 +299,6 @@ hat_kpm_fault(struct hat *hat, caddr_t vaddr) return (error); } -extern krwlock_t memsegslock; - /* * memseg_hash[] was cleared, need to clear memseg_phash[] too. */ @@ -356,7 +354,7 @@ hat_kpm_addmem_mseg_insert(struct memseg *msp) if (kpm_enable == 0) return; - ASSERT(RW_LOCK_HELD(&memsegslock)); + ASSERT(memsegs_lock_held()); msp->nextpa = (memsegs) ? va_to_pa(memsegs) : MSEG_NULLPTR_PA; } @@ -372,7 +370,7 @@ hat_kpm_addmem_memsegs_update(struct memseg *msp) if (kpm_enable == 0) return; - ASSERT(RW_LOCK_HELD(&memsegslock)); + ASSERT(memsegs_lock_held()); ASSERT(memsegs); memsegspa = va_to_pa(msp); } @@ -411,7 +409,7 @@ hat_kpm_delmem_mseg_update(struct memseg *msp, struct memseg **mspp) if (kpm_enable == 0) return; - ASSERT(RW_LOCK_HELD(&memsegslock)); + ASSERT(memsegs_lock_held()); if (mspp == &memsegs) { memsegspa = (msp->next) ? @@ -447,7 +445,7 @@ hat_kpm_split_mseg_update(struct memseg *msp, struct memseg **mspp, if (kpm_enable == 0) return; - ASSERT(RW_LOCK_HELD(&memsegslock)); + ASSERT(memsegs_lock_held()); ASSERT(msp && mid && msp->kpm_pages); kbase = ptokpmp(msp->kpm_pbase); diff --git a/usr/src/uts/sun4v/Makefile b/usr/src/uts/sun4v/Makefile index 97d645f59c..0cd8f4a8f6 100644 --- a/usr/src/uts/sun4v/Makefile +++ b/usr/src/uts/sun4v/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -81,7 +81,7 @@ check := TARGET= check .KEEP_STATE: -.PARALLEL: $(KMODS) $(CLOSED_KMODS) $(XMODS) $(CLOSED_XMODS) \ +.PARALLEL: $(PARALLEL_KMODS) $(CLOSED_KMODS) $(XMODS) $(CLOSED_XMODS) \ modlist modlist.sparc # Override for CPU_KMODS... they cannot be built diff --git a/usr/src/uts/sun4v/Makefile.sun4v.shared b/usr/src/uts/sun4v/Makefile.sun4v.shared index 921d3ad0f5..25420469a1 100644 --- a/usr/src/uts/sun4v/Makefile.sun4v.shared +++ b/usr/src/uts/sun4v/Makefile.sun4v.shared @@ -42,6 +42,11 @@ PROMIF = ieee1275 PSMBASE = $(UTSBASE)/../psm # +# uname -m value +# +UNAME_M = $(PLATFORM) + +# # Definitions for the platform-specific /platform directories. # # PLATFORMS designates those sun4v machines which have no platform diff --git a/usr/src/uts/sun4v/os/mach_trap.c b/usr/src/uts/sun4v/os/mach_trap.c index 6a09aa1c80..e74c26df5a 100644 --- a/usr/src/uts/sun4v/os/mach_trap.c +++ b/usr/src/uts/sun4v/os/mach_trap.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -135,7 +134,7 @@ showregs(uint_t type, struct regs *rp, caddr_t addr, uint_t mmu_fsr) s = spl7(); type &= ~T_USER; - printf("%s: ", u.u_comm); + printf("%s: ", PTOU(curproc)->u_comm); switch (type) { case T_SYS_RTT_ALIGN: diff --git a/usr/src/uts/sun4v/sys/machparam.h b/usr/src/uts/sun4v/sys/machparam.h index 6ea07291d1..3fd034bdc5 100644 --- a/usr/src/uts/sun4v/sys/machparam.h +++ b/usr/src/uts/sun4v/sys/machparam.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -149,6 +149,12 @@ extern "C" { #define KERNELBASE ADDRESS_C(0x01000000) /* + * Virtual address range available to the debugger + */ +#define SEGDEBUGBASE ADDRESS_C(0xedd00000) +#define SEGDEBUGSIZE (ADDRESS_C(0xf0000000) - SEGDEBUGBASE) + +/* * Define the userlimits */ diff --git a/usr/src/xmod/xmod_files b/usr/src/xmod/xmod_files index 613a6e60a9..30721f2f0a 100644 --- a/usr/src/xmod/xmod_files +++ b/usr/src/xmod/xmod_files @@ -28,8 +28,8 @@ ../closed/uts/intel/adpu320 ../closed/uts/intel/io/lsimega ../closed/uts/intel/lsimega -../closed/uts/i86pc/spwr -../closed/uts/i86pc/io/spwr +../closed/uts/intel/spwr +../closed/uts/intel/io/spwr cmd/openssl cmd/ssh common/net/wanboot |