diff options
780 files changed, 31254 insertions, 18941 deletions
diff --git a/usr/src/cmd/eeprom/common/Makefile b/deleted_files/usr/src/cmd/eeprom/common/Makefile index 9828df5a79..9828df5a79 100644 --- a/usr/src/cmd/eeprom/common/Makefile +++ b/deleted_files/usr/src/cmd/eeprom/common/Makefile diff --git a/usr/src/cmd/eeprom/eeprom.xml b/deleted_files/usr/src/cmd/eeprom/eeprom.xml index 48db9f3599..48db9f3599 100644 --- a/usr/src/cmd/eeprom/eeprom.xml +++ b/deleted_files/usr/src/cmd/eeprom/eeprom.xml diff --git a/usr/src/cmd/eeprom/i386/common/benv_sync.c b/deleted_files/usr/src/cmd/eeprom/i386/common/benv_sync.c index 5faf7e68ab..5faf7e68ab 100644 --- a/usr/src/cmd/eeprom/i386/common/benv_sync.c +++ b/deleted_files/usr/src/cmd/eeprom/i386/common/benv_sync.c diff --git a/usr/src/cmd/eeprom/i386/i86pc/Makefile b/deleted_files/usr/src/cmd/eeprom/i386/i86pc/Makefile index da26f7f3a7..da26f7f3a7 100644 --- a/usr/src/cmd/eeprom/i386/i86pc/Makefile +++ b/deleted_files/usr/src/cmd/eeprom/i386/i86pc/Makefile diff --git a/usr/src/cmd/eeprom/sparc/sun4u/Makefile b/deleted_files/usr/src/cmd/eeprom/sparc/sun4u/Makefile index 2cb9c73cfb..2cb9c73cfb 100644 --- a/usr/src/cmd/eeprom/sparc/sun4u/Makefile +++ b/deleted_files/usr/src/cmd/eeprom/sparc/sun4u/Makefile diff --git a/usr/src/cmd/eeprom/sparc/sun4v/Makefile b/deleted_files/usr/src/cmd/eeprom/sparc/sun4v/Makefile index d4cb137cff..d4cb137cff 100644 --- a/usr/src/cmd/eeprom/sparc/sun4v/Makefile +++ b/deleted_files/usr/src/cmd/eeprom/sparc/sun4v/Makefile diff --git a/usr/src/cmd/mdb/common/kmdb/kmdb_kdi_impl.h b/deleted_files/usr/src/cmd/mdb/common/kmdb/kmdb_kdi_impl.h index 3ff5deb4ee..3ff5deb4ee 100644 --- a/usr/src/cmd/mdb/common/kmdb/kmdb_kdi_impl.h +++ b/deleted_files/usr/src/cmd/mdb/common/kmdb/kmdb_kdi_impl.h diff --git a/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.h b/deleted_files/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.h index 6abe1ba166..6abe1ba166 100644 --- a/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.h +++ b/deleted_files/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.h diff --git a/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.s b/deleted_files/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.s index 4861bcc476..4861bcc476 100644 --- a/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.s +++ b/deleted_files/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_asmutil.s diff --git a/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_resume.s b/deleted_files/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_resume.s index 8574be2336..8574be2336 100644 --- a/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_resume.s +++ b/deleted_files/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_resume.s diff --git a/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.h b/deleted_files/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.h index 0ed570f1d2..0ed570f1d2 100644 --- a/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.h +++ b/deleted_files/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.h diff --git a/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.s b/deleted_files/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.s index f695047c52..f695047c52 100644 --- a/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.s +++ b/deleted_files/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_asmutil.s diff --git a/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_resume.s b/deleted_files/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_resume.s index c9693b8212..c9693b8212 100644 --- a/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_resume.s +++ b/deleted_files/usr/src/cmd/mdb/intel/ia32/kmdb/kaif_resume.s diff --git a/usr/src/cmd/mdb/intel/kmdb/kaif_activate.c b/deleted_files/usr/src/cmd/mdb/intel/kmdb/kaif_activate.c index 17294e5bb7..17294e5bb7 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kaif_activate.c +++ b/deleted_files/usr/src/cmd/mdb/intel/kmdb/kaif_activate.c diff --git a/usr/src/cmd/mdb/intel/kmdb/kaif_start_isadep.c b/deleted_files/usr/src/cmd/mdb/intel/kmdb/kaif_start_isadep.c index 708cbb390c..708cbb390c 100644 --- a/usr/src/cmd/mdb/intel/kmdb/kaif_start_isadep.c +++ b/deleted_files/usr/src/cmd/mdb/intel/kmdb/kaif_start_isadep.c diff --git a/usr/src/cmd/mdb/sparc/kmdb/kaif_enter.s b/deleted_files/usr/src/cmd/mdb/sparc/kmdb/kaif_enter.s index 4275773a71..4275773a71 100644 --- a/usr/src/cmd/mdb/sparc/kmdb/kaif_enter.s +++ b/deleted_files/usr/src/cmd/mdb/sparc/kmdb/kaif_enter.s diff --git a/usr/src/cmd/prtdiag/i386/i86pc/Makefile b/deleted_files/usr/src/cmd/prtdiag/i386/i86pc/Makefile index 77891ef8e4..77891ef8e4 100644 --- a/usr/src/cmd/prtdiag/i386/i86pc/Makefile +++ b/deleted_files/usr/src/cmd/prtdiag/i386/i86pc/Makefile diff --git a/usr/src/cmd/svc/profile/platform_i86pc.xml b/deleted_files/usr/src/cmd/svc/profile/platform_i86pc.xml index 3c196487c1..3c196487c1 100644 --- a/usr/src/cmd/svc/profile/platform_i86pc.xml +++ b/deleted_files/usr/src/cmd/svc/profile/platform_i86pc.xml diff --git a/usr/src/psm/stand/boot/amd64/alloc.c b/deleted_files/usr/src/psm/stand/boot/amd64/alloc.c index 4da403f0e1..4da403f0e1 100644 --- a/usr/src/psm/stand/boot/amd64/alloc.c +++ b/deleted_files/usr/src/psm/stand/boot/amd64/alloc.c diff --git a/usr/src/psm/stand/boot/amd64/amd64/alloc.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/alloc.h index ba6a8c8da5..ba6a8c8da5 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/alloc.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/alloc.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/amd64.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/amd64.h index c7518b84c8..c7518b84c8 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/amd64.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/amd64.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/amd64_page.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/amd64_page.h index c2e7115205..c2e7115205 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/amd64_page.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/amd64_page.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/auxv64.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/auxv64.h index 42e897e7ce..42e897e7ce 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/auxv64.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/auxv64.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/boothooks.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/boothooks.h index becc1ef9b9..becc1ef9b9 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/boothooks.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/boothooks.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/bootops64.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/bootops64.h index e45872ca47..e45872ca47 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/bootops64.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/bootops64.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h index 4fd533e2df..4fd533e2df 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/bootsvcs64.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/cpu.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/cpu.h index 9f035799f3..9f035799f3 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/cpu.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/cpu.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/debug.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/debug.h index d62d24c927..d62d24c927 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/debug.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/debug.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/machregs.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/machregs.h index 6784059966..6784059966 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/machregs.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/machregs.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/memlist64.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/memlist64.h index ce3978e1e8..ce3978e1e8 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/memlist64.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/memlist64.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/msr.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/msr.h index 4bbba75b9b..4bbba75b9b 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/msr.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/msr.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/print.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/print.h index 0db7816902..0db7816902 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/print.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/print.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/segments.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/segments.h index 478fc99790..478fc99790 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/segments.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/segments.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/tss.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/tss.h index 1aff429e8d..1aff429e8d 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/tss.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/tss.h diff --git a/usr/src/psm/stand/boot/amd64/amd64/types.h b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/types.h index 127effff25..127effff25 100644 --- a/usr/src/psm/stand/boot/amd64/amd64/types.h +++ b/deleted_files/usr/src/psm/stand/boot/amd64/amd64/types.h diff --git a/usr/src/psm/stand/boot/amd64/context.c b/deleted_files/usr/src/psm/stand/boot/amd64/context.c index 7fb2d61c7f..7fb2d61c7f 100644 --- a/usr/src/psm/stand/boot/amd64/context.c +++ b/deleted_files/usr/src/psm/stand/boot/amd64/context.c diff --git a/usr/src/psm/stand/boot/amd64/cpu.c b/deleted_files/usr/src/psm/stand/boot/amd64/cpu.c index 668d2f17e6..668d2f17e6 100644 --- a/usr/src/psm/stand/boot/amd64/cpu.c +++ b/deleted_files/usr/src/psm/stand/boot/amd64/cpu.c diff --git a/usr/src/psm/stand/boot/amd64/exception.s b/deleted_files/usr/src/psm/stand/boot/amd64/exception.s index 0d696a6120..0d696a6120 100644 --- a/usr/src/psm/stand/boot/amd64/exception.s +++ b/deleted_files/usr/src/psm/stand/boot/amd64/exception.s diff --git a/usr/src/psm/stand/boot/amd64/genassym.c b/deleted_files/usr/src/psm/stand/boot/amd64/genassym.c index cba7592a16..cba7592a16 100644 --- a/usr/src/psm/stand/boot/amd64/genassym.c +++ b/deleted_files/usr/src/psm/stand/boot/amd64/genassym.c diff --git a/usr/src/psm/stand/boot/amd64/handoff.c b/deleted_files/usr/src/psm/stand/boot/amd64/handoff.c index dafc7ad751..dafc7ad751 100644 --- a/usr/src/psm/stand/boot/amd64/handoff.c +++ b/deleted_files/usr/src/psm/stand/boot/amd64/handoff.c diff --git a/usr/src/psm/stand/boot/amd64/i386_subr.s b/deleted_files/usr/src/psm/stand/boot/amd64/i386_subr.s index 2f4846e927..2f4846e927 100644 --- a/usr/src/psm/stand/boot/amd64/i386_subr.s +++ b/deleted_files/usr/src/psm/stand/boot/amd64/i386_subr.s diff --git a/usr/src/psm/stand/boot/amd64/locore.s b/deleted_files/usr/src/psm/stand/boot/amd64/locore.s index a127e02f05..a127e02f05 100644 --- a/usr/src/psm/stand/boot/amd64/locore.s +++ b/deleted_files/usr/src/psm/stand/boot/amd64/locore.s diff --git a/usr/src/psm/stand/boot/amd64/memlist.c b/deleted_files/usr/src/psm/stand/boot/amd64/memlist.c index da62480d1d..da62480d1d 100644 --- a/usr/src/psm/stand/boot/amd64/memlist.c +++ b/deleted_files/usr/src/psm/stand/boot/amd64/memlist.c diff --git a/usr/src/psm/stand/boot/amd64/offsets.in b/deleted_files/usr/src/psm/stand/boot/amd64/offsets.in index b07ea48e76..b07ea48e76 100644 --- a/usr/src/psm/stand/boot/amd64/offsets.in +++ b/deleted_files/usr/src/psm/stand/boot/amd64/offsets.in diff --git a/usr/src/psm/stand/boot/amd64/print.c b/deleted_files/usr/src/psm/stand/boot/amd64/print.c index 7f2f7f3aef..7f2f7f3aef 100644 --- a/usr/src/psm/stand/boot/amd64/print.c +++ b/deleted_files/usr/src/psm/stand/boot/amd64/print.c diff --git a/usr/src/psm/stand/boot/amd64/ptops.c b/deleted_files/usr/src/psm/stand/boot/amd64/ptops.c index 3b6244efe9..3b6244efe9 100644 --- a/usr/src/psm/stand/boot/amd64/ptops.c +++ b/deleted_files/usr/src/psm/stand/boot/amd64/ptops.c diff --git a/usr/src/psm/stand/boot/amd64/ptxlate.c b/deleted_files/usr/src/psm/stand/boot/amd64/ptxlate.c index 80e20f783a..80e20f783a 100644 --- a/usr/src/psm/stand/boot/amd64/ptxlate.c +++ b/deleted_files/usr/src/psm/stand/boot/amd64/ptxlate.c diff --git a/usr/src/psm/stand/boot/amd64/segments.c b/deleted_files/usr/src/psm/stand/boot/amd64/segments.c index f384110045..f384110045 100644 --- a/usr/src/psm/stand/boot/amd64/segments.c +++ b/deleted_files/usr/src/psm/stand/boot/amd64/segments.c diff --git a/usr/src/psm/stand/boot/amd64/vtrap.c b/deleted_files/usr/src/psm/stand/boot/amd64/vtrap.c index 95c4ee32a4..95c4ee32a4 100644 --- a/usr/src/psm/stand/boot/amd64/vtrap.c +++ b/deleted_files/usr/src/psm/stand/boot/amd64/vtrap.c diff --git a/usr/src/psm/stand/boot/i386/Makefile b/deleted_files/usr/src/psm/stand/boot/i386/Makefile index ad7f5d24a0..ad7f5d24a0 100644 --- a/usr/src/psm/stand/boot/i386/Makefile +++ b/deleted_files/usr/src/psm/stand/boot/i386/Makefile diff --git a/usr/src/psm/stand/boot/i386/Makefile.com b/deleted_files/usr/src/psm/stand/boot/i386/Makefile.com index 06e00ac095..06e00ac095 100644 --- a/usr/src/psm/stand/boot/i386/Makefile.com +++ b/deleted_files/usr/src/psm/stand/boot/i386/Makefile.com diff --git a/usr/src/psm/stand/boot/i386/common/bios.c b/deleted_files/usr/src/psm/stand/boot/i386/common/bios.c index e80d0ad55d..e80d0ad55d 100644 --- a/usr/src/psm/stand/boot/i386/common/bios.c +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/bios.c diff --git a/usr/src/psm/stand/boot/i386/common/biosint.h b/deleted_files/usr/src/psm/stand/boot/i386/common/biosint.h index 0372ed078a..0372ed078a 100644 --- a/usr/src/psm/stand/boot/i386/common/biosint.h +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/biosint.h diff --git a/usr/src/psm/stand/boot/i386/common/biosint.map b/deleted_files/usr/src/psm/stand/boot/i386/common/biosint.map index 8780bf99b3..8780bf99b3 100644 --- a/usr/src/psm/stand/boot/i386/common/biosint.map +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/biosint.map diff --git a/usr/src/psm/stand/boot/i386/common/biosutil.c b/deleted_files/usr/src/psm/stand/boot/i386/common/biosutil.c index ad262ae4b4..ad262ae4b4 100644 --- a/usr/src/psm/stand/boot/i386/common/biosutil.c +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/biosutil.c diff --git a/usr/src/psm/stand/boot/i386/common/boot_plat.c b/deleted_files/usr/src/psm/stand/boot/i386/common/boot_plat.c index 3de61380da..3de61380da 100644 --- a/usr/src/psm/stand/boot/i386/common/boot_plat.c +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/boot_plat.c diff --git a/usr/src/psm/stand/boot/i386/common/boot_ramdisk.c b/deleted_files/usr/src/psm/stand/boot/i386/common/boot_ramdisk.c index b380e3149c..b380e3149c 100644 --- a/usr/src/psm/stand/boot/i386/common/boot_ramdisk.c +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/boot_ramdisk.c diff --git a/usr/src/psm/stand/boot/i386/common/bootenv.c b/deleted_files/usr/src/psm/stand/boot/i386/common/bootenv.c index 30eb186b93..30eb186b93 100644 --- a/usr/src/psm/stand/boot/i386/common/bootenv.c +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/bootenv.c diff --git a/usr/src/psm/stand/boot/i386/common/bootflags.c b/deleted_files/usr/src/psm/stand/boot/i386/common/bootflags.c index 26bd0de1b8..26bd0de1b8 100644 --- a/usr/src/psm/stand/boot/i386/common/bootflags.c +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/bootflags.c diff --git a/usr/src/psm/stand/boot/i386/common/bootops.c b/deleted_files/usr/src/psm/stand/boot/i386/common/bootops.c index b7fe051099..b7fe051099 100644 --- a/usr/src/psm/stand/boot/i386/common/bootops.c +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/bootops.c diff --git a/usr/src/psm/stand/boot/i386/common/bootprop.c b/deleted_files/usr/src/psm/stand/boot/i386/common/bootprop.c index 466f27338b..466f27338b 100644 --- a/usr/src/psm/stand/boot/i386/common/bootprop.c +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/bootprop.c diff --git a/usr/src/psm/stand/boot/i386/common/bootprop.h b/deleted_files/usr/src/psm/stand/boot/i386/common/bootprop.h index 7c25e8e69d..7c25e8e69d 100644 --- a/usr/src/psm/stand/boot/i386/common/bootprop.h +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/bootprop.h diff --git a/usr/src/psm/stand/boot/i386/common/chario.h b/deleted_files/usr/src/psm/stand/boot/i386/common/chario.h index 7023c17134..7023c17134 100644 --- a/usr/src/psm/stand/boot/i386/common/chario.h +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/chario.h diff --git a/usr/src/psm/stand/boot/i386/common/check_iopath.c b/deleted_files/usr/src/psm/stand/boot/i386/common/check_iopath.c index fb842546f0..fb842546f0 100644 --- a/usr/src/psm/stand/boot/i386/common/check_iopath.c +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/check_iopath.c diff --git a/usr/src/psm/stand/boot/i386/common/cpu_id.h b/deleted_files/usr/src/psm/stand/boot/i386/common/cpu_id.h index 8948d8031b..8948d8031b 100644 --- a/usr/src/psm/stand/boot/i386/common/cpu_id.h +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/cpu_id.h diff --git a/usr/src/psm/stand/boot/i386/common/debug.h b/deleted_files/usr/src/psm/stand/boot/i386/common/debug.h index 858cb21245..858cb21245 100644 --- a/usr/src/psm/stand/boot/i386/common/debug.h +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/debug.h diff --git a/usr/src/psm/stand/boot/i386/common/i86.il b/deleted_files/usr/src/psm/stand/boot/i386/common/i86.il index 180cb5135a..180cb5135a 100644 --- a/usr/src/psm/stand/boot/i386/common/i86.il +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/i86.il diff --git a/usr/src/psm/stand/boot/i386/common/machine.h b/deleted_files/usr/src/psm/stand/boot/i386/common/machine.h index d841cb8526..d841cb8526 100644 --- a/usr/src/psm/stand/boot/i386/common/machine.h +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/machine.h diff --git a/usr/src/psm/stand/boot/i386/common/mapfile b/deleted_files/usr/src/psm/stand/boot/i386/common/mapfile index 85a3c88c5d..85a3c88c5d 100644 --- a/usr/src/psm/stand/boot/i386/common/mapfile +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/mapfile diff --git a/usr/src/psm/stand/boot/i386/common/memory.c b/deleted_files/usr/src/psm/stand/boot/i386/common/memory.c index 591c7781fe..591c7781fe 100644 --- a/usr/src/psm/stand/boot/i386/common/memory.c +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/memory.c diff --git a/usr/src/psm/stand/boot/i386/common/mkbin.c b/deleted_files/usr/src/psm/stand/boot/i386/common/mkbin.c index 423ecec781..423ecec781 100644 --- a/usr/src/psm/stand/boot/i386/common/mkbin.c +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/mkbin.c diff --git a/usr/src/psm/stand/boot/i386/common/multiboot.c b/deleted_files/usr/src/psm/stand/boot/i386/common/multiboot.c index 79bacf01ba..79bacf01ba 100644 --- a/usr/src/psm/stand/boot/i386/common/multiboot.c +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/multiboot.c diff --git a/usr/src/psm/stand/boot/i386/common/multiboot.h b/deleted_files/usr/src/psm/stand/boot/i386/common/multiboot.h index 7674c16faf..7674c16faf 100644 --- a/usr/src/psm/stand/boot/i386/common/multiboot.h +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/multiboot.h diff --git a/usr/src/psm/stand/boot/i386/common/standalloc.c b/deleted_files/usr/src/psm/stand/boot/i386/common/standalloc.c index 4e8af8667a..4e8af8667a 100644 --- a/usr/src/psm/stand/boot/i386/common/standalloc.c +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/standalloc.c diff --git a/usr/src/psm/stand/boot/i386/common/standalloc.h b/deleted_files/usr/src/psm/stand/boot/i386/common/standalloc.h index ee99de104b..ee99de104b 100644 --- a/usr/src/psm/stand/boot/i386/common/standalloc.h +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/standalloc.h diff --git a/usr/src/psm/stand/boot/i386/common/util.h b/deleted_files/usr/src/psm/stand/boot/i386/common/util.h index 0aa18da2a6..0aa18da2a6 100644 --- a/usr/src/psm/stand/boot/i386/common/util.h +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/util.h diff --git a/usr/src/psm/stand/boot/i386/common/vgaprobe.c b/deleted_files/usr/src/psm/stand/boot/i386/common/vgaprobe.c index d93df5a3ac..d93df5a3ac 100644 --- a/usr/src/psm/stand/boot/i386/common/vgaprobe.c +++ b/deleted_files/usr/src/psm/stand/boot/i386/common/vgaprobe.c diff --git a/usr/src/psm/stand/boot/i386/i86pc/Makefile b/deleted_files/usr/src/psm/stand/boot/i386/i86pc/Makefile index 672e381b2c..672e381b2c 100644 --- a/usr/src/psm/stand/boot/i386/i86pc/Makefile +++ b/deleted_files/usr/src/psm/stand/boot/i386/i86pc/Makefile diff --git a/usr/src/psm/stand/boot/i386/i86pc/asm.s b/deleted_files/usr/src/psm/stand/boot/i386/i86pc/asm.s index 27dbb67aac..27dbb67aac 100644 --- a/usr/src/psm/stand/boot/i386/i86pc/asm.s +++ b/deleted_files/usr/src/psm/stand/boot/i386/i86pc/asm.s diff --git a/usr/src/psm/stand/boot/i386/i86pc/biosint.s b/deleted_files/usr/src/psm/stand/boot/i386/i86pc/biosint.s index dd5326c9e5..dd5326c9e5 100644 --- a/usr/src/psm/stand/boot/i386/i86pc/biosint.s +++ b/deleted_files/usr/src/psm/stand/boot/i386/i86pc/biosint.s diff --git a/usr/src/psm/stand/boot/i386/i86pc/cpu_id.s b/deleted_files/usr/src/psm/stand/boot/i386/i86pc/cpu_id.s index 8301a2a3b0..8301a2a3b0 100644 --- a/usr/src/psm/stand/boot/i386/i86pc/cpu_id.s +++ b/deleted_files/usr/src/psm/stand/boot/i386/i86pc/cpu_id.s diff --git a/usr/src/psm/stand/boot/i386/i86pc/idttab.s b/deleted_files/usr/src/psm/stand/boot/i386/i86pc/idttab.s index f205856ab6..f205856ab6 100644 --- a/usr/src/psm/stand/boot/i386/i86pc/idttab.s +++ b/deleted_files/usr/src/psm/stand/boot/i386/i86pc/idttab.s diff --git a/usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s b/deleted_files/usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s index fae6774331..fae6774331 100644 --- a/usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s +++ b/deleted_files/usr/src/psm/stand/boot/i386/i86pc/samuldiv64.s diff --git a/usr/src/uts/common/zmod/mapfile b/deleted_files/usr/src/uts/common/zmod/mapfile index 460b10cc10..460b10cc10 100644 --- a/usr/src/uts/common/zmod/mapfile +++ b/deleted_files/usr/src/uts/common/zmod/mapfile diff --git a/usr/src/uts/intel/amd64/Makefile.rules b/deleted_files/usr/src/uts/intel/amd64/Makefile.rules index 83dfec5f2a..83dfec5f2a 100644 --- a/usr/src/uts/intel/amd64/Makefile.rules +++ b/deleted_files/usr/src/uts/intel/amd64/Makefile.rules diff --git a/usr/src/uts/intel/ia32/Makefile.rules b/deleted_files/usr/src/uts/intel/ia32/Makefile.rules index d8b526458e..d8b526458e 100644 --- a/usr/src/uts/intel/ia32/Makefile.rules +++ b/deleted_files/usr/src/uts/intel/ia32/Makefile.rules diff --git a/usr/src/uts/intel/ia32/os/arch_kdi.c b/deleted_files/usr/src/uts/intel/ia32/os/arch_kdi.c index 2ac020245a..2ac020245a 100644 --- a/usr/src/uts/intel/ia32/os/arch_kdi.c +++ b/deleted_files/usr/src/uts/intel/ia32/os/arch_kdi.c diff --git a/usr/src/uts/intel/ia32/sys/mmu.h b/deleted_files/usr/src/uts/intel/ia32/sys/mmu.h index 135882602a..135882602a 100644 --- a/usr/src/uts/intel/ia32/sys/mmu.h +++ b/deleted_files/usr/src/uts/intel/ia32/sys/mmu.h diff --git a/usr/src/uts/intel/krtld/Makefile b/deleted_files/usr/src/uts/intel/krtld/Makefile index 9b88eaad0a..9b88eaad0a 100644 --- a/usr/src/uts/intel/krtld/Makefile +++ b/deleted_files/usr/src/uts/intel/krtld/Makefile diff --git a/usr/src/uts/intel/sys/immu.h b/deleted_files/usr/src/uts/intel/sys/immu.h index ac9af15bf6..ac9af15bf6 100644 --- a/usr/src/uts/intel/sys/immu.h +++ b/deleted_files/usr/src/uts/intel/sys/immu.h diff --git a/usr/src/uts/intel/sys/mmu.h b/deleted_files/usr/src/uts/intel/sys/mmu.h index 167a7ee895..167a7ee895 100644 --- a/usr/src/uts/intel/sys/mmu.h +++ b/deleted_files/usr/src/uts/intel/sys/mmu.h diff --git a/usr/src/uts/intel/zmod/Makefile b/deleted_files/usr/src/uts/intel/zmod/Makefile index 267187911e..267187911e 100644 --- a/usr/src/uts/intel/zmod/Makefile +++ b/deleted_files/usr/src/uts/intel/zmod/Makefile diff --git a/usr/src/uts/sparc/zmod/Makefile b/deleted_files/usr/src/uts/sparc/zmod/Makefile index 2cd46b6a11..2cd46b6a11 100644 --- a/usr/src/uts/sparc/zmod/Makefile +++ b/deleted_files/usr/src/uts/sparc/zmod/Makefile 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/boot/symdef/Makefile b/usr/src/cmd/boot/symdef/Makefile new file mode 100644 index 0000000000..dba76dea89 --- /dev/null +++ b/usr/src/cmd/boot/symdef/Makefile @@ -0,0 +1,58 @@ +# +# 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" +# + +PROG= symdef + +OBJS= symdef.o +SRCS = $(OBJS:.o=.c) + +include ../Makefile.com + +.KEEP_STATE: + +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: + +lint: lint_SRCS + +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/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/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/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_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_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_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/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/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/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/common/util/memcpy.h b/usr/src/common/util/memcpy.h new file mode 100644 index 0000000000..de7756825e --- /dev/null +++ b/usr/src/common/util/memcpy.h @@ -0,0 +1,44 @@ +/* + * 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_MEMCPY_H +#define _COMMON_UTIL_MEMCPY_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern void *memcpy(void *, const void *, size_t); + +#ifdef __cplusplus +} +#endif + +#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/common/util/memset.h b/usr/src/common/util/memset.h new file mode 100644 index 0000000000..93436f2ac1 --- /dev/null +++ b/usr/src/common/util/memset.h @@ -0,0 +1,44 @@ +/* + * 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_MEMSET_H +#define _COMMON_UTIL_MEMSET_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern void *memset(void *, int, size_t); + +#ifdef __cplusplus +} +#endif + +#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/common/util/sscanf.h b/usr/src/common/util/sscanf.h new file mode 100644 index 0000000000..8ca717b9c1 --- /dev/null +++ b/usr/src/common/util/sscanf.h @@ -0,0 +1,47 @@ +/* + * 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_SSCANF_H +#define _COMMON_UTIL_SSCANF_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <sys/varargs.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*SCANFLIKE2*/ +extern int sscanf(const char *, const char *, ...); +extern int vsscanf(const char *, const char *, va_list); + +#ifdef __cplusplus +} +#endif + +#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/pkgdefs/SUNWxsvc/postremove b/usr/src/pkgdefs/SUNWxsvc/postremove new file mode 100644 index 0000000000..9e98dbd5b5 --- /dev/null +++ b/usr/src/pkgdefs/SUNWxsvc/postremove @@ -0,0 +1,35 @@ +#!/sbin/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" +# +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/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/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/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/tools/elfextract/Makefile b/usr/src/tools/elfextract/Makefile new file mode 100644 index 0000000000..7a3e6838d4 --- /dev/null +++ b/usr/src/tools/elfextract/Makefile @@ -0,0 +1,44 @@ +# +# 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 = elfextract + +include ../Makefile.tools + + +.KEEP_STATE: + +all: $(PROG) + +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/uts/common/sys/multiboot.h b/usr/src/uts/common/sys/multiboot.h new file mode 100644 index 0000000000..1118aa9f53 --- /dev/null +++ b/usr/src/uts/common/sys/multiboot.h @@ -0,0 +1,174 @@ +/* + * 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 _MULTIBOOT_H +#define _MULTIBOOT_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * 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) */ + +/* + * passed by boot loader to kernel + */ +#define MB_BOOTLOADER_MAGIC 0x2BADB002 + +#ifndef _ASM /* excluded from assembly routines */ + +#include <sys/types.h> +#include <sys/types32.h> + +/* + * The Multiboot header must be somewhere in the 1st 8K of the image that + * the loader loads into memory. + */ +typedef struct multiboot_header { + 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 { + uint32_t num; + uint32_t size; + uint32_t addr; + uint32_t shndx; +} mb_elf_shtable_t; + +/* The module structure. */ +typedef struct mb_module { + caddr32_t mod_start; + caddr32_t mod_end; + caddr32_t mod_name; /* use as (char *) */ + uint32_t reserved; +} mb_module_t; + +/* + * Memory map data structure. Walked in a bizarre way - see mutltiboot + * documentation for example. + */ +typedef struct mb_memory_map { + 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 + */ +struct sol_netinfo { + uint8_t sn_infotype; + uint8_t sn_mactype; + uint8_t sn_maclen; + uint8_t sn_padding; + ulong_t sn_ciaddr; + ulong_t sn_siaddr; + ulong_t sn_giaddr; + ulong_t sn_netmask; + uint8_t sn_macaddr[1]; +}; + +/* identify bootp/dhcp reply or rarp/ifconfig */ +#define SN_TYPE_BOOTP 2 +#define SN_TYPE_RARP 0xf0 + + +#endif /* _ASM */ + + +#ifdef __cplusplus +} +#endif + +#endif /* _MULTIBOOT_H */ 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/uts/i86pc/conf/Mapfile.bios b/usr/src/uts/i86pc/conf/Mapfile.bios new file mode 100644 index 0000000000..18aa3ef9fc --- /dev/null +++ b/usr/src/uts/i86pc/conf/Mapfile.bios @@ -0,0 +1,30 @@ +# +# 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" + +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/i86pc/dboot/dboot_elfload.h b/usr/src/uts/i86pc/dboot/dboot_elfload.h new file mode 100644 index 0000000000..16b7a16011 --- /dev/null +++ b/usr/src/uts/i86pc/dboot/dboot_elfload.h @@ -0,0 +1,42 @@ +/* + * 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 _ELFLOAD_H +#define _ELFLOAD_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +extern int dboot_elfload64(uintptr_t); + +#ifdef __cplusplus +} +#endif + +#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/uts/i86pc/dboot/dboot_printf.h b/usr/src/uts/i86pc/dboot/dboot_printf.h new file mode 100644 index 0000000000..22cf561e51 --- /dev/null +++ b/usr/src/uts/i86pc/dboot/dboot_printf.h @@ -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. + */ + +#ifndef _DBOOT_PRINTF_H +#define _DBOOT_PRINTF_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * 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); + +/* + * Primitive version of panic, prints a message, waits for a keystroke, + * then resets the system + */ +/*PRINTFLIKE1*/ +extern void dboot_panic(char *fmt, ...) + __KPRINTFLIKE(1); + + +#ifdef __cplusplus +} +#endif + +#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/i86pc/os/hold_page.c b/usr/src/uts/i86pc/os/hold_page.c new file mode 100644 index 0000000000..1c11bc80f1 --- /dev/null +++ b/usr/src/uts/i86pc/os/hold_page.c @@ -0,0 +1,42 @@ +/* + * 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/hold_page.h> + +/*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/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/uts/i86pc/sys/debug_info.h b/usr/src/uts/i86pc/sys/debug_info.h new file mode 100644 index 0000000000..3c626fd360 --- /dev/null +++ b/usr/src/uts/i86pc/sys/debug_info.h @@ -0,0 +1,49 @@ +/* + * 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_DEBUG_INFO_H +#define _SYS_DEBUG_INFO_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/machparam.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEBUG_INFO_MAGIC 0xdeb116ed +#define DEBUG_INFO_VERSION 0x1 + +typedef struct debug_info { + uint32_t di_magic; + uint32_t di_version; +} debug_info_t; + +#ifdef __cplusplus +} +#endif + +#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/uts/i86pc/sys/machclock.h b/usr/src/uts/i86pc/sys/machclock.h new file mode 100644 index 0000000000..6b3686b95c --- /dev/null +++ b/usr/src/uts/i86pc/sys/machclock.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_MACHCLOCK_H +#define _SYS_MACHCLOCK_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * tod module name and operations + */ + +struct tod_ops; +typedef struct tod_ops tod_ops_t; + +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; +}; + +#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 /* _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/uts/i86pc/unix/dboot/Mapfile.dboot b/usr/src/uts/i86pc/unix/dboot/Mapfile.dboot new file mode 100644 index 0000000000..a8c6856dfe --- /dev/null +++ b/usr/src/uts/i86pc/unix/dboot/Mapfile.dboot @@ -0,0 +1,32 @@ +# +# 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" +# + +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/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/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/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/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/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/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/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 |
