aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile9
-rw-r--r--Makefile.inc112
-rw-r--r--UPDATING7
-rw-r--r--bin/csh/Makefile57
-rw-r--r--bin/csh/iconv_stub.c6
-rw-r--r--bin/dd/args.c90
-rw-r--r--bin/dd/dd.17
-rw-r--r--bin/sh/redir.c29
-rw-r--r--bin/sh/sh.125
-rw-r--r--bin/test/test.c164
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c6
-rw-r--r--contrib/bsnmp/snmp_mibII/mibII.c12
-rw-r--r--contrib/elftoolchain/readelf/readelf.c35
-rw-r--r--contrib/libucl/tests/.gitignore8
-rw-r--r--contrib/libxo/.gitignore46
-rw-r--r--contrib/ofed/librdmacm/examples/build/cmatose/Makefile3
-rw-r--r--contrib/ofed/librdmacm/examples/build/mckey/Makefile3
-rw-r--r--contrib/ofed/librdmacm/examples/build/udaddy/Makefile3
-rw-r--r--contrib/openresolv/Makefile8
-rw-r--r--contrib/openresolv/resolvconf.8.in2
-rw-r--r--contrib/openresolv/resolvconf.conf.5.in11
-rw-r--r--contrib/openresolv/resolvconf.in1
-rw-r--r--contrib/openresolv/unbound.in3
-rw-r--r--contrib/smbfs/smbutil/print.c1
-rw-r--r--contrib/unbound/.gitignore38
-rw-r--r--crypto/openssh/sshd_config2
-rw-r--r--crypto/openssh/sshd_config.52
-rw-r--r--crypto/openssl/ACKNOWLEDGMENTS32
-rw-r--r--crypto/openssl/CHANGES48
-rwxr-xr-xcrypto/openssl/Configure33
-rw-r--r--crypto/openssl/INSTALL8
-rw-r--r--crypto/openssl/LICENSE2
-rw-r--r--crypto/openssl/Makefile40
-rw-r--r--crypto/openssl/Makefile.org38
-rw-r--r--crypto/openssl/NEWS5
-rw-r--r--crypto/openssl/README13
-rw-r--r--crypto/openssl/apps/engine.c2
-rw-r--r--crypto/openssl/apps/ocsp.c2
-rw-r--r--crypto/openssl/apps/pkcs12.c42
-rw-r--r--crypto/openssl/apps/pkeyutl.c38
-rw-r--r--crypto/openssl/apps/s_client.c2
-rw-r--r--crypto/openssl/apps/s_server.c2
-rw-r--r--crypto/openssl/apps/speed.c2
-rw-r--r--crypto/openssl/apps/x509.c7
-rw-r--r--crypto/openssl/crypto/aes/aes.h2
-rw-r--r--crypto/openssl/crypto/aes/aes_cbc.c2
-rw-r--r--crypto/openssl/crypto/aes/aes_cfb.c2
-rw-r--r--crypto/openssl/crypto/aes/aes_core.c2
-rw-r--r--crypto/openssl/crypto/aes/aes_ctr.c2
-rw-r--r--crypto/openssl/crypto/aes/aes_ecb.c2
-rw-r--r--crypto/openssl/crypto/aes/aes_ige.c2
-rw-r--r--crypto/openssl/crypto/aes/aes_locl.h2
-rw-r--r--crypto/openssl/crypto/aes/aes_misc.c2
-rw-r--r--crypto/openssl/crypto/aes/aes_ofb.c2
-rw-r--r--crypto/openssl/crypto/aes/aes_x86core.c2
-rwxr-xr-xcrypto/openssl/crypto/aes/asm/aesni-mb-x86_64.pl2
-rwxr-xr-xcrypto/openssl/crypto/aes/asm/aesni-sha1-x86_64.pl2
-rwxr-xr-xcrypto/openssl/crypto/aes/asm/aesni-sha256-x86_64.pl2
-rw-r--r--crypto/openssl/crypto/bio/bio.h8
-rw-r--r--crypto/openssl/crypto/bio/bss_bio.c2
-rw-r--r--crypto/openssl/crypto/bio/bss_conn.c31
-rw-r--r--crypto/openssl/crypto/bio/bss_dgram.c2
-rwxr-xr-xcrypto/openssl/crypto/bn/asm/rsaz-x86_64.pl2
-rwxr-xr-xcrypto/openssl/crypto/bn/asm/x86_64-mont.pl2
-rwxr-xr-xcrypto/openssl/crypto/bn/asm/x86_64-mont5.pl2
-rw-r--r--crypto/openssl/crypto/bn/bn_exp.c41
-rw-r--r--crypto/openssl/crypto/bn/exptest.c82
-rw-r--r--crypto/openssl/crypto/camellia/camellia.c4
-rw-r--r--crypto/openssl/crypto/camellia/camellia.h2
-rw-r--r--crypto/openssl/crypto/camellia/cmll_cbc.c2
-rw-r--r--crypto/openssl/crypto/camellia/cmll_cfb.c2
-rw-r--r--crypto/openssl/crypto/camellia/cmll_ctr.c2
-rw-r--r--crypto/openssl/crypto/camellia/cmll_ecb.c2
-rw-r--r--crypto/openssl/crypto/camellia/cmll_locl.h2
-rw-r--r--crypto/openssl/crypto/camellia/cmll_misc.c2
-rw-r--r--crypto/openssl/crypto/camellia/cmll_ofb.c2
-rw-r--r--crypto/openssl/crypto/camellia/cmll_utl.c2
-rw-r--r--crypto/openssl/crypto/des/des_old.c2
-rw-r--r--crypto/openssl/crypto/des/des_old.h2
-rw-r--r--crypto/openssl/crypto/des/des_old2.c2
-rw-r--r--crypto/openssl/crypto/dh/dh.h1
-rw-r--r--crypto/openssl/crypto/dh/dh_check.c35
-rw-r--r--crypto/openssl/crypto/dh/dhtest.c85
-rw-r--r--crypto/openssl/crypto/dsa/dsa_ossl.c8
-rw-r--r--crypto/openssl/crypto/dso/dso.h2
-rw-r--r--crypto/openssl/crypto/dso/dso_dl.c2
-rw-r--r--crypto/openssl/crypto/dso/dso_dlfcn.c2
-rw-r--r--crypto/openssl/crypto/dso/dso_lib.c2
-rwxr-xr-xcrypto/openssl/crypto/ec/asm/ecp_nistz256-x86_64.pl2
-rw-r--r--crypto/openssl/crypto/ec/ec2_smpl.c1
-rw-r--r--crypto/openssl/crypto/ec/ec_key.c2
-rw-r--r--crypto/openssl/crypto/ec/ecp_nistz256_table.c2
-rw-r--r--crypto/openssl/crypto/ec/ectest.c2
-rw-r--r--crypto/openssl/crypto/engine/eng_all.c2
-rw-r--r--crypto/openssl/crypto/evp/e_camellia.c2
-rw-r--r--crypto/openssl/crypto/evp/e_old.c2
-rw-r--r--crypto/openssl/crypto/evp/e_seed.c2
-rw-r--r--crypto/openssl/crypto/mem_clr.c2
-rwxr-xr-xcrypto/openssl/crypto/modes/asm/aesni-gcm-x86_64.pl2
-rwxr-xr-xcrypto/openssl/crypto/modes/asm/ghash-x86_64.pl2
-rw-r--r--crypto/openssl/crypto/o_dir.c2
-rw-r--r--crypto/openssl/crypto/o_dir.h2
-rw-r--r--crypto/openssl/crypto/o_dir_test.c2
-rw-r--r--crypto/openssl/crypto/o_str.c2
-rw-r--r--crypto/openssl/crypto/o_str.h2
-rw-r--r--crypto/openssl/crypto/o_time.c2
-rw-r--r--crypto/openssl/crypto/o_time.h2
-rw-r--r--crypto/openssl/crypto/opensslv.h6
-rw-r--r--crypto/openssl/crypto/rc4/rc4_utl.c2
-rw-r--r--crypto/openssl/crypto/rsa/rsa_chk.c2
-rw-r--r--crypto/openssl/crypto/rsa/rsa_sign.c4
-rw-r--r--crypto/openssl/crypto/seed/seed_cbc.c2
-rw-r--r--crypto/openssl/crypto/seed/seed_cfb.c2
-rw-r--r--crypto/openssl/crypto/seed/seed_ecb.c2
-rw-r--r--crypto/openssl/crypto/seed/seed_ofb.c2
-rwxr-xr-xcrypto/openssl/crypto/sha/asm/sha1-mb-x86_64.pl2
-rwxr-xr-xcrypto/openssl/crypto/sha/asm/sha1-x86_64.pl2
-rwxr-xr-xcrypto/openssl/crypto/sha/asm/sha256-mb-x86_64.pl2
-rwxr-xr-xcrypto/openssl/crypto/sha/asm/sha512-x86_64.pl2
-rw-r--r--crypto/openssl/crypto/sha/sha1test.c2
-rw-r--r--crypto/openssl/crypto/store/store.h2
-rw-r--r--crypto/openssl/crypto/store/str_lib.c2
-rw-r--r--crypto/openssl/crypto/store/str_locl.h2
-rw-r--r--crypto/openssl/crypto/store/str_mem.c2
-rw-r--r--crypto/openssl/crypto/store/str_meth.c2
-rw-r--r--crypto/openssl/crypto/ts/ts_rsp_verify.c3
-rw-r--r--crypto/openssl/crypto/ui/ui.h2
-rw-r--r--crypto/openssl/crypto/ui/ui_compat.c2
-rw-r--r--crypto/openssl/crypto/ui/ui_compat.h2
-rw-r--r--crypto/openssl/crypto/ui/ui_lib.c2
-rw-r--r--crypto/openssl/crypto/ui/ui_locl.h2
-rw-r--r--crypto/openssl/crypto/ui/ui_openssl.c2
-rw-r--r--crypto/openssl/crypto/ui/ui_util.c2
-rw-r--r--crypto/openssl/crypto/x509/x509_vfy.c39
-rw-r--r--crypto/openssl/crypto/x509/x509_vfy.h2
-rw-r--r--crypto/openssl/crypto/x509/x509_vpm.c4
-rw-r--r--crypto/openssl/crypto/x509v3/v3_pci.c2
-rw-r--r--crypto/openssl/crypto/x509v3/v3_pcia.c2
-rw-r--r--crypto/openssl/crypto/x509v3/v3_utl.c3
-rw-r--r--crypto/openssl/crypto/x509v3/v3nametest.c10
-rw-r--r--crypto/openssl/doc/apps/s_time.pod4
-rw-r--r--crypto/openssl/doc/crypto/BIO_s_connect.pod4
-rw-r--r--crypto/openssl/doc/ssl/SSL_CTX_set1_verify_cert_store.pod8
-rw-r--r--crypto/openssl/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod73
-rw-r--r--crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod29
-rw-r--r--crypto/openssl/engines/e_chil.c2
-rw-r--r--crypto/openssl/ssl/d1_both.c70
-rw-r--r--crypto/openssl/ssl/kssl.c2
-rw-r--r--crypto/openssl/ssl/kssl.h2
-rw-r--r--crypto/openssl/ssl/kssl_lcl.h2
-rw-r--r--crypto/openssl/ssl/s2_srvr.c20
-rw-r--r--crypto/openssl/ssl/s3_clnt.c63
-rw-r--r--crypto/openssl/ssl/s3_lib.c34
-rw-r--r--crypto/openssl/ssl/s3_srvr.c25
-rw-r--r--crypto/openssl/ssl/ssl.h6
-rw-r--r--crypto/openssl/ssl/ssl_err.c2
-rw-r--r--crypto/openssl/ssl/ssl_lib.c5
-rw-r--r--crypto/openssl/ssl/ssl_sess.c3
-rw-r--r--crypto/openssl/ssl/t1_enc.c2
-rw-r--r--crypto/openssl/ssl/t1_lib.c22
-rwxr-xr-xcrypto/openssl/util/domd4
-rw-r--r--crypto/openssl/util/pl/VC-32.pl8
-rwxr-xr-xcrypto/openssl/util/pod2mantest58
-rw-r--r--etc/defaults/rc.conf13
-rwxr-xr-xetc/periodic/daily/800.scrub-zfs10
-rw-r--r--etc/periodic/security/security.functions2
-rwxr-xr-xetc/rc.d/jail2
-rw-r--r--lib/libbluetooth/bluetooth.h2
-rw-r--r--lib/libc/db/hash/hash.h10
-rw-r--r--lib/libc/db/hash/hash_buf.c2
-rw-r--r--lib/libc/gen/Makefile.inc4
-rw-r--r--lib/libc/gen/recvmmsg.c96
-rw-r--r--lib/libc/gen/sendmmsg.c64
-rw-r--r--lib/libc/include/namespace.h2
-rw-r--r--lib/libc/include/un-namespace.h2
-rw-r--r--lib/libc/nls/msgcat.c26
-rw-r--r--lib/libc/sys/Symbol.map2
-rw-r--r--lib/libc/sys/connect.210
-rw-r--r--lib/libc/sys/recv.295
-rw-r--r--lib/libc/sys/send.258
-rw-r--r--lib/libc/tests/gen/Makefile1
-rw-r--r--lib/libc/tests/gen/dlopen_empty_test.c97
-rw-r--r--lib/libdevctl/devctl.39
-rw-r--r--lib/libmemstat/memstat_uma.c1
-rw-r--r--lib/libsysdecode/syscallnames.c10
-rw-r--r--lib/libsysdecode/sysdecode.316
-rw-r--r--lib/libsysdecode/sysdecode.h12
-rw-r--r--libexec/atrun/atrun.c3
-rw-r--r--libexec/rtld-elf/map_object.c12
-rw-r--r--sbin/ggate/ggated/Makefile2
-rw-r--r--sbin/ggate/ggated/ggated.814
-rw-r--r--sbin/ggate/ggated/ggated.c61
-rw-r--r--sbin/nvmecontrol/Makefile2
-rw-r--r--sbin/nvmecontrol/nvmecontrol.817
-rw-r--r--sbin/nvmecontrol/nvmecontrol.c1
-rw-r--r--sbin/nvmecontrol/nvmecontrol.h4
-rw-r--r--sbin/nvmecontrol/power.c185
-rw-r--r--sbin/pfctl/pf_print_state.c18
-rw-r--r--sbin/rcorder/rcorder.c7
-rw-r--r--sbin/swapon/swapon.c4
-rw-r--r--secure/lib/libcrypto/Makefile.inc4
-rw-r--r--secure/lib/libcrypto/man/ASN1_OBJECT_new.34
-rw-r--r--secure/lib/libcrypto/man/ASN1_STRING_length.34
-rw-r--r--secure/lib/libcrypto/man/ASN1_STRING_new.34
-rw-r--r--secure/lib/libcrypto/man/ASN1_STRING_print_ex.34
-rw-r--r--secure/lib/libcrypto/man/ASN1_TIME_set.34
-rw-r--r--secure/lib/libcrypto/man/ASN1_generate_nconf.34
-rw-r--r--secure/lib/libcrypto/man/BIO_ctrl.34
-rw-r--r--secure/lib/libcrypto/man/BIO_f_base64.34
-rw-r--r--secure/lib/libcrypto/man/BIO_f_buffer.34
-rw-r--r--secure/lib/libcrypto/man/BIO_f_cipher.34
-rw-r--r--secure/lib/libcrypto/man/BIO_f_md.34
-rw-r--r--secure/lib/libcrypto/man/BIO_f_null.34
-rw-r--r--secure/lib/libcrypto/man/BIO_f_ssl.34
-rw-r--r--secure/lib/libcrypto/man/BIO_find_type.34
-rw-r--r--secure/lib/libcrypto/man/BIO_new.34
-rw-r--r--secure/lib/libcrypto/man/BIO_new_CMS.34
-rw-r--r--secure/lib/libcrypto/man/BIO_push.34
-rw-r--r--secure/lib/libcrypto/man/BIO_read.34
-rw-r--r--secure/lib/libcrypto/man/BIO_s_accept.34
-rw-r--r--secure/lib/libcrypto/man/BIO_s_bio.34
-rw-r--r--secure/lib/libcrypto/man/BIO_s_connect.38
-rw-r--r--secure/lib/libcrypto/man/BIO_s_fd.34
-rw-r--r--secure/lib/libcrypto/man/BIO_s_file.34
-rw-r--r--secure/lib/libcrypto/man/BIO_s_mem.34
-rw-r--r--secure/lib/libcrypto/man/BIO_s_null.34
-rw-r--r--secure/lib/libcrypto/man/BIO_s_socket.34
-rw-r--r--secure/lib/libcrypto/man/BIO_set_callback.34
-rw-r--r--secure/lib/libcrypto/man/BIO_should_retry.34
-rw-r--r--secure/lib/libcrypto/man/BN_BLINDING_new.34
-rw-r--r--secure/lib/libcrypto/man/BN_CTX_new.34
-rw-r--r--secure/lib/libcrypto/man/BN_CTX_start.34
-rw-r--r--secure/lib/libcrypto/man/BN_add.34
-rw-r--r--secure/lib/libcrypto/man/BN_add_word.34
-rw-r--r--secure/lib/libcrypto/man/BN_bn2bin.34
-rw-r--r--secure/lib/libcrypto/man/BN_cmp.34
-rw-r--r--secure/lib/libcrypto/man/BN_copy.34
-rw-r--r--secure/lib/libcrypto/man/BN_generate_prime.34
-rw-r--r--secure/lib/libcrypto/man/BN_mod_inverse.34
-rw-r--r--secure/lib/libcrypto/man/BN_mod_mul_montgomery.34
-rw-r--r--secure/lib/libcrypto/man/BN_mod_mul_reciprocal.34
-rw-r--r--secure/lib/libcrypto/man/BN_new.34
-rw-r--r--secure/lib/libcrypto/man/BN_num_bytes.34
-rw-r--r--secure/lib/libcrypto/man/BN_rand.34
-rw-r--r--secure/lib/libcrypto/man/BN_set_bit.34
-rw-r--r--secure/lib/libcrypto/man/BN_swap.34
-rw-r--r--secure/lib/libcrypto/man/BN_zero.34
-rw-r--r--secure/lib/libcrypto/man/CMS_add0_cert.34
-rw-r--r--secure/lib/libcrypto/man/CMS_add1_recipient_cert.34
-rw-r--r--secure/lib/libcrypto/man/CMS_add1_signer.34
-rw-r--r--secure/lib/libcrypto/man/CMS_compress.34
-rw-r--r--secure/lib/libcrypto/man/CMS_decrypt.34
-rw-r--r--secure/lib/libcrypto/man/CMS_encrypt.34
-rw-r--r--secure/lib/libcrypto/man/CMS_final.34
-rw-r--r--secure/lib/libcrypto/man/CMS_get0_RecipientInfos.34
-rw-r--r--secure/lib/libcrypto/man/CMS_get0_SignerInfos.34
-rw-r--r--secure/lib/libcrypto/man/CMS_get0_type.34
-rw-r--r--secure/lib/libcrypto/man/CMS_get1_ReceiptRequest.34
-rw-r--r--secure/lib/libcrypto/man/CMS_sign.34
-rw-r--r--secure/lib/libcrypto/man/CMS_sign_receipt.34
-rw-r--r--secure/lib/libcrypto/man/CMS_uncompress.34
-rw-r--r--secure/lib/libcrypto/man/CMS_verify.34
-rw-r--r--secure/lib/libcrypto/man/CMS_verify_receipt.34
-rw-r--r--secure/lib/libcrypto/man/CONF_modules_free.34
-rw-r--r--secure/lib/libcrypto/man/CONF_modules_load_file.34
-rw-r--r--secure/lib/libcrypto/man/CRYPTO_set_ex_data.34
-rw-r--r--secure/lib/libcrypto/man/DH_generate_key.34
-rw-r--r--secure/lib/libcrypto/man/DH_generate_parameters.34
-rw-r--r--secure/lib/libcrypto/man/DH_get_ex_new_index.34
-rw-r--r--secure/lib/libcrypto/man/DH_new.34
-rw-r--r--secure/lib/libcrypto/man/DH_set_method.34
-rw-r--r--secure/lib/libcrypto/man/DH_size.34
-rw-r--r--secure/lib/libcrypto/man/DSA_SIG_new.34
-rw-r--r--secure/lib/libcrypto/man/DSA_do_sign.34
-rw-r--r--secure/lib/libcrypto/man/DSA_dup_DH.34
-rw-r--r--secure/lib/libcrypto/man/DSA_generate_key.34
-rw-r--r--secure/lib/libcrypto/man/DSA_generate_parameters.34
-rw-r--r--secure/lib/libcrypto/man/DSA_get_ex_new_index.34
-rw-r--r--secure/lib/libcrypto/man/DSA_new.34
-rw-r--r--secure/lib/libcrypto/man/DSA_set_method.34
-rw-r--r--secure/lib/libcrypto/man/DSA_sign.34
-rw-r--r--secure/lib/libcrypto/man/DSA_size.34
-rw-r--r--secure/lib/libcrypto/man/EC_GFp_simple_method.34
-rw-r--r--secure/lib/libcrypto/man/EC_GROUP_copy.34
-rw-r--r--secure/lib/libcrypto/man/EC_GROUP_new.34
-rw-r--r--secure/lib/libcrypto/man/EC_KEY_new.34
-rw-r--r--secure/lib/libcrypto/man/EC_POINT_add.34
-rw-r--r--secure/lib/libcrypto/man/EC_POINT_new.34
-rw-r--r--secure/lib/libcrypto/man/ERR_GET_LIB.34
-rw-r--r--secure/lib/libcrypto/man/ERR_clear_error.34
-rw-r--r--secure/lib/libcrypto/man/ERR_error_string.34
-rw-r--r--secure/lib/libcrypto/man/ERR_get_error.34
-rw-r--r--secure/lib/libcrypto/man/ERR_load_crypto_strings.34
-rw-r--r--secure/lib/libcrypto/man/ERR_load_strings.34
-rw-r--r--secure/lib/libcrypto/man/ERR_print_errors.34
-rw-r--r--secure/lib/libcrypto/man/ERR_put_error.34
-rw-r--r--secure/lib/libcrypto/man/ERR_remove_state.34
-rw-r--r--secure/lib/libcrypto/man/ERR_set_mark.34
-rw-r--r--secure/lib/libcrypto/man/EVP_BytesToKey.34
-rw-r--r--secure/lib/libcrypto/man/EVP_DigestInit.34
-rw-r--r--secure/lib/libcrypto/man/EVP_DigestSignInit.34
-rw-r--r--secure/lib/libcrypto/man/EVP_DigestVerifyInit.34
-rw-r--r--secure/lib/libcrypto/man/EVP_EncryptInit.34
-rw-r--r--secure/lib/libcrypto/man/EVP_OpenInit.34
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_CTX_ctrl.34
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_CTX_new.34
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_cmp.34
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_decrypt.34
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_derive.34
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_encrypt.34
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_get_default_digest.34
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_keygen.34
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_new.34
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_print_private.34
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_set1_RSA.34
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_sign.34
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_verify.34
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_verify_recover.34
-rw-r--r--secure/lib/libcrypto/man/EVP_SealInit.34
-rw-r--r--secure/lib/libcrypto/man/EVP_SignInit.34
-rw-r--r--secure/lib/libcrypto/man/EVP_VerifyInit.34
-rw-r--r--secure/lib/libcrypto/man/OBJ_nid2obj.34
-rw-r--r--secure/lib/libcrypto/man/OPENSSL_Applink.34
-rw-r--r--secure/lib/libcrypto/man/OPENSSL_VERSION_NUMBER.34
-rw-r--r--secure/lib/libcrypto/man/OPENSSL_config.34
-rw-r--r--secure/lib/libcrypto/man/OPENSSL_ia32cap.34
-rw-r--r--secure/lib/libcrypto/man/OPENSSL_instrument_bus.34
-rw-r--r--secure/lib/libcrypto/man/OPENSSL_load_builtin_modules.34
-rw-r--r--secure/lib/libcrypto/man/OpenSSL_add_all_algorithms.34
-rw-r--r--secure/lib/libcrypto/man/PEM_write_bio_CMS_stream.34
-rw-r--r--secure/lib/libcrypto/man/PEM_write_bio_PKCS7_stream.34
-rw-r--r--secure/lib/libcrypto/man/PKCS12_create.34
-rw-r--r--secure/lib/libcrypto/man/PKCS12_parse.34
-rw-r--r--secure/lib/libcrypto/man/PKCS7_decrypt.34
-rw-r--r--secure/lib/libcrypto/man/PKCS7_encrypt.34
-rw-r--r--secure/lib/libcrypto/man/PKCS7_sign.34
-rw-r--r--secure/lib/libcrypto/man/PKCS7_sign_add_signer.34
-rw-r--r--secure/lib/libcrypto/man/PKCS7_verify.34
-rw-r--r--secure/lib/libcrypto/man/RAND_add.34
-rw-r--r--secure/lib/libcrypto/man/RAND_bytes.34
-rw-r--r--secure/lib/libcrypto/man/RAND_cleanup.34
-rw-r--r--secure/lib/libcrypto/man/RAND_egd.34
-rw-r--r--secure/lib/libcrypto/man/RAND_load_file.34
-rw-r--r--secure/lib/libcrypto/man/RAND_set_rand_method.34
-rw-r--r--secure/lib/libcrypto/man/RSA_blinding_on.34
-rw-r--r--secure/lib/libcrypto/man/RSA_check_key.34
-rw-r--r--secure/lib/libcrypto/man/RSA_generate_key.34
-rw-r--r--secure/lib/libcrypto/man/RSA_get_ex_new_index.34
-rw-r--r--secure/lib/libcrypto/man/RSA_new.34
-rw-r--r--secure/lib/libcrypto/man/RSA_padding_add_PKCS1_type_1.34
-rw-r--r--secure/lib/libcrypto/man/RSA_print.34
-rw-r--r--secure/lib/libcrypto/man/RSA_private_encrypt.34
-rw-r--r--secure/lib/libcrypto/man/RSA_public_encrypt.34
-rw-r--r--secure/lib/libcrypto/man/RSA_set_method.34
-rw-r--r--secure/lib/libcrypto/man/RSA_sign.34
-rw-r--r--secure/lib/libcrypto/man/RSA_sign_ASN1_OCTET_STRING.34
-rw-r--r--secure/lib/libcrypto/man/RSA_size.34
-rw-r--r--secure/lib/libcrypto/man/SMIME_read_CMS.34
-rw-r--r--secure/lib/libcrypto/man/SMIME_read_PKCS7.34
-rw-r--r--secure/lib/libcrypto/man/SMIME_write_CMS.34
-rw-r--r--secure/lib/libcrypto/man/SMIME_write_PKCS7.34
-rw-r--r--secure/lib/libcrypto/man/X509_NAME_ENTRY_get_object.34
-rw-r--r--secure/lib/libcrypto/man/X509_NAME_add_entry_by_txt.34
-rw-r--r--secure/lib/libcrypto/man/X509_NAME_get_index_by_NID.34
-rw-r--r--secure/lib/libcrypto/man/X509_NAME_print_ex.34
-rw-r--r--secure/lib/libcrypto/man/X509_STORE_CTX_get_error.34
-rw-r--r--secure/lib/libcrypto/man/X509_STORE_CTX_get_ex_new_index.34
-rw-r--r--secure/lib/libcrypto/man/X509_STORE_CTX_new.34
-rw-r--r--secure/lib/libcrypto/man/X509_STORE_CTX_set_verify_cb.34
-rw-r--r--secure/lib/libcrypto/man/X509_STORE_set_verify_cb_func.34
-rw-r--r--secure/lib/libcrypto/man/X509_VERIFY_PARAM_set_flags.34
-rw-r--r--secure/lib/libcrypto/man/X509_check_host.34
-rw-r--r--secure/lib/libcrypto/man/X509_new.34
-rw-r--r--secure/lib/libcrypto/man/X509_verify_cert.34
-rw-r--r--secure/lib/libcrypto/man/bio.34
-rw-r--r--secure/lib/libcrypto/man/blowfish.34
-rw-r--r--secure/lib/libcrypto/man/bn.34
-rw-r--r--secure/lib/libcrypto/man/bn_internal.34
-rw-r--r--secure/lib/libcrypto/man/buffer.34
-rw-r--r--secure/lib/libcrypto/man/crypto.34
-rw-r--r--secure/lib/libcrypto/man/d2i_ASN1_OBJECT.34
-rw-r--r--secure/lib/libcrypto/man/d2i_CMS_ContentInfo.34
-rw-r--r--secure/lib/libcrypto/man/d2i_DHparams.34
-rw-r--r--secure/lib/libcrypto/man/d2i_DSAPublicKey.34
-rw-r--r--secure/lib/libcrypto/man/d2i_ECPKParameters.34
-rw-r--r--secure/lib/libcrypto/man/d2i_ECPrivateKey.34
-rw-r--r--secure/lib/libcrypto/man/d2i_PKCS8PrivateKey.34
-rw-r--r--secure/lib/libcrypto/man/d2i_RSAPublicKey.34
-rw-r--r--secure/lib/libcrypto/man/d2i_X509.34
-rw-r--r--secure/lib/libcrypto/man/d2i_X509_ALGOR.34
-rw-r--r--secure/lib/libcrypto/man/d2i_X509_CRL.34
-rw-r--r--secure/lib/libcrypto/man/d2i_X509_NAME.34
-rw-r--r--secure/lib/libcrypto/man/d2i_X509_REQ.34
-rw-r--r--secure/lib/libcrypto/man/d2i_X509_SIG.34
-rw-r--r--secure/lib/libcrypto/man/des.34
-rw-r--r--secure/lib/libcrypto/man/dh.34
-rw-r--r--secure/lib/libcrypto/man/dsa.34
-rw-r--r--secure/lib/libcrypto/man/ec.34
-rw-r--r--secure/lib/libcrypto/man/ecdsa.34
-rw-r--r--secure/lib/libcrypto/man/engine.34
-rw-r--r--secure/lib/libcrypto/man/err.34
-rw-r--r--secure/lib/libcrypto/man/evp.34
-rw-r--r--secure/lib/libcrypto/man/hmac.34
-rw-r--r--secure/lib/libcrypto/man/i2d_CMS_bio_stream.34
-rw-r--r--secure/lib/libcrypto/man/i2d_PKCS7_bio_stream.34
-rw-r--r--secure/lib/libcrypto/man/lh_stats.34
-rw-r--r--secure/lib/libcrypto/man/lhash.34
-rw-r--r--secure/lib/libcrypto/man/md5.34
-rw-r--r--secure/lib/libcrypto/man/mdc2.34
-rw-r--r--secure/lib/libcrypto/man/pem.34
-rw-r--r--secure/lib/libcrypto/man/rand.34
-rw-r--r--secure/lib/libcrypto/man/rc4.34
-rw-r--r--secure/lib/libcrypto/man/ripemd.34
-rw-r--r--secure/lib/libcrypto/man/rsa.34
-rw-r--r--secure/lib/libcrypto/man/sha.34
-rw-r--r--secure/lib/libcrypto/man/threads.34
-rw-r--r--secure/lib/libcrypto/man/ui.34
-rw-r--r--secure/lib/libcrypto/man/ui_compat.34
-rw-r--r--secure/lib/libcrypto/man/x509.34
-rw-r--r--secure/lib/libssl/Makefile.man5
-rw-r--r--secure/lib/libssl/man/SSL_CIPHER_get_name.34
-rw-r--r--secure/lib/libssl/man/SSL_COMP_add_compression_method.34
-rw-r--r--secure/lib/libssl/man/SSL_CONF_CTX_new.34
-rw-r--r--secure/lib/libssl/man/SSL_CONF_CTX_set1_prefix.34
-rw-r--r--secure/lib/libssl/man/SSL_CONF_CTX_set_flags.34
-rw-r--r--secure/lib/libssl/man/SSL_CONF_CTX_set_ssl_ctx.34
-rw-r--r--secure/lib/libssl/man/SSL_CONF_cmd.34
-rw-r--r--secure/lib/libssl/man/SSL_CONF_cmd_argv.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_add1_chain_cert.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_add_extra_chain_cert.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_add_session.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_ctrl.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_flush_sessions.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_free.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_get0_param.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_get_ex_new_index.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_get_verify_mode.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_load_verify_locations.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_new.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_sess_number.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_sess_set_cache_size.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_sess_set_get_cb.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_sessions.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set1_curves.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set1_verify_cert_store.312
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_cert_cb.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_cert_store.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_cert_verify_callback.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_cipher_list.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_client_CA_list.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_client_cert_cb.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_custom_cli_ext.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_default_passwd_cb.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_generate_session_id.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_info_callback.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_max_cert_list.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_mode.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_msg_callback.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_options.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_psk_client_callback.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_quiet_shutdown.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_read_ahead.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_session_cache_mode.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_session_id_context.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_ssl_version.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_timeout.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_tlsext_status_cb.3207
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_tlsext_ticket_key_cb.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_tmp_dh_callback.333
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_tmp_rsa_callback.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_set_verify.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_use_certificate.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_use_psk_identity_hint.34
-rw-r--r--secure/lib/libssl/man/SSL_CTX_use_serverinfo.34
-rw-r--r--secure/lib/libssl/man/SSL_SESSION_free.34
-rw-r--r--secure/lib/libssl/man/SSL_SESSION_get_ex_new_index.34
-rw-r--r--secure/lib/libssl/man/SSL_SESSION_get_time.34
-rw-r--r--secure/lib/libssl/man/SSL_accept.34
-rw-r--r--secure/lib/libssl/man/SSL_alert_type_string.34
-rw-r--r--secure/lib/libssl/man/SSL_check_chain.34
-rw-r--r--secure/lib/libssl/man/SSL_clear.34
-rw-r--r--secure/lib/libssl/man/SSL_connect.34
-rw-r--r--secure/lib/libssl/man/SSL_do_handshake.34
-rw-r--r--secure/lib/libssl/man/SSL_free.34
-rw-r--r--secure/lib/libssl/man/SSL_get_SSL_CTX.34
-rw-r--r--secure/lib/libssl/man/SSL_get_ciphers.34
-rw-r--r--secure/lib/libssl/man/SSL_get_client_CA_list.34
-rw-r--r--secure/lib/libssl/man/SSL_get_current_cipher.34
-rw-r--r--secure/lib/libssl/man/SSL_get_default_timeout.34
-rw-r--r--secure/lib/libssl/man/SSL_get_error.34
-rw-r--r--secure/lib/libssl/man/SSL_get_ex_data_X509_STORE_CTX_idx.34
-rw-r--r--secure/lib/libssl/man/SSL_get_ex_new_index.34
-rw-r--r--secure/lib/libssl/man/SSL_get_fd.34
-rw-r--r--secure/lib/libssl/man/SSL_get_peer_cert_chain.34
-rw-r--r--secure/lib/libssl/man/SSL_get_peer_certificate.34
-rw-r--r--secure/lib/libssl/man/SSL_get_psk_identity.34
-rw-r--r--secure/lib/libssl/man/SSL_get_rbio.34
-rw-r--r--secure/lib/libssl/man/SSL_get_session.34
-rw-r--r--secure/lib/libssl/man/SSL_get_verify_result.34
-rw-r--r--secure/lib/libssl/man/SSL_get_version.34
-rw-r--r--secure/lib/libssl/man/SSL_library_init.34
-rw-r--r--secure/lib/libssl/man/SSL_load_client_CA_file.34
-rw-r--r--secure/lib/libssl/man/SSL_new.34
-rw-r--r--secure/lib/libssl/man/SSL_pending.34
-rw-r--r--secure/lib/libssl/man/SSL_read.34
-rw-r--r--secure/lib/libssl/man/SSL_rstate_string.34
-rw-r--r--secure/lib/libssl/man/SSL_session_reused.34
-rw-r--r--secure/lib/libssl/man/SSL_set_bio.34
-rw-r--r--secure/lib/libssl/man/SSL_set_connect_state.34
-rw-r--r--secure/lib/libssl/man/SSL_set_fd.34
-rw-r--r--secure/lib/libssl/man/SSL_set_session.34
-rw-r--r--secure/lib/libssl/man/SSL_set_shutdown.34
-rw-r--r--secure/lib/libssl/man/SSL_set_verify_result.34
-rw-r--r--secure/lib/libssl/man/SSL_shutdown.34
-rw-r--r--secure/lib/libssl/man/SSL_state_string.34
-rw-r--r--secure/lib/libssl/man/SSL_want.34
-rw-r--r--secure/lib/libssl/man/SSL_write.34
-rw-r--r--secure/lib/libssl/man/d2i_SSL_SESSION.34
-rw-r--r--secure/lib/libssl/man/ssl.34
-rw-r--r--secure/usr.bin/openssl/man/CA.pl.14
-rw-r--r--secure/usr.bin/openssl/man/asn1parse.14
-rw-r--r--secure/usr.bin/openssl/man/c_rehash.14
-rw-r--r--secure/usr.bin/openssl/man/ca.14
-rw-r--r--secure/usr.bin/openssl/man/ciphers.14
-rw-r--r--secure/usr.bin/openssl/man/cms.14
-rw-r--r--secure/usr.bin/openssl/man/crl.14
-rw-r--r--secure/usr.bin/openssl/man/crl2pkcs7.14
-rw-r--r--secure/usr.bin/openssl/man/dgst.14
-rw-r--r--secure/usr.bin/openssl/man/dhparam.14
-rw-r--r--secure/usr.bin/openssl/man/dsa.14
-rw-r--r--secure/usr.bin/openssl/man/dsaparam.14
-rw-r--r--secure/usr.bin/openssl/man/ec.14
-rw-r--r--secure/usr.bin/openssl/man/ecparam.14
-rw-r--r--secure/usr.bin/openssl/man/enc.14
-rw-r--r--secure/usr.bin/openssl/man/errstr.14
-rw-r--r--secure/usr.bin/openssl/man/gendsa.14
-rw-r--r--secure/usr.bin/openssl/man/genpkey.14
-rw-r--r--secure/usr.bin/openssl/man/genrsa.14
-rw-r--r--secure/usr.bin/openssl/man/nseq.14
-rw-r--r--secure/usr.bin/openssl/man/ocsp.14
-rw-r--r--secure/usr.bin/openssl/man/openssl.14
-rw-r--r--secure/usr.bin/openssl/man/passwd.14
-rw-r--r--secure/usr.bin/openssl/man/pkcs12.14
-rw-r--r--secure/usr.bin/openssl/man/pkcs7.14
-rw-r--r--secure/usr.bin/openssl/man/pkcs8.14
-rw-r--r--secure/usr.bin/openssl/man/pkey.14
-rw-r--r--secure/usr.bin/openssl/man/pkeyparam.14
-rw-r--r--secure/usr.bin/openssl/man/pkeyutl.14
-rw-r--r--secure/usr.bin/openssl/man/rand.14
-rw-r--r--secure/usr.bin/openssl/man/req.14
-rw-r--r--secure/usr.bin/openssl/man/rsa.14
-rw-r--r--secure/usr.bin/openssl/man/rsautl.14
-rw-r--r--secure/usr.bin/openssl/man/s_client.14
-rw-r--r--secure/usr.bin/openssl/man/s_server.14
-rw-r--r--secure/usr.bin/openssl/man/s_time.18
-rw-r--r--secure/usr.bin/openssl/man/sess_id.14
-rw-r--r--secure/usr.bin/openssl/man/smime.14
-rw-r--r--secure/usr.bin/openssl/man/speed.14
-rw-r--r--secure/usr.bin/openssl/man/spkac.14
-rw-r--r--secure/usr.bin/openssl/man/ts.14
-rw-r--r--secure/usr.bin/openssl/man/tsget.14
-rw-r--r--secure/usr.bin/openssl/man/verify.14
-rw-r--r--secure/usr.bin/openssl/man/version.14
-rw-r--r--secure/usr.bin/openssl/man/x509.14
-rw-r--r--secure/usr.bin/openssl/man/x509v3_config.14
-rw-r--r--share/i18n/esdb/MISC/MISC.alias8
-rw-r--r--share/man/man4/filemon.423
-rw-r--r--share/man/man4/inet.426
-rw-r--r--share/man/man4/nvd.413
-rw-r--r--share/mk/bsd.dep.mk11
-rw-r--r--share/mk/bsd.incs.mk3
-rw-r--r--share/mk/bsd.links.mk6
-rw-r--r--share/mk/bsd.man.mk32
-rw-r--r--share/mk/bsd.nls.mk3
-rw-r--r--sys/amd64/amd64/uma_machdep.c1
-rw-r--r--sys/arm/allwinner/a20/a20_mp.c4
-rw-r--r--sys/arm/altera/socfpga/socfpga_mp.c4
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_mp.c3
-rw-r--r--sys/arm/annapurna/alpine/alpine_machdep.c2
-rw-r--r--sys/arm/arm/cpufunc.c323
-rw-r--r--sys/arm/arm/cpufunc_asm.S21
-rw-r--r--sys/arm/arm/cpufunc_asm_arm10.S76
-rw-r--r--sys/arm/arm/cpufunc_asm_arm11.S12
-rw-r--r--sys/arm/arm/cpufunc_asm_arm11x6.S11
-rw-r--r--sys/arm/arm/cpufunc_asm_arm9.S4
-rw-r--r--sys/arm/arm/cpufunc_asm_armv4.S5
-rw-r--r--sys/arm/arm/cpufunc_asm_armv5_ec.S4
-rw-r--r--sys/arm/arm/cpufunc_asm_armv7.S10
-rw-r--r--sys/arm/arm/cpufunc_asm_fa526.S29
-rw-r--r--sys/arm/arm/cpufunc_asm_xscale.S19
-rw-r--r--sys/arm/arm/cpufunc_asm_xscale_c3.S20
-rw-r--r--sys/arm/arm/cpuinfo.c7
-rw-r--r--sys/arm/arm/db_interface.c12
-rw-r--r--sys/arm/arm/debug_monitor.c161
-rw-r--r--sys/arm/arm/devmap.c10
-rw-r--r--sys/arm/arm/dump_machdep.c3
-rw-r--r--sys/arm/arm/elf_machdep.c2
-rw-r--r--sys/arm/arm/elf_trampoline.c13
-rw-r--r--sys/arm/arm/fiq.c2
-rw-r--r--sys/arm/arm/fusu.S91
-rw-r--r--sys/arm/arm/genassym.c23
-rw-r--r--sys/arm/arm/identcpu.c4
-rw-r--r--sys/arm/arm/locore-v6.S26
-rw-r--r--sys/arm/arm/machdep.c36
-rw-r--r--sys/arm/arm/mem.c3
-rw-r--r--sys/arm/arm/minidump_machdep.c7
-rw-r--r--sys/arm/arm/mp_machdep.c46
-rw-r--r--sys/arm/arm/pmap-v6-new.c6634
-rw-r--r--sys/arm/arm/pmap-v6.c9625
-rw-r--r--sys/arm/arm/pmap.c90
-rw-r--r--sys/arm/arm/swtch-v4.S377
-rw-r--r--sys/arm/arm/swtch-v6.S482
-rw-r--r--sys/arm/arm/swtch.S700
-rw-r--r--sys/arm/arm/sys_machdep.c9
-rw-r--r--sys/arm/arm/trap-v6.c56
-rw-r--r--sys/arm/arm/trap.c9
-rw-r--r--sys/arm/arm/vm_machdep.c1
-rw-r--r--sys/arm/at91/at91_machdep.c4
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2836_mp.c4
-rw-r--r--sys/arm/cavium/cns11xx/econa_machdep.c4
-rw-r--r--sys/arm/conf/NOTES2
-rw-r--r--sys/arm/conf/std.armv62
-rw-r--r--sys/arm/freescale/imx/imx6_mp.c3
-rw-r--r--sys/arm/freescale/vybrid/vf_ehci.c18
-rw-r--r--sys/arm/include/cpu-v4.h186
-rw-r--r--sys/arm/include/cpu-v6.h71
-rw-r--r--sys/arm/include/cpu.h8
-rw-r--r--sys/arm/include/cpuconf.h14
-rw-r--r--sys/arm/include/cpufunc.h138
-rw-r--r--sys/arm/include/debug_monitor.h6
-rw-r--r--sys/arm/include/kdb.h6
-rw-r--r--sys/arm/include/machdep.h4
-rw-r--r--sys/arm/include/param.h1
-rw-r--r--sys/arm/include/pcpu.h7
-rw-r--r--sys/arm/include/pmap-v6.h61
-rw-r--r--sys/arm/include/pmap.h180
-rw-r--r--sys/arm/include/pte.h8
-rw-r--r--sys/arm/include/reg.h4
-rw-r--r--sys/arm/include/sf_buf.h6
-rw-r--r--sys/arm/include/smp.h8
-rw-r--r--sys/arm/include/vm.h20
-rw-r--r--sys/arm/mv/armada38x/pmsu.c5
-rw-r--r--sys/arm/mv/armadaxp/armadaxp.c2
-rw-r--r--sys/arm/mv/armadaxp/armadaxp_mp.c5
-rw-r--r--sys/arm/mv/mv_common.c2
-rw-r--r--sys/arm/mv/mv_machdep.c2
-rw-r--r--sys/arm/mv/orion/db88f5xxx.c3
-rw-r--r--sys/arm/rockchip/rk30xx_mp.c4
-rw-r--r--sys/arm/samsung/exynos/exynos5_mp.c4
-rw-r--r--sys/arm/ti/omap4/omap4_mp.c5
-rw-r--r--sys/arm/ti/omap4/pandaboard/pandaboard.c1
-rw-r--r--sys/arm/ti/ti_cpuid.c2
-rw-r--r--sys/arm/versatile/versatile_machdep.c2
-rw-r--r--sys/arm/xilinx/zy7_ehci.c17
-rw-r--r--sys/arm/xilinx/zy7_mp.c4
-rw-r--r--sys/arm/xscale/i80321/ep80219_machdep.c402
-rw-r--r--sys/arm/xscale/i80321/files.ep8021911
-rw-r--r--sys/arm/xscale/i80321/files.i8021911
-rw-r--r--sys/arm/xscale/i80321/files.i803219
-rw-r--r--sys/arm/xscale/i80321/files.iq312448
-rw-r--r--sys/arm/xscale/i80321/i80321.c250
-rw-r--r--sys/arm/xscale/i80321/i80321_aau.c292
-rw-r--r--sys/arm/xscale/i80321/i80321_dma.c351
-rw-r--r--sys/arm/xscale/i80321/i80321_intr.h165
-rw-r--r--sys/arm/xscale/i80321/i80321_mcu.c90
-rw-r--r--sys/arm/xscale/i80321/i80321_pci.c401
-rw-r--r--sys/arm/xscale/i80321/i80321_space.c209
-rw-r--r--sys/arm/xscale/i80321/iq31244_7seg.c390
-rw-r--r--sys/arm/xscale/i80321/iq31244_machdep.c416
-rw-r--r--sys/arm/xscale/i80321/iq80321.c394
-rw-r--r--sys/arm/xscale/i80321/iq80321reg.h111
-rw-r--r--sys/arm/xscale/i80321/iq80321var.h53
-rw-r--r--sys/arm/xscale/i80321/obio.c163
-rw-r--r--sys/arm/xscale/i80321/obiovar.h58
-rw-r--r--sys/arm/xscale/i80321/std.ep802197
-rw-r--r--sys/arm/xscale/i80321/std.i802195
-rw-r--r--sys/arm/xscale/i80321/std.i803215
-rw-r--r--sys/arm/xscale/i80321/std.iq312447
-rw-r--r--sys/arm/xscale/i80321/uart_bus_i80321.c76
-rw-r--r--sys/arm/xscale/i8134x/crb_machdep.c6
-rw-r--r--sys/arm/xscale/i8134x/files.i813424
-rw-r--r--sys/arm/xscale/i8134x/i80321_timer.c (renamed from sys/arm/xscale/i80321/i80321_timer.c)4
-rw-r--r--sys/arm/xscale/i8134x/i80321_wdog.c (renamed from sys/arm/xscale/i80321/i80321_wdog.c)4
-rw-r--r--sys/arm/xscale/i8134x/i80321reg.h (renamed from sys/arm/xscale/i80321/i80321reg.h)92
-rw-r--r--sys/arm/xscale/i8134x/i80321var.h (renamed from sys/arm/xscale/i80321/i80321var.h)0
-rw-r--r--sys/arm/xscale/ixp425/avila_machdep.c4
-rw-r--r--sys/arm/xscale/pxa/pxa_machdep.c4
-rw-r--r--sys/arm64/arm64/copystr.c2
-rw-r--r--sys/arm64/arm64/db_disasm.c31
-rw-r--r--sys/arm64/arm64/disassem.c330
-rw-r--r--sys/arm64/arm64/genassym.c2
-rw-r--r--sys/arm64/arm64/gic_fdt.c7
-rw-r--r--sys/arm64/arm64/intr_machdep.c3
-rw-r--r--sys/arm64/arm64/locore.S8
-rw-r--r--sys/arm64/arm64/machdep.c6
-rw-r--r--sys/arm64/arm64/mp_machdep.c3
-rw-r--r--sys/arm64/arm64/pmap.c5
-rw-r--r--sys/arm64/arm64/swtch.S44
-rw-r--r--sys/arm64/arm64/trap.c19
-rw-r--r--sys/arm64/arm64/uma_machdep.c1
-rw-r--r--sys/arm64/arm64/vm_machdep.c1
-rw-r--r--sys/arm64/cavium/thunder_pcie.c186
-rw-r--r--sys/arm64/cavium/thunder_pcie_common.c5
-rw-r--r--sys/arm64/cavium/thunder_pcie_common.h19
-rw-r--r--sys/arm64/cavium/thunder_pcie_fdt.c382
-rw-r--r--sys/arm64/include/armreg.h3
-rw-r--r--sys/arm64/include/disassem.h42
-rw-r--r--sys/arm64/include/kdb.h2
-rw-r--r--sys/arm64/include/pcb.h4
-rw-r--r--sys/arm64/include/pmap.h2
-rw-r--r--sys/boot/efi/boot1/boot1.c560
-rw-r--r--sys/boot/efi/boot1/boot_module.h13
-rw-r--r--sys/boot/efi/boot1/ufs_module.c53
-rw-r--r--sys/boot/efi/boot1/zfs_module.c59
-rw-r--r--sys/boot/efi/include/efidevp.h13
-rw-r--r--sys/boot/efi/libefi/efinet.c30
-rw-r--r--sys/boot/fdt/dts/riscv/spike.dts92
-rw-r--r--sys/boot/ficl/riscv/sysdep.c99
-rw-r--r--sys/boot/ficl/riscv/sysdep.h411
-rw-r--r--sys/cam/ata/ata_all.c60
-rw-r--r--sys/cam/scsi/scsi_pass.c3
-rw-r--r--sys/cam/scsi/scsi_sa.c4
-rw-r--r--sys/cddl/compat/opensolaris/sys/atomic.h2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c58
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c36
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/sys/isa_defs.h42
-rw-r--r--sys/cddl/dev/fbt/arm/fbt_isa.c2
-rw-r--r--sys/compat/cloudabi/cloudabi_proc.c8
-rw-r--r--sys/compat/linux/linux_fork.c20
-rw-r--r--sys/conf/Makefile.arm1
-rw-r--r--sys/conf/Makefile.riscv49
-rw-r--r--sys/conf/NOTES8
-rw-r--r--sys/conf/files.arm12
-rw-r--r--sys/conf/files.arm645
-rw-r--r--sys/conf/files.riscv44
-rw-r--r--sys/conf/kern.mk4
-rw-r--r--sys/conf/kern.post.mk5
-rw-r--r--sys/conf/kern.pre.mk9
-rw-r--r--sys/conf/ldscript.riscv136
-rw-r--r--sys/conf/options1
-rw-r--r--sys/conf/options.arm3
-rw-r--r--sys/conf/options.mips10
-rw-r--r--sys/conf/options.riscv4
-rw-r--r--sys/contrib/ipfilter/netinet/ip_compat.h1
-rw-r--r--sys/contrib/ipfilter/netinet/ip_fil_freebsd.c1
-rw-r--r--sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c5
-rw-r--r--sys/dev/ata/ata-all.c100
-rw-r--r--sys/dev/bwn/if_bwn.c3
-rw-r--r--sys/dev/cfi/cfi_core.c15
-rw-r--r--sys/dev/cxgb/cxgb_sge.c2
-rw-r--r--sys/dev/e1000/e1000_80003es2lan.c33
-rw-r--r--sys/dev/e1000/e1000_82540.c10
-rw-r--r--sys/dev/e1000/e1000_82541.c7
-rw-r--r--sys/dev/e1000/e1000_82542.c4
-rw-r--r--sys/dev/e1000/e1000_82543.c4
-rw-r--r--sys/dev/e1000/e1000_82571.h5
-rw-r--r--sys/dev/e1000/e1000_82575.c169
-rw-r--r--sys/dev/e1000/e1000_82575.h5
-rw-r--r--sys/dev/e1000/e1000_api.c8
-rw-r--r--sys/dev/e1000/e1000_defines.h11
-rw-r--r--sys/dev/e1000/e1000_hw.h8
-rw-r--r--sys/dev/e1000/e1000_i210.c30
-rw-r--r--sys/dev/e1000/e1000_ich8lan.c938
-rw-r--r--sys/dev/e1000/e1000_ich8lan.h32
-rw-r--r--sys/dev/e1000/e1000_mac.h2
-rw-r--r--sys/dev/e1000/e1000_mbx.c36
-rw-r--r--sys/dev/e1000/e1000_nvm.h2
-rw-r--r--sys/dev/e1000/e1000_osdep.h25
-rw-r--r--sys/dev/e1000/e1000_phy.c10
-rw-r--r--sys/dev/e1000/e1000_regs.h9
-rw-r--r--sys/dev/e1000/if_em.c177
-rw-r--r--sys/dev/e1000/if_em.h3
-rw-r--r--sys/dev/e1000/if_igb.c14
-rw-r--r--sys/dev/ed/if_ed.c3
-rw-r--r--sys/dev/ep/if_ep.c1
-rw-r--r--sys/dev/fe/if_fe.c1
-rw-r--r--sys/dev/filemon/filemon.c8
-rw-r--r--sys/dev/filemon/filemon_wrapper.c160
-rw-r--r--sys/dev/fxp/if_fxp.c1
-rw-r--r--sys/dev/hwpmc/hwpmc_riscv.h51
-rw-r--r--sys/dev/hyperv/include/hyperv.h33
-rw-r--r--sys/dev/hyperv/netvsc/hv_net_vsc.c48
-rw-r--r--sys/dev/hyperv/netvsc/hv_net_vsc.h10
-rw-r--r--sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c693
-rw-r--r--sys/dev/hyperv/netvsc/hv_rndis_filter.c24
-rw-r--r--sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c13
-rw-r--r--sys/dev/hyperv/utilities/hv_kvp.c35
-rw-r--r--sys/dev/hyperv/utilities/hv_util.c58
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel.c4
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel_mgmt.c231
-rw-r--r--sys/dev/hyperv/vmbus/hv_connection.c79
-rw-r--r--sys/dev/hyperv/vmbus/hv_hv.c6
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c36
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_priv.h9
-rw-r--r--sys/dev/iicbus/iic.c3
-rw-r--r--sys/dev/iscsi_initiator/isc_cam.c1
-rw-r--r--sys/dev/iscsi_initiator/isc_sm.c1
-rw-r--r--sys/dev/iscsi_initiator/isc_soc.c1
-rw-r--r--sys/dev/iscsi_initiator/isc_subr.c1
-rw-r--r--sys/dev/iscsi_initiator/iscsi_subr.c1
-rw-r--r--sys/dev/ixgbe/if_ix.c30
-rw-r--r--sys/dev/ixgbe/ixgbe_common.c5
-rw-r--r--sys/dev/ixgbe/ixgbe_phy.c3
-rw-r--r--sys/dev/ixgbe/ixgbe_type.h3
-rw-r--r--sys/dev/ixgbe/ixgbe_x540.c3
-rw-r--r--sys/dev/ixgbe/ixgbe_x550.c19
-rw-r--r--sys/dev/ixl/if_ixl.c6
-rw-r--r--sys/dev/le/lance.c1
-rw-r--r--sys/dev/malo/if_malo.c1
-rw-r--r--sys/dev/md/md.c14
-rw-r--r--sys/dev/mps/mps.c8
-rw-r--r--sys/dev/mps/mps_mapping.c63
-rw-r--r--sys/dev/mps/mps_sas.c2
-rw-r--r--sys/dev/mps/mpsvar.h2
-rw-r--r--sys/dev/netmap/netmap_offloadings.c1
-rw-r--r--sys/dev/nvd/nvd.c18
-rw-r--r--sys/dev/nvme/nvme.h30
-rw-r--r--sys/dev/oce/oce_if.h1
-rw-r--r--sys/dev/otus/if_otus.c1
-rw-r--r--sys/dev/sfxge/sfxge.h2
-rw-r--r--sys/dev/sfxge/sfxge_rx.c33
-rw-r--r--sys/dev/sfxge/sfxge_tx.c3
-rw-r--r--sys/dev/sn/if_sn.c1
-rw-r--r--sys/dev/tx/if_tx.c1
-rw-r--r--sys/dev/usb/controller/ehci.c64
-rw-r--r--sys/dev/usb/controller/ehci.h9
-rw-r--r--sys/dev/usb/controller/ehci_ixp4xx.c30
-rw-r--r--sys/dev/usb/controller/ehci_mv.c18
-rw-r--r--sys/dev/usb/controller/ehcireg.h26
-rw-r--r--sys/dev/usb/wlan/if_rsu.c1
-rw-r--r--sys/dev/vnic/mrml_bridge.c280
-rw-r--r--sys/dev/vnic/thunder_bgx.c2
-rw-r--r--sys/dev/vnic/thunder_bgx_fdt.c150
-rw-r--r--sys/dev/vnic/thunder_bgx_var.h2
-rw-r--r--sys/dev/vnic/thunder_mdio_fdt.c204
-rw-r--r--sys/dev/vnic/thunder_mdio_var.h1
-rw-r--r--sys/dev/wi/if_wi.c1
-rw-r--r--sys/dev/wi/if_wi_pci.c1
-rw-r--r--sys/dev/xe/if_xe.c1
-rw-r--r--sys/dev/xl/if_xl.c3
-rw-r--r--sys/fs/ext2fs/ext2_inode_cnv.c12
-rw-r--r--sys/kern/imgact_elf.c21
-rw-r--r--sys/kern/init_main.c7
-rw-r--r--sys/kern/kern_event.c61
-rw-r--r--sys/kern/kern_fork.c184
-rw-r--r--sys/kern/kern_kthread.c8
-rw-r--r--sys/kern/kern_ktr.c2
-rw-r--r--sys/kern/kern_malloc.c1
-rw-r--r--sys/kern/kern_mbuf.c93
-rw-r--r--sys/kern/kern_racct.c3
-rw-r--r--sys/kern/subr_mchain.c1
-rw-r--r--sys/kern/uipc_debug.c6
-rw-r--r--sys/kern/uipc_sockbuf.c1
-rw-r--r--sys/kern/uipc_socket.c10
-rw-r--r--sys/kern/vfs_aio.c644
-rw-r--r--sys/kern/vfs_mount.c34
-rw-r--r--sys/kgssapi/krb5/kcrypto_aes.c58
-rw-r--r--sys/mips/atheros/ar71xx_ehci.c21
-rw-r--r--sys/mips/conf/AR933X_BASE2
-rw-r--r--sys/mips/conf/AR934X_BASE2
-rw-r--r--sys/mips/conf/QCA955X_BASE2
-rw-r--r--sys/mips/include/asm.h2
-rw-r--r--sys/mips/include/cpufunc.h2
-rw-r--r--sys/mips/include/cpuregs.h34
-rw-r--r--sys/mips/mips/uma_machdep.c1
-rw-r--r--sys/mips/mips/vm_machdep.c1
-rw-r--r--sys/mips/rt305x/std.rt305x2
-rw-r--r--sys/modules/filemon/Makefile2
-rw-r--r--sys/net/bridgestp.c1
-rw-r--r--sys/net/if_epair.c1
-rw-r--r--sys/net/if_mib.c1
-rw-r--r--sys/net/netisr.c1
-rw-r--r--sys/net/pfvar.h2
-rw-r--r--sys/net80211/ieee80211.c1
-rw-r--r--sys/net80211/ieee80211_acl.c1
-rw-r--r--sys/net80211/ieee80211_action.c1
-rw-r--r--sys/net80211/ieee80211_ageq.c1
-rw-r--r--sys/net80211/ieee80211_amrr.c1
-rw-r--r--sys/net80211/ieee80211_crypto_none.c1
-rw-r--r--sys/net80211/ieee80211_ddb.c1
-rw-r--r--sys/net80211/ieee80211_freebsd.c3
-rw-r--r--sys/net80211/ieee80211_ht.c1
-rw-r--r--sys/net80211/ieee80211_ioctl.c1
-rw-r--r--sys/net80211/ieee80211_output.c3
-rw-r--r--sys/net80211/ieee80211_power.c1
-rw-r--r--sys/net80211/ieee80211_proto.c3
-rw-r--r--sys/net80211/ieee80211_scan.c1
-rw-r--r--sys/net80211/ieee80211_scan_sta.c1
-rw-r--r--sys/net80211/ieee80211_scan_sw.c1
-rw-r--r--sys/net80211/ieee80211_xauth.c1
-rw-r--r--sys/netgraph/netflow/netflow.c1
-rw-r--r--sys/netgraph/netflow/netflow_v9.c2
-rw-r--r--sys/netgraph/netflow/ng_netflow.c2
-rw-r--r--sys/netgraph/ng_base.c1
-rw-r--r--sys/netinet/in_proto.c1
-rw-r--r--sys/netinet/sctp_input.c47
-rw-r--r--sys/netinet/sctp_output.c139
-rw-r--r--sys/netinet/sctp_output.h3
-rw-r--r--sys/netinet/sctp_pcb.c17
-rw-r--r--sys/netinet/sctp_sysctl.c4
-rw-r--r--sys/netinet/sctp_uio.h10
-rw-r--r--sys/netinet/sctp_var.h2
-rw-r--r--sys/netinet/tcp_lro.c3
-rw-r--r--sys/netinet/toecore.c1
-rw-r--r--sys/netinet6/in6_proto.c1
-rw-r--r--sys/netinet6/send.c1
-rw-r--r--sys/netipsec/ipsec_mbuf.c1
-rw-r--r--sys/netipsec/key_debug.c2
-rw-r--r--sys/netpfil/ipfw/ip_fw_log.c3
-rw-r--r--sys/powerpc/fpu/fpu_emu.c44
-rw-r--r--sys/powerpc/fpu/fpu_emu.h2
-rw-r--r--sys/powerpc/fpu/fpu_explode.c6
-rw-r--r--sys/powerpc/fpu/fpu_extern.h4
-rw-r--r--sys/powerpc/include/reg.h6
-rw-r--r--sys/powerpc/mpc85xx/lbc.c3
-rw-r--r--sys/powerpc/powerpc/exec_machdep.c24
-rw-r--r--sys/powerpc/powerpc/nexus.c8
-rw-r--r--sys/powerpc/powerpc/sigcode32.S4
-rw-r--r--sys/powerpc/powerpc/uma_machdep.c1
-rw-r--r--sys/powerpc/ps3/ehci_ps3.c13
-rw-r--r--sys/riscv/conf/DEFAULTS13
-rw-r--r--sys/riscv/conf/GENERIC104
-rw-r--r--sys/riscv/htif/htif.c284
-rw-r--r--sys/riscv/htif/htif.h93
-rw-r--r--sys/riscv/htif/htif_block.c289
-rw-r--r--sys/riscv/htif/htif_console.c361
-rw-r--r--sys/riscv/include/asm.h4
-rw-r--r--sys/riscv/include/pcpu.h7
-rw-r--r--sys/riscv/riscv/autoconf.c94
-rw-r--r--sys/riscv/riscv/bcopy.c139
-rw-r--r--sys/riscv/riscv/bus_machdep.c144
-rw-r--r--sys/riscv/riscv/busdma_machdep.c102
-rw-r--r--sys/riscv/riscv/clock.c46
-rw-r--r--sys/riscv/riscv/copyinout.S137
-rw-r--r--sys/riscv/riscv/copystr.c59
-rw-r--r--sys/riscv/riscv/cpufunc_asm.S101
-rw-r--r--sys/riscv/riscv/devmap.c61
-rw-r--r--sys/riscv/riscv/dump_machdep.c57
-rw-r--r--sys/riscv/riscv/elf_machdep.c169
-rw-r--r--sys/riscv/riscv/exception.S461
-rw-r--r--sys/riscv/riscv/genassym.c99
-rw-r--r--sys/riscv/riscv/identcpu.c149
-rw-r--r--sys/riscv/riscv/in_cksum.c241
-rw-r--r--sys/riscv/riscv/intr_machdep.c223
-rw-r--r--sys/riscv/riscv/locore.S274
-rw-r--r--sys/riscv/riscv/machdep.c794
-rw-r--r--sys/riscv/riscv/mem.c124
-rw-r--r--sys/riscv/riscv/minidump_machdep.c (renamed from sys/arm/xscale/i80321/uart_cpu_i80321.c)52
-rw-r--r--sys/riscv/riscv/nexus.c387
-rw-r--r--sys/riscv/riscv/pmap.c3197
-rw-r--r--sys/riscv/riscv/support.S295
-rw-r--r--sys/riscv/riscv/swtch.S271
-rw-r--r--sys/riscv/riscv/sys_machdep.c49
-rw-r--r--sys/riscv/riscv/timer.c298
-rw-r--r--sys/riscv/riscv/trap.c311
-rw-r--r--sys/riscv/riscv/uio_machdep.c134
-rw-r--r--sys/riscv/riscv/uma_machdep.c56
-rw-r--r--sys/riscv/riscv/vm_machdep.c260
-rw-r--r--sys/rpc/replay.c1
-rw-r--r--sys/sparc64/sparc64/vm_machdep.c1
-rw-r--r--sys/sys/ata.h3
-rw-r--r--sys/sys/cdefs.h2
-rw-r--r--sys/sys/event.h3
-rw-r--r--sys/sys/kerneldump.h1
-rw-r--r--sys/sys/proc.h13
-rw-r--r--sys/sys/socket.h15
-rw-r--r--sys/sys/socketvar.h14
-rw-r--r--sys/tools/embed_mfs.sh20
-rw-r--r--sys/ufs/ffs/ffs_extern.h1
-rw-r--r--sys/vm/memguard.c1
-rw-r--r--sys/vm/sg_pager.c3
-rw-r--r--sys/vm/uma.h2
-rw-r--r--sys/vm/uma_core.c112
-rw-r--r--sys/vm/uma_dbg.c98
-rw-r--r--sys/vm/uma_dbg.h3
-rw-r--r--sys/vm/uma_int.h2
-rw-r--r--sys/vm/vm_page.c1
-rw-r--r--tests/sys/acl/Makefile8
-rw-r--r--tests/sys/geom/class/gate/1_test.sh6
-rw-r--r--tests/sys/kqueue/common.h1
-rw-r--r--tests/sys/kqueue/main.c75
-rw-r--r--tests/sys/kqueue/proc.c168
-rwxr-xr-xtools/tools/nanobsd/defaults.sh12
-rw-r--r--tools/tools/nanobsd/embedded/README2
-rw-r--r--tools/tools/nanobsd/embedded/common61
-rw-r--r--tools/tools/nanobsd/embedded/qemu-amd64-uefi-bios.cfg43
-rw-r--r--tools/tools/nanobsd/embedded/qemu-amd64-uefi.cfg43
-rw-r--r--usr.bin/kdump/kdump.c10
-rw-r--r--usr.bin/netstat/inet.c6
-rw-r--r--usr.bin/netstat/sctp.c5
-rw-r--r--usr.bin/netstat/unix.c8
-rw-r--r--usr.bin/truss/aarch64-cloudabi64.c2
-rw-r--r--usr.bin/truss/aarch64-freebsd.c2
-rw-r--r--usr.bin/truss/amd64-cloudabi64.c2
-rw-r--r--usr.bin/truss/amd64-freebsd.c2
-rw-r--r--usr.bin/truss/amd64-freebsd32.c4
-rw-r--r--usr.bin/truss/amd64-linux32.c2
-rw-r--r--usr.bin/truss/arm-freebsd.c2
-rw-r--r--usr.bin/truss/i386-freebsd.c4
-rw-r--r--usr.bin/truss/i386-linux.c2
-rw-r--r--usr.bin/truss/mips-freebsd.c2
-rw-r--r--usr.bin/truss/powerpc-freebsd.c2
-rw-r--r--usr.bin/truss/powerpc64-freebsd.c2
-rw-r--r--usr.bin/truss/powerpc64-freebsd32.c2
-rw-r--r--usr.bin/truss/sparc64-freebsd.c2
-rwxr-xr-xusr.sbin/bsdconfig/bsdconfig4
-rw-r--r--usr.sbin/bsdconfig/networking/share/media.subr12
-rw-r--r--usr.sbin/bsdconfig/networking/share/resolv.subr2
-rw-r--r--usr.sbin/bsdconfig/share/common.subr9
-rw-r--r--usr.sbin/bsdconfig/share/device.subr4
-rw-r--r--usr.sbin/bsdconfig/share/strings.subr467
-rwxr-xr-xusr.sbin/bsdinstall/scripts/zfsboot115
-rw-r--r--usr.sbin/ctld/Makefile7
-rw-r--r--usr.sbin/ctld/ctld.c112
-rw-r--r--usr.sbin/ctld/ctld.h4
-rw-r--r--usr.sbin/ctld/parse.y93
-rw-r--r--usr.sbin/ctld/uclparse.c900
-rw-r--r--usr.sbin/devctl/devctl.84
-rw-r--r--usr.sbin/freebsd-update/freebsd-update.sh2
-rw-r--r--usr.sbin/sysrc/sysrc10
-rw-r--r--usr.sbin/sysrc/sysrc.816
1021 files changed, 28215 insertions, 21440 deletions
diff --git a/Makefile b/Makefile
index acb061bf8a74..988d9cc683d8 100644
--- a/Makefile
+++ b/Makefile
@@ -136,6 +136,7 @@ TGTS+= ${BITGTS}
.ORDER: buildworld installworld
.ORDER: buildworld distributeworld
.ORDER: buildworld buildkernel
+.ORDER: installworld distribution
.ORDER: buildkernel installkernel
.ORDER: buildkernel installkernel.debug
.ORDER: buildkernel reinstallkernel
@@ -328,7 +329,7 @@ bmake: .PHONY
${MMAKE} all; \
${MMAKE} install DESTDIR=${MYMAKE:H} BINDIR=
-tinderbox toolchains kernel-toolchains: upgrade_checks
+tinderbox toolchains kernel-toolchains kernels worlds: upgrade_checks
tinderbox:
@cd ${.CURDIR}; ${SUB_MAKE} DOING_TINDERBOX=YES universe
@@ -339,6 +340,12 @@ toolchains:
kernel-toolchains:
@cd ${.CURDIR}; ${SUB_MAKE} UNIVERSE_TARGET=kernel-toolchain universe
+kernels:
+ @cd ${.CURDIR}; ${SUB_MAKE} UNIVERSE_TARGET=buildkernel universe
+
+worlds:
+ @cd ${.CURDIR}; ${SUB_MAKE} UNIVERSE_TARGET=buildworld universe
+
#
# universe
#
diff --git a/Makefile.inc1 b/Makefile.inc1
index ad3e0fe24072..87de0621acb6 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -72,7 +72,7 @@ SRCDIR?= ${.CURDIR}
SUBDIR= ${SUBDIR_OVERRIDE}
.else
SUBDIR= lib libexec
-.if make(install*)
+.if !defined(NO_ROOT) && (make(installworld) || make(install))
# Ensure libraries are installed before progressing.
SUBDIR+=.WAIT
.endif
@@ -127,7 +127,7 @@ SUBDIR+= ${_DIR}
# by calling 'makedb' in share/man. This is only relevant for
# install/distribute so they build the whatis file after every manpage is
# installed.
-.if make(install*)
+.if make(installworld) || make(install)
SUBDIR+=.WAIT
.endif
SUBDIR+=etc
@@ -1083,16 +1083,14 @@ redistribute: .MAKE .PHONY
DISTRIBUTION=lib32
.endif
-distrib-dirs: .MAKE .PHONY
- ${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \
- ${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET}
-
-distribution: .MAKE .PHONY
+distrib-dirs distribution: .MAKE .PHONY
${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \
${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET}
+.if make(distribution)
${_+_}cd ${.CURDIR}; ${CROSSENV} PATH=${TMPPATH} \
${MAKE} -f Makefile.inc1 ${IMAKE_INSTALL} \
METALOG=${METALOG} installconfig
+.endif
#
# buildkernel and installkernel
diff --git a/UPDATING b/UPDATING
index 1b98e40cbaf2..123c05ae975e 100644
--- a/UPDATING
+++ b/UPDATING
@@ -31,6 +31,13 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
+20160129:
+ Building ZFS pools on top of zvols is prohibited by default. That
+ feature has never worked safely; it's always been prone to deadlocks.
+ Using a zvol as the backing store for a VM guest's virtual disk will
+ still work, even if the guest is using ZFS. Legacy behavior can be
+ restored by setting vfs.zfs.vol.recursive=1.
+
20160119:
The NONE and HPN patches has been removed from OpenSSH. They are
still available in the security/openssh-portable port.
diff --git a/bin/csh/Makefile b/bin/csh/Makefile
index 51ef3dd9c306..deb63478727d 100644
--- a/bin/csh/Makefile
+++ b/bin/csh/Makefile
@@ -51,41 +51,40 @@ FILESDIR= ${SHAREDIR}/examples/tcsh
FILES= complete.tcsh csh-mode.el
.endif
-CATALOGS= et:et_EE.ISO8859-15 \
- finnish:fi_FI.ISO8859-1 \
- french:fr_FR.ISO8859-1 \
- german:de_DE.ISO8859-1 \
- greek:el_GR.ISO8859-7 \
- italian:it_IT.ISO8859-1 \
- ja:ja_JP.eucJP \
- russian:ru_RU.KOI8-R \
- spanish:es_ES.ISO8859-1 \
- ukrainian:uk_UA.KOI8-U
-
-NLSLINKS_fi_FI.ISO8859-1= fi_FI.ISO8859-15
-NLSLINKS_fr_FR.ISO8859-1= fr_BE.ISO8859-1 fr_BE.ISO8859-15 \
- fr_CA.ISO8859-1 fr_CA.ISO8859-15 fr_CH.ISO8859-1 \
- fr_CH.ISO8859-15 fr_FR.ISO8859-15
-NLSLINKS_de_DE.ISO8859-1= de_AT.ISO8859-1 de_AT.ISO8859-15 de_CH.ISO8859-1 \
- de_CH.ISO8859-15 de_DE.ISO8859-15
-NLSLINKS_it_IT.ISO8859-1= it_CH.ISO8859-1 it_CH.ISO8859-15 it_IT.ISO8859-15
-NLSLINKS_es_ES.ISO8859-1= es_ES.ISO8859-15
+CATALOGS= et:et_EE.UTF-8 \
+ finnish:fi_FI.UTF-8 \
+ french:fr_FR.UTF-8 \
+ german:de_DE.UTF-8 \
+ greek:el_GR.UTF-8 \
+ italian:it_IT.UTF-8 \
+ ja:ja_JP.UTF-8 \
+ russian:ru_RU.UTF-8 \
+ spanish:es_ES.UTF-8 \
+ ukrainian:uk_UA.UTF-8
+
+NLSLINKS_de_DE.UTF-8 = de_AT.UTF-8 de_CH.UTF-8
+NLSLINKS_fr_FR.UTF-8 = fr_BE.UTF-8 fr_CA.UTF-8 fr_CH.UTF-8
+NLSLINKS_it_IT.UTF-8 = it_CH.UTF-8
.if ${MK_NLS_CATALOGS} == "no" || defined(RESCUE)
CFLAGS+= -DNO_NLS_CATALOGS
.else
CFLAGS+= -DHAVE_ICONV
.if ${MK_ICONV} != "no"
-NLSLINKS_de_DE.ISO8859-1 += de_AT.UTF-8 de_CH.UTF-8 de_DE.UTF-8
-NLSLINKS_el_GR.ISO8859-7 = el_GR.UTF-8
-NLSLINKS_es_ES.ISO8859-1 += es_ES.UTF-8
-NLSLINKS_et_EE.ISO8859-15 = et_EE.UTF-8
-NLSLINKS_fi_FI.ISO8859-1 += fi_FI.UTF-8
-NLSLINKS_fr_FR.ISO8859-1 += fr_BE.UTF-8 fr_CA.UTF-8 fr_CH.UTF-8 fr_FR.UTF-8
-NLSLINKS_it_IT.ISO8859-1 += it_CH.UTF-8 it_IT.UTF-8
-NLSLINKS_ja_JP.eucJP = ja_JP.SJIS ja_JP.UTF-8
-NLSLINKS_ru_RU.KOI8-R = ru_RU.CP1251 ru_RU.CP866 ru_RU.ISO8859-5 ru_RU.UTF-8
-NLSLINKS_uk_UA.KOI8-U = uk_UA.ISO8859-5 uk_UA.UTF-8
+NLSLINKS_de_DE.UTF-8 += de_AT.ISO8859-1 de_AT.ISO8859-15 de_CH.ISO8859-1 \
+ de_CH.ISO8859-15 de_DE.ISO8859-1 de_DE.ISO8859-15
+NLSLINKS_el_GR.UTF-8 = el_GR.ISO8859-7
+NLSLINKS_es_ES.UTF-8 = es_ES.ISO8859-1 es_ES.ISO8859-15
+NLSLINKS_et_EE.UTF-8 = et_EE.ISO8859-15
+NLSLINKS_fi_FI.UTF-8 = fi_FI.ISO8859-1 fi_FI.ISO8859-15
+NLSLINKS_fr_FR.UTF-8 += fr_BE.ISO8859-1 fr_BE.ISO8859-15 \
+ fr_CA.ISO8859-1 fr_CA.ISO8859-15 fr_CH.ISO8859-1 \
+ fr_CH.ISO8859-15 fr_FR.ISO8859-1 fr_FR.ISO8859-15
+NLSLINKS_it_IT.UTF-8 += it_CH.ISO8859-1 it_CH.ISO8859-15 it_IT.ISO8859-1 \
+ it_IT.ISO8859-15
+NLSLINKS_ja_JP.UTF-8 = ja_JP.SJIS ja_JP.eucJP
+NLSLINKS_ru_RU.UTF-8 = ru_RU.CP1251 ru_RU.CP866 ru_RU.ISO8859-5 ru_RU.KOI8-R
+NLSLINKS_uk_UA.UTF-8 = uk_UA.ISO8859-5 uk_UA.KOI8-U
.else
# Above links can be installed from ports/shells/tcsh_nls
diff --git a/bin/csh/iconv_stub.c b/bin/csh/iconv_stub.c
index d1a9e475d87e..e20608c60616 100644
--- a/bin/csh/iconv_stub.c
+++ b/bin/csh/iconv_stub.c
@@ -36,9 +36,9 @@
#undef iconv_close
#define ICONVLIB "libiconv.so"
-#define ICONV_ENGINE "iconv"
-#define ICONV_OPEN "iconv_open"
-#define ICONV_CLOSE "iconv_close"
+#define ICONV_ENGINE "libiconv"
+#define ICONV_OPEN "libiconv_open"
+#define ICONV_CLOSE "libiconv_close"
typedef iconv_t iconv_open_t(const char *, const char *);
diff --git a/bin/dd/args.c b/bin/dd/args.c
index 2f197f8da505..1cbf3b374cf1 100644
--- a/bin/dd/args.c
+++ b/bin/dd/args.c
@@ -360,6 +360,46 @@ c_conv(const void *a, const void *b)
((const struct conv *)b)->name));
}
+static uintmax_t
+postfix_to_mult(const char expr)
+{
+ uintmax_t mult;
+
+ mult = 0;
+ switch (expr) {
+ case 'B':
+ case 'b':
+ mult = 512;
+ break;
+ case 'K':
+ case 'k':
+ mult = 1 << 10;
+ break;
+ case 'M':
+ case 'm':
+ mult = 1 << 20;
+ break;
+ case 'G':
+ case 'g':
+ mult = 1 << 30;
+ break;
+ case 'T':
+ case 't':
+ mult = (uintmax_t)1 << 40;
+ break;
+ case 'P':
+ case 'p':
+ mult = (uintmax_t)1 << 50;
+ break;
+ case 'W':
+ case 'w':
+ mult = sizeof(int);
+ break;
+ }
+
+ return (mult);
+}
+
/*
* Convert an expression of the following forms to a uintmax_t.
* 1) A positive decimal number.
@@ -386,31 +426,7 @@ get_num(const char *val)
if (expr == val) /* No valid digits. */
errx(1, "%s: illegal numeric value", oper);
- mult = 0;
- switch (*expr) {
- case 'B':
- case 'b':
- mult = 512;
- break;
- case 'K':
- case 'k':
- mult = 1 << 10;
- break;
- case 'M':
- case 'm':
- mult = 1 << 20;
- break;
- case 'G':
- case 'g':
- mult = 1 << 30;
- break;
- case 'W':
- case 'w':
- mult = sizeof(int);
- break;
- default:
- ;
- }
+ mult = postfix_to_mult(*expr);
if (mult != 0) {
prevnum = num;
@@ -460,29 +476,7 @@ get_off_t(const char *val)
if (expr == val) /* No valid digits. */
errx(1, "%s: illegal numeric value", oper);
- mult = 0;
- switch (*expr) {
- case 'B':
- case 'b':
- mult = 512;
- break;
- case 'K':
- case 'k':
- mult = 1 << 10;
- break;
- case 'M':
- case 'm':
- mult = 1 << 20;
- break;
- case 'G':
- case 'g':
- mult = 1 << 30;
- break;
- case 'W':
- case 'w':
- mult = sizeof(int);
- break;
- }
+ mult = postfix_to_mult(*expr);
if (mult != 0) {
prevnum = num;
diff --git a/bin/dd/dd.1 b/bin/dd/dd.1
index 0908642dd1cf..4047cdca57f5 100644
--- a/bin/dd/dd.1
+++ b/bin/dd/dd.1
@@ -32,7 +32,7 @@
.\" @(#)dd.1 8.2 (Berkeley) 1/13/94
.\" $FreeBSD$
.\"
-.Dd August 28, 2014
+.Dd February 4, 2016
.Dt DD 1
.Os
.Sh NAME
@@ -332,10 +332,13 @@ If the number ends with a
.Dq Li k ,
.Dq Li m ,
.Dq Li g ,
+.Dq Li t ,
+.Dq Li p ,
or
.Dq Li w ,
the
-number is multiplied by 512, 1024 (1K), 1048576 (1M), 1073741824 (1G)
+number is multiplied by 512, 1024 (1K), 1048576 (1M), 1073741824 (1G),
+1099511627776 (1T), 1125899906842624 (1P)
or the number of bytes in an integer, respectively.
Two or more numbers may be separated by an
.Dq Li x
diff --git a/bin/sh/redir.c b/bin/sh/redir.c
index 95d3238daf1b..0a7aa96fb601 100644
--- a/bin/sh/redir.c
+++ b/bin/sh/redir.c
@@ -70,6 +70,7 @@ struct redirtab {
struct redirtab *next;
int renamed[10];
int fd0_redirected;
+ unsigned int empty_redirs;
};
@@ -82,6 +83,9 @@ static struct redirtab *redirlist;
*/
static int fd0_redirected = 0;
+/* Number of redirtabs that have not been allocated. */
+static unsigned int empty_redirs = 0;
+
static void openredirect(union node *, char[10 ]);
static int openhere(union node *);
@@ -115,12 +119,17 @@ redirect(union node *redir, int flags)
memory[i] = 0;
memory[1] = flags & REDIR_BACKQ;
if (flags & REDIR_PUSH) {
- sv = ckmalloc(sizeof (struct redirtab));
- for (i = 0 ; i < 10 ; i++)
- sv->renamed[i] = EMPTY;
- sv->fd0_redirected = fd0_redirected;
- sv->next = redirlist;
- redirlist = sv;
+ empty_redirs++;
+ if (redir != NULL) {
+ sv = ckmalloc(sizeof (struct redirtab));
+ for (i = 0 ; i < 10 ; i++)
+ sv->renamed[i] = EMPTY;
+ sv->fd0_redirected = fd0_redirected;
+ sv->empty_redirs = empty_redirs - 1;
+ sv->next = redirlist;
+ redirlist = sv;
+ empty_redirs = 0;
+ }
}
for (n = redir ; n ; n = n->nfile.next) {
fd = n->nfile.fd;
@@ -303,6 +312,12 @@ popredir(void)
struct redirtab *rp = redirlist;
int i;
+ INTOFF;
+ if (empty_redirs > 0) {
+ empty_redirs--;
+ INTON;
+ return;
+ }
for (i = 0 ; i < 10 ; i++) {
if (rp->renamed[i] != EMPTY) {
if (rp->renamed[i] >= 0) {
@@ -313,8 +328,8 @@ popredir(void)
}
}
}
- INTOFF;
fd0_redirected = rp->fd0_redirected;
+ empty_redirs = rp->empty_redirs;
redirlist = rp->next;
ckfree(rp);
INTON;
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 14ae89833c8a..94067792e40e 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -32,7 +32,7 @@
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
.\" $FreeBSD$
.\"
-.Dd August 29, 2015
+.Dd January 30, 2016
.Dt SH 1
.Os
.Sh NAME
@@ -1952,13 +1952,20 @@ Execute the specified built-in command,
This is useful when the user wishes to override a shell function
with the same name as a built-in command.
.It Ic cd Oo Fl L | P Oc Oo Fl e Oc Op Ar directory
+.It Ic cd Fl
Switch to the specified
.Ar directory ,
-or to the directory specified in the
+to the directory specified in the
.Va HOME
environment variable if no
.Ar directory
-is specified.
+is specified or
+to the directory specified in the
+.Va OLDPWD
+environment variable if
+.Ar directory
+is
+.Fl .
If
.Ar directory
does not begin with
@@ -1982,10 +1989,12 @@ the
.Ic cd
command will print out the name of the directory
that it actually switched to
-if this is different from the name that the user gave.
-These may be different either because the
+if the
.Va CDPATH
-mechanism was used or because a symbolic link was crossed.
+mechanism was used or if
+.Ar directory
+was
+.Fl .
.Pp
If the
.Fl P
@@ -2774,6 +2783,10 @@ Initialization file for interactive shells.
Locale settings.
These are inherited by children of the shell,
and is used in a limited manner by the shell itself.
+.It Ev OLDPWD
+The previous current directory.
+This is used and updated by
+.Ic cd .
.It Ev PWD
An absolute pathname for the current directory,
possibly containing symbolic links.
diff --git a/bin/test/test.c b/bin/test/test.c
index 46e9999eb0bb..48b718e6412d 100644
--- a/bin/test/test.c
+++ b/bin/test/test.c
@@ -120,51 +120,53 @@ enum token {
#define TOKEN_TYPE(token) ((token) & 0xff00)
-static struct t_op {
- char op_text[4];
+static const struct t_op {
+ char op_text[2];
short op_num;
-} const ops [] = {
- {"-r", FILRD},
- {"-w", FILWR},
- {"-x", FILEX},
- {"-e", FILEXIST},
- {"-f", FILREG},
- {"-d", FILDIR},
- {"-c", FILCDEV},
- {"-b", FILBDEV},
- {"-p", FILFIFO},
- {"-u", FILSUID},
- {"-g", FILSGID},
- {"-k", FILSTCK},
- {"-s", FILGZ},
- {"-t", FILTT},
- {"-z", STREZ},
- {"-n", STRNZ},
- {"-h", FILSYM}, /* for backwards compat */
- {"-O", FILUID},
- {"-G", FILGID},
- {"-L", FILSYM},
- {"-S", FILSOCK},
+} ops1[] = {
{"=", STREQ},
- {"==", STREQ},
- {"!=", STRNE},
{"<", STRLT},
{">", STRGT},
- {"-eq", INTEQ},
- {"-ne", INTNE},
- {"-ge", INTGE},
- {"-gt", INTGT},
- {"-le", INTLE},
- {"-lt", INTLT},
- {"-nt", FILNT},
- {"-ot", FILOT},
- {"-ef", FILEQ},
{"!", UNOT},
- {"-a", BAND},
- {"-o", BOR},
{"(", LPAREN},
{")", RPAREN},
- {"", 0}
+}, opsm1[] = {
+ {"r", FILRD},
+ {"w", FILWR},
+ {"x", FILEX},
+ {"e", FILEXIST},
+ {"f", FILREG},
+ {"d", FILDIR},
+ {"c", FILCDEV},
+ {"b", FILBDEV},
+ {"p", FILFIFO},
+ {"u", FILSUID},
+ {"g", FILSGID},
+ {"k", FILSTCK},
+ {"s", FILGZ},
+ {"t", FILTT},
+ {"z", STREZ},
+ {"n", STRNZ},
+ {"h", FILSYM}, /* for backwards compat */
+ {"O", FILUID},
+ {"G", FILGID},
+ {"L", FILSYM},
+ {"S", FILSOCK},
+ {"a", BAND},
+ {"o", BOR},
+}, ops2[] = {
+ {"==", STREQ},
+ {"!=", STRNE},
+}, opsm2[] = {
+ {"eq", INTEQ},
+ {"ne", INTNE},
+ {"ge", INTGE},
+ {"gt", INTGT},
+ {"le", INTLE},
+ {"lt", INTLT},
+ {"nt", FILNT},
+ {"ot", FILOT},
+ {"ef", FILEQ},
};
static int nargc;
@@ -416,35 +418,71 @@ filstat(char *nm, enum token mode)
}
}
-static enum token
-t_lex(char *s)
+static int
+find_op_1char(const struct t_op *op, const struct t_op *end, const char *s)
{
- struct t_op const *op = ops;
+ char c;
- if (s == 0) {
- return EOI;
+ c = s[0];
+ while (op != end) {
+ if (c == *op->op_text)
+ return op->op_num;
+ op++;
}
- while (*op->op_text) {
- if (strcmp(s, op->op_text) == 0) {
- if (((TOKEN_TYPE(op->op_num) == UNOP ||
- TOKEN_TYPE(op->op_num) == BUNOP)
- && isunopoperand()) ||
- (op->op_num == LPAREN && islparenoperand()) ||
- (op->op_num == RPAREN && isrparenoperand()))
- break;
+ return OPERAND;
+}
+
+static int
+find_op_2char(const struct t_op *op, const struct t_op *end, const char *s)
+{
+ while (op != end) {
+ if (s[0] == op->op_text[0] && s[1] == op->op_text[1])
return op->op_num;
- }
op++;
}
return OPERAND;
}
static int
+find_op(const char *s)
+{
+ if (s[0] == '\0')
+ return OPERAND;
+ else if (s[1] == '\0')
+ return find_op_1char(ops1, (&ops1)[1], s);
+ else if (s[2] == '\0')
+ return s[0] == '-' ? find_op_1char(opsm1, (&opsm1)[1], s + 1) :
+ find_op_2char(ops2, (&ops2)[1], s);
+ else if (s[3] == '\0')
+ return s[0] == '-' ? find_op_2char(opsm2, (&opsm2)[1], s + 1) :
+ OPERAND;
+ else
+ return OPERAND;
+}
+
+static enum token
+t_lex(char *s)
+{
+ int num;
+
+ if (s == 0) {
+ return EOI;
+ }
+ num = find_op(s);
+ if (((TOKEN_TYPE(num) == UNOP || TOKEN_TYPE(num) == BUNOP)
+ && isunopoperand()) ||
+ (num == LPAREN && islparenoperand()) ||
+ (num == RPAREN && isrparenoperand()))
+ return OPERAND;
+ return num;
+}
+
+static int
isunopoperand(void)
{
- struct t_op const *op = ops;
char *s;
char *t;
+ int num;
if (nargc == 1)
return 1;
@@ -452,20 +490,16 @@ isunopoperand(void)
if (nargc == 2)
return parenlevel == 1 && strcmp(s, ")") == 0;
t = *(t_wp + 2);
- while (*op->op_text) {
- if (strcmp(s, op->op_text) == 0)
- return TOKEN_TYPE(op->op_num) == BINOP &&
- (parenlevel == 0 || t[0] != ')' || t[1] != '\0');
- op++;
- }
- return 0;
+ num = find_op(s);
+ return TOKEN_TYPE(num) == BINOP &&
+ (parenlevel == 0 || t[0] != ')' || t[1] != '\0');
}
static int
islparenoperand(void)
{
- struct t_op const *op = ops;
char *s;
+ int num;
if (nargc == 1)
return 1;
@@ -474,12 +508,8 @@ islparenoperand(void)
return parenlevel == 1 && strcmp(s, ")") == 0;
if (nargc != 3)
return 0;
- while (*op->op_text) {
- if (strcmp(s, op->op_text) == 0)
- return TOKEN_TYPE(op->op_num) == BINOP;
- op++;
- }
- return 0;
+ num = find_op(s);
+ return TOKEN_TYPE(num) == BINOP;
}
static int
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c
index d5ba20fde0cf..c3dafd6a777c 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c
@@ -26,6 +26,7 @@
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2015 by Syneto S.R.L. All rights reserved.
*/
/*
@@ -246,8 +247,9 @@ zpool_get_features(zpool_handle_t *zhp)
config = zpool_get_config(zhp, NULL);
}
- verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS,
- &features) == 0);
+ if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS,
+ &features) != 0)
+ return (NULL);
return (features);
}
diff --git a/contrib/bsnmp/snmp_mibII/mibII.c b/contrib/bsnmp/snmp_mibII/mibII.c
index b62ee66d6d61..9079d1d3b58c 100644
--- a/contrib/bsnmp/snmp_mibII/mibII.c
+++ b/contrib/bsnmp/snmp_mibII/mibII.c
@@ -982,7 +982,7 @@ handle_rtmsg(struct rt_msghdr *rtm)
{
struct sockaddr *addrs[RTAX_MAX];
struct if_msghdr *ifm;
- struct ifa_msghdr ifam;
+ struct ifa_msghdr ifam, *ifamp;
struct ifma_msghdr *ifmam;
#ifdef RTM_IFANNOUNCE
struct if_announcemsghdr *ifan;
@@ -1002,8 +1002,9 @@ handle_rtmsg(struct rt_msghdr *rtm)
switch (rtm->rtm_type) {
case RTM_NEWADDR:
- memcpy(&ifam, rtm, sizeof(ifam));
- mib_extract_addrs(ifam.ifam_addrs, (u_char *)(&ifam + 1), addrs);
+ ifamp = (struct ifa_msghdr *)rtm;
+ memcpy(&ifam, ifamp, sizeof(ifam));
+ mib_extract_addrs(ifam.ifam_addrs, (u_char *)(ifamp + 1), addrs);
if (addrs[RTAX_IFA] == NULL || addrs[RTAX_NETMASK] == NULL)
break;
@@ -1029,8 +1030,9 @@ handle_rtmsg(struct rt_msghdr *rtm)
break;
case RTM_DELADDR:
- memcpy(&ifam, rtm, sizeof(ifam));
- mib_extract_addrs(ifam.ifam_addrs, (u_char *)(&ifam + 1), addrs);
+ ifamp = (struct ifa_msghdr *)rtm;
+ memcpy(&ifam, ifamp, sizeof(ifam));
+ mib_extract_addrs(ifam.ifam_addrs, (u_char *)(ifamp + 1), addrs);
if (addrs[RTAX_IFA] == NULL)
break;
diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c
index 6902024725af..a0170234fb07 100644
--- a/contrib/elftoolchain/readelf/readelf.c
+++ b/contrib/elftoolchain/readelf/readelf.c
@@ -1053,8 +1053,9 @@ static struct {
static const char *
r_type(unsigned int mach, unsigned int type)
{
+ static char s_type[32];
+
switch(mach) {
- case EM_NONE: return "";
case EM_386:
case EM_IAMCU:
switch(type) {
@@ -1089,8 +1090,8 @@ r_type(unsigned int mach, unsigned int type)
case 35: return "R_386_TLS_DTPMOD32";
case 36: return "R_386_TLS_DTPOFF32";
case 37: return "R_386_TLS_TPOFF32";
- default: return "";
}
+ break;
case EM_AARCH64:
switch(type) {
case 0: return "R_AARCH64_NONE";
@@ -1145,6 +1146,16 @@ r_type(unsigned int mach, unsigned int type)
case 311: return "R_AARCH64_ADR_GOT_PAGE";
case 312: return "R_AARCH64_LD64_GOT_LO12_NC";
case 313: return "R_AARCH64_LD64_GOTPAGE_LO15";
+ case 560: return "R_AARCH64_TLSDESC_LD_PREL19";
+ case 561: return "R_AARCH64_TLSDESC_ADR_PREL21";
+ case 562: return "R_AARCH64_TLSDESC_ADR_PAGE21";
+ case 563: return "R_AARCH64_TLSDESC_LD64_LO12";
+ case 564: return "R_AARCH64_TLSDESC_ADD_LO12";
+ case 565: return "R_AARCH64_TLSDESC_OFF_G1";
+ case 566: return "R_AARCH64_TLSDESC_OFF_G0_NC";
+ case 567: return "R_AARCH64_TLSDESC_LDR";
+ case 568: return "R_AARCH64_TLSDESC_ADD";
+ case 569: return "R_AARCH64_TLSDESC_CALL";
case 1024: return "R_AARCH64_COPY";
case 1025: return "R_AARCH64_GLOB_DAT";
case 1026: return "R_AARCH64_JUMP_SLOT";
@@ -1154,8 +1165,8 @@ r_type(unsigned int mach, unsigned int type)
case 1030: return "R_AARCH64_TLS_TPREL64";
case 1031: return "R_AARCH64_TLSDESC";
case 1032: return "R_AARCH64_IRELATIVE";
- default: return "";
}
+ break;
case EM_ARM:
switch(type) {
case 0: return "R_ARM_NONE";
@@ -1206,8 +1217,8 @@ r_type(unsigned int mach, unsigned int type)
case 253: return "R_ARM_RABS32";
case 254: return "R_ARM_RPC24";
case 255: return "R_ARM_RBASE";
- default: return "";
}
+ break;
case EM_IA_64:
switch(type) {
case 0: return "R_IA_64_NONE";
@@ -1290,8 +1301,8 @@ r_type(unsigned int mach, unsigned int type)
case 182: return "R_IA_64_DTPREL64MSB";
case 183: return "R_IA_64_DTPREL64LSB";
case 186: return "R_IA_64_LTOFF_DTPREL22";
- default: return "";
}
+ break;
case EM_MIPS:
switch(type) {
case 0: return "R_MIPS_NONE";
@@ -1324,9 +1335,8 @@ r_type(unsigned int mach, unsigned int type)
case 48: return "R_MIPS_TLS_TPREL64";
case 49: return "R_MIPS_TLS_TPREL_HI16";
case 50: return "R_MIPS_TLS_TPREL_LO16";
-
- default: return "";
}
+ break;
case EM_PPC:
switch(type) {
case 0: return "R_PPC_NONE";
@@ -1406,8 +1416,8 @@ r_type(unsigned int mach, unsigned int type)
case 114: return "R_PPC_EMB_RELST_HA";
case 115: return "R_PPC_EMB_BIT_FLD";
case 116: return "R_PPC_EMB_RELSDA";
- default: return "";
}
+ break;
case EM_RISCV:
switch(type) {
case 0: return "R_RISCV_NONE";
@@ -1453,6 +1463,7 @@ r_type(unsigned int mach, unsigned int type)
case 44: return "R_RISCV_RVC_BRANCH";
case 45: return "R_RISCV_RVC_JUMP";
}
+ break;
case EM_SPARC:
case EM_SPARCV9:
switch(type) {
@@ -1536,8 +1547,8 @@ r_type(unsigned int mach, unsigned int type)
case 77: return "R_SPARC_TLS_DTPOFF64";
case 78: return "R_SPARC_TLS_TPOFF32";
case 79: return "R_SPARC_TLS_TPOFF64";
- default: return "";
}
+ break;
case EM_X86_64:
switch(type) {
case 0: return "R_X86_64_NONE";
@@ -1578,10 +1589,12 @@ r_type(unsigned int mach, unsigned int type)
case 35: return "R_X86_64_TLSDESC_CALL";
case 36: return "R_X86_64_TLSDESC";
case 37: return "R_X86_64_IRELATIVE";
- default: return "";
}
- default: return "";
+ break;
}
+
+ snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type);
+ return (s_type);
}
static const char *
diff --git a/contrib/libucl/tests/.gitignore b/contrib/libucl/tests/.gitignore
deleted file mode 100644
index 5a48681d39b2..000000000000
--- a/contrib/libucl/tests/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-*.log
-*.trs
-*.plist
-
-test_basic
-test_generate
-test_schema
-test_speed
diff --git a/contrib/libxo/.gitignore b/contrib/libxo/.gitignore
deleted file mode 100644
index 8d70b6cc1550..000000000000
--- a/contrib/libxo/.gitignore
+++ /dev/null
@@ -1,46 +0,0 @@
-# Object files
-*.o
-
-# Libraries
-*.lib
-*.a
-
-# Shared objects (inc. Windows DLLs)
-*.dll
-*.so
-*.so.*
-*.dylib
-
-# Executables
-*.exe
-*.app
-
-*~
-*.orig
-
-aclocal.m4
-ar-lib
-autom4te.cache
-build
-compile
-config.guess
-config.h.in
-config.sub
-depcomp
-install-sh
-ltmain.sh
-missing
-m4
-
-Makefile.in
-configure
-.DS_Store
-
-xoconfig.h.in
-xo_config.h.in
-
-.gdbinit
-.gdbinit.local
-xtest
-xtest.dSYM
-tests/w
diff --git a/contrib/ofed/librdmacm/examples/build/cmatose/Makefile b/contrib/ofed/librdmacm/examples/build/cmatose/Makefile
index 31d2ae7f7f6b..e2baf40bcf2c 100644
--- a/contrib/ofed/librdmacm/examples/build/cmatose/Makefile
+++ b/contrib/ofed/librdmacm/examples/build/cmatose/Makefile
@@ -5,7 +5,6 @@
PROG= cmatose
MAN=
SRCS= cmatose.c
-LDADD+= -libverbs -lrdmacm -lpthread
-LDADD+= -lmlx4
+LIBADD= ibverbs rdmacm pthread mlx4
.include <bsd.prog.mk>
diff --git a/contrib/ofed/librdmacm/examples/build/mckey/Makefile b/contrib/ofed/librdmacm/examples/build/mckey/Makefile
index 4abaf2786d56..6ef498fb905b 100644
--- a/contrib/ofed/librdmacm/examples/build/mckey/Makefile
+++ b/contrib/ofed/librdmacm/examples/build/mckey/Makefile
@@ -5,7 +5,6 @@
PROG= mckey
MAN=
SRCS= mckey.c
-LDADD+= -libverbs -lrdmacm -lpthread
-LDADD+= -lmlx4
+LIBADD= ibverbs rdmacm pthread mlx4
.include <bsd.prog.mk>
diff --git a/contrib/ofed/librdmacm/examples/build/udaddy/Makefile b/contrib/ofed/librdmacm/examples/build/udaddy/Makefile
index 1e325505bc86..fc76534fbed1 100644
--- a/contrib/ofed/librdmacm/examples/build/udaddy/Makefile
+++ b/contrib/ofed/librdmacm/examples/build/udaddy/Makefile
@@ -5,7 +5,6 @@
PROG= udaddy
MAN=
SRCS= udaddy.c
-LDADD+= -libverbs -lrdmacm -lpthread
-LDADD+= -lmlx4
+LIBADD= ibverbs rdmacm pthread mlx4
.include <bsd.prog.mk>
diff --git a/contrib/openresolv/Makefile b/contrib/openresolv/Makefile
index aca2cb531769..a898b95e6b51 100644
--- a/contrib/openresolv/Makefile
+++ b/contrib/openresolv/Makefile
@@ -1,5 +1,5 @@
PKG= openresolv
-VERSION= 3.7.0
+VERSION= 3.7.1
# Nasty hack so that make clean works without configure being run
_CONFIG_MK!= test -e config.mk && echo config.mk || echo config-null.mk
@@ -37,7 +37,7 @@ SED_RESTARTCMD= -e 's:@RESTARTCMD \(.*\)@:${RESTARTCMD}:g'
DISTPREFIX?= ${PKG}-${VERSION}
DISTFILEGZ?= ${DISTPREFIX}.tar.gz
-DISTFILE?= ${DISTPREFIX}.tar.bz2
+DISTFILE?= ${DISTPREFIX}.tar.xz
FOSSILID?= current
.SUFFIXES: .in
@@ -77,9 +77,9 @@ install: proginstall maninstall
import:
rm -rf /tmp/${DISTPREFIX}
${INSTALL} -d /tmp/${DISTPREFIX}
- cp README ${SRCS} /tmp/${DISPREFIX}
+ cp README ${SRCS} /tmp/${DISTPREFIX}
dist:
fossil tarball --name ${DISTPREFIX} ${FOSSILID} ${DISTFILEGZ}
- gunzip -c ${DISTFILEGZ} | bzip2 >${DISTFILE}
+ gunzip -c ${DISTFILEGZ} | xz >${DISTFILE}
rm ${DISTFILEGZ}
diff --git a/contrib/openresolv/resolvconf.8.in b/contrib/openresolv/resolvconf.8.in
index 10dcf5dd7399..bfbfc7f4726a 100644
--- a/contrib/openresolv/resolvconf.8.in
+++ b/contrib/openresolv/resolvconf.8.in
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd April 27, 2014
+.Dd April 27, 2015
.Dt RESOLVCONF 8
.Os
.Sh NAME
diff --git a/contrib/openresolv/resolvconf.conf.5.in b/contrib/openresolv/resolvconf.conf.5.in
index d4f654308e9e..7aa14507f4e8 100644
--- a/contrib/openresolv/resolvconf.conf.5.in
+++ b/contrib/openresolv/resolvconf.conf.5.in
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd March 20, 2015
+.Dd May 14, 2015
.Dt RESOLVCONF.CONF 5
.Os
.Sh NAME
@@ -91,6 +91,11 @@ To remove a block, you can use 192.168.*
These interfaces name servers will only be queried for the domains listed
in their resolv.conf.
Useful for VPN domains.
+Setting
+.Sy private_interfaces Ns ="*"
+will stop the forwarding of the root zone and allows the local resolver to
+recursively query the root servers directly.
+Requires a local nameserver other than libc.
This is equivalent to the
.Nm resolvconf -p
option.
@@ -149,7 +154,7 @@ When set to /dev/null or NULL,
.Sy resolv_conf_local_only
is defaulted to NO,
.Sy local_nameservers
-is unset unless overriden and only the information set in
+is unset unless overridden and only the information set in
.Nm
is written to
.Sy resolv_conf .
@@ -271,7 +276,7 @@ Each subscriber attempts to automatically configure itself, but not every
distribution has been catered for.
Also, users could equally want to use a different version from the one
installed by default, such as bind8 and bind9.
-To accomodate this, the subscribers have these files in configurable
+To accommodate this, the subscribers have these files in configurable
variables, documented below.
.Pp
.Bl -tag -width indent
diff --git a/contrib/openresolv/resolvconf.in b/contrib/openresolv/resolvconf.in
index 3b2b0f53fd83..a946ed8c44b5 100644
--- a/contrib/openresolv/resolvconf.in
+++ b/contrib/openresolv/resolvconf.in
@@ -50,7 +50,6 @@ elif [ -d "$SYSCONFDIR/resolvconf" ]; then
interface_order="$(cat "$SYSCONFDIR"/interface-order)"
fi
fi
-TMPDIR="$VARDIR/tmp"
IFACEDIR="$VARDIR/interfaces"
METRICDIR="$VARDIR/metrics"
PRIVATEDIR="$VARDIR/private"
diff --git a/contrib/openresolv/unbound.in b/contrib/openresolv/unbound.in
index 5752e6f2c412..a803615783fc 100644
--- a/contrib/openresolv/unbound.in
+++ b/contrib/openresolv/unbound.in
@@ -45,7 +45,8 @@ for d in $DOMAINS; do
ns="${d#*:}"
case "$unbound_insecure" in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
- newconf="$newconf${NL}domain-insecure: \"$dn\""
+ newconf="$newconf${NL}server:$NL"
+ newconf="$newconf domain-insecure: \"$dn\"$NL"
;;
esac
newconf="$newconf${NL}forward-zone:$NL name: \"$dn\"$NL"
diff --git a/contrib/smbfs/smbutil/print.c b/contrib/smbfs/smbutil/print.c
index d87ec78587c6..5e4538f7d1cb 100644
--- a/contrib/smbfs/smbutil/print.c
+++ b/contrib/smbfs/smbutil/print.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
+#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <sysexits.h>
diff --git a/contrib/unbound/.gitignore b/contrib/unbound/.gitignore
deleted file mode 100644
index 7fed8d74d386..000000000000
--- a/contrib/unbound/.gitignore
+++ /dev/null
@@ -1,38 +0,0 @@
-*.lo
-*.o
-/.libs/
-/Makefile
-/autom4te.cache/
-/config.h
-/config.log
-/config.status
-/dnstap/dnstap_config.h
-/doc/example.conf
-/doc/libunbound.3
-/doc/unbound-anchor.8
-/doc/unbound-checkconf.8
-/doc/unbound-control.8
-/doc/unbound-host.1
-/doc/unbound.8
-/doc/unbound.conf.5
-/libtool
-/libunbound.la
-/smallapp/unbound-control-setup.sh
-/unbound
-/unbound-anchor
-/unbound-checkconf
-/unbound-control
-/unbound-control-setup
-/unbound-host
-/unbound.h
-/asynclook
-/delayer
-/lock-verify
-/memstats
-/perf
-/petal
-/pktview
-/streamtcp
-/testbound
-/unittest
-
diff --git a/crypto/openssh/sshd_config b/crypto/openssh/sshd_config
index 6ab7900bc544..5cf3d4f6ea97 100644
--- a/crypto/openssh/sshd_config
+++ b/crypto/openssh/sshd_config
@@ -45,7 +45,7 @@
# Authentication:
#LoginGraceTime 2m
-#PermitRootLogin prohibit-password
+#PermitRootLogin no
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
diff --git a/crypto/openssh/sshd_config.5 b/crypto/openssh/sshd_config.5
index 9945fc93cab0..e9e460b5e297 100644
--- a/crypto/openssh/sshd_config.5
+++ b/crypto/openssh/sshd_config.5
@@ -1217,7 +1217,7 @@ The argument must be
or
.Dq no .
The default is
-.Dq prohibit-password .
+.Dq no .
Note that if
.Cm ChallengeResponseAuthentication
is
diff --git a/crypto/openssl/ACKNOWLEDGMENTS b/crypto/openssl/ACKNOWLEDGMENTS
index 59c6f01f97f6..d21dccbb79cf 100644
--- a/crypto/openssl/ACKNOWLEDGMENTS
+++ b/crypto/openssl/ACKNOWLEDGMENTS
@@ -1,30 +1,2 @@
-The OpenSSL project depends on volunteer efforts and financial support from
-the end user community. That support comes in the form of donations and paid
-sponsorships, software support contracts, paid consulting services
-and commissioned software development.
-
-Since all these activities support the continued development and improvement
-of OpenSSL we consider all these clients and customers as sponsors of the
-OpenSSL project.
-
-We would like to identify and thank the following such sponsors for their past
-or current significant support of the OpenSSL project:
-
-Major support:
-
- Qualys http://www.qualys.com/
-
-Very significant support:
-
- OpenGear: http://www.opengear.com/
-
-Significant support:
-
- PSW Group: http://www.psw.net/
- Acano Ltd. http://acano.com/
-
-Please note that we ask permission to identify sponsors and that some sponsors
-we consider eligible for inclusion here have requested to remain anonymous.
-
-Additional sponsorship or financial support is always welcome: for more
-information please contact the OpenSSL Software Foundation.
+Please https://www.openssl.org/community/thanks.html for the current
+acknowledgements.
diff --git a/crypto/openssl/CHANGES b/crypto/openssl/CHANGES
index 5e9225b57cd9..18693f70efe9 100644
--- a/crypto/openssl/CHANGES
+++ b/crypto/openssl/CHANGES
@@ -2,6 +2,54 @@
OpenSSL CHANGES
_______________
+ Changes between 1.0.2e and 1.0.2f [28 Jan 2016]
+
+ *) DH small subgroups
+
+ Historically OpenSSL only ever generated DH parameters based on "safe"
+ primes. More recently (in version 1.0.2) support was provided for
+ generating X9.42 style parameter files such as those required for RFC 5114
+ support. The primes used in such files may not be "safe". Where an
+ application is using DH configured with parameters based on primes that are
+ not "safe" then an attacker could use this fact to find a peer's private
+ DH exponent. This attack requires that the attacker complete multiple
+ handshakes in which the peer uses the same private DH exponent. For example
+ this could be used to discover a TLS server's private DH exponent if it's
+ reusing the private DH exponent or it's using a static DH ciphersuite.
+
+ OpenSSL provides the option SSL_OP_SINGLE_DH_USE for ephemeral DH (DHE) in
+ TLS. It is not on by default. If the option is not set then the server
+ reuses the same private DH exponent for the life of the server process and
+ would be vulnerable to this attack. It is believed that many popular
+ applications do set this option and would therefore not be at risk.
+
+ The fix for this issue adds an additional check where a "q" parameter is
+ available (as is the case in X9.42 based parameters). This detects the
+ only known attack, and is the only possible defense for static DH
+ ciphersuites. This could have some performance impact.
+
+ Additionally the SSL_OP_SINGLE_DH_USE option has been switched on by
+ default and cannot be disabled. This could have some performance impact.
+
+ This issue was reported to OpenSSL by Antonio Sanso (Adobe).
+ (CVE-2016-0701)
+ [Matt Caswell]
+
+ *) SSLv2 doesn't block disabled ciphers
+
+ A malicious client can negotiate SSLv2 ciphers that have been disabled on
+ the server and complete SSLv2 handshakes even if all SSLv2 ciphers have
+ been disabled, provided that the SSLv2 protocol was not also disabled via
+ SSL_OP_NO_SSLv2.
+
+ This issue was reported to OpenSSL on 26th December 2015 by Nimrod Aviram
+ and Sebastian Schinzel.
+ (CVE-2015-3197)
+ [Viktor Dukhovni]
+
+ *) Reject DH handshakes with parameters shorter than 1024 bits.
+ [Kurt Roeckx]
+
Changes between 1.0.2d and 1.0.2e [3 Dec 2015]
*) BN_mod_exp may produce incorrect results on x86_64
diff --git a/crypto/openssl/Configure b/crypto/openssl/Configure
index ac86cd6cf6a2..4a715dc43732 100755
--- a/crypto/openssl/Configure
+++ b/crypto/openssl/Configure
@@ -124,6 +124,9 @@ my $clang_disabled_warnings = "-Wno-unused-parameter -Wno-missing-field-initiali
# -Wextended-offsetof
my $clang_devteam_warn = "-Wno-unused-parameter -Wno-missing-field-initializers -Wno-language-extension-token -Wno-extended-offsetof -Qunused-arguments";
+# Warn that "make depend" should be run?
+my $warn_make_depend = 0;
+
my $strict_warnings = 0;
my $x86_gcc_des="DES_PTR DES_RISC1 DES_UNROLL";
@@ -1513,7 +1516,7 @@ if ($target =~ /\-icc$/) # Intel C compiler
# linker only when --prefix is not /usr.
if ($target =~ /^BSD\-/)
{
- $shared_ldflag.=" -Wl,-rpath,\$(LIBRPATH)" if ($prefix !~ m|^/usr[/]*$|);
+ $shared_ldflag.=" -Wl,-rpath,\$\$(LIBRPATH)" if ($prefix !~ m|^/usr[/]*$|);
}
if ($sys_id ne "")
@@ -2028,14 +2031,8 @@ EOF
&dofile("apps/CA.pl",'/usr/local/bin/perl','^#!/', '#!%s');
}
if ($depflags ne $default_depflags && !$make_depend) {
- print <<EOF;
-
-Since you've disabled or enabled at least one algorithm, you need to do
-the following before building:
-
- make depend
-EOF
- }
+ $warn_make_depend++;
+ }
}
# create the ms/version32.rc file if needed
@@ -2114,12 +2111,18 @@ EOF
print <<\EOF if ($no_shared_warn);
-You gave the option 'shared'. Normally, that would give you shared libraries.
-Unfortunately, the OpenSSL configuration doesn't include shared library support
-for this platform yet, so it will pretend you gave the option 'no-shared'. If
-you can inform the developpers (openssl-dev\@openssl.org) how to support shared
-libraries on this platform, they will at least look at it and try their best
-(but please first make sure you have tried with a current version of OpenSSL).
+You gave the option 'shared', which is not supported on this platform, so
+we will pretend you gave the option 'no-shared'. If you know how to implement
+shared libraries, please let us know (but please first make sure you have
+tried with a current version of OpenSSL).
+EOF
+
+print <<EOF if ($warn_make_depend);
+
+*** Because of configuration changes, you MUST do the following before
+*** building:
+
+ make depend
EOF
exit(0);
diff --git a/crypto/openssl/INSTALL b/crypto/openssl/INSTALL
index 1325079f2a99..679b30d4c790 100644
--- a/crypto/openssl/INSTALL
+++ b/crypto/openssl/INSTALL
@@ -164,10 +164,10 @@
standard headers). If it is a problem with OpenSSL itself, please
report the problem to <openssl-bugs@openssl.org> (note that your
message will be recorded in the request tracker publicly readable
- via http://www.openssl.org/support/rt.html and will be forwarded to a
- public mailing list). Include the output of "make report" in your message.
- Please check out the request tracker. Maybe the bug was already
- reported or has already been fixed.
+ at https://www.openssl.org/community/index.html#bugs and will be
+ forwarded to a public mailing list). Include the output of "make
+ report" in your message. Please check out the request tracker. Maybe
+ the bug was already reported or has already been fixed.
[If you encounter assembler error messages, try the "no-asm"
configuration option as an immediate fix.]
diff --git a/crypto/openssl/LICENSE b/crypto/openssl/LICENSE
index e47d101f1025..fb03713dd111 100644
--- a/crypto/openssl/LICENSE
+++ b/crypto/openssl/LICENSE
@@ -12,7 +12,7 @@
---------------
/* ====================================================================
- * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2016 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/crypto/openssl/Makefile b/crypto/openssl/Makefile
index e2bbb475c7df..ee04c02cc1ca 100644
--- a/crypto/openssl/Makefile
+++ b/crypto/openssl/Makefile
@@ -4,7 +4,7 @@
## Makefile for OpenSSL
##
-VERSION=1.0.2e
+VERSION=1.0.2f
MAJOR=1
MINOR=0.2
SHLIB_VERSION_NUMBER=1.0.0
@@ -182,8 +182,7 @@ SHARED_LDFLAGS=
GENERAL= Makefile
BASENAME= openssl
NAME= $(BASENAME)-$(VERSION)
-TARFILE= $(NAME).tar
-WTARFILE= $(NAME)-win.tar
+TARFILE= ../$(NAME).tar
EXHEADER= e_os2.h
HEADER= e_os.h
@@ -501,38 +500,35 @@ TABLE: Configure
# would occur. Therefore the list of files is temporarily stored into a file
# and read directly, requiring GNU-Tar. Call "make TAR=gtar dist" if the normal
# tar does not support the --files-from option.
-TAR_COMMAND=$(TAR) $(TARFLAGS) --files-from ../$(TARFILE).list \
- --owner openssl:0 --group openssl:0 \
- --transform 's|^|openssl-$(VERSION)/|' \
+TAR_COMMAND=$(TAR) $(TARFLAGS) --files-from $(TARFILE).list \
+ --owner 0 --group 0 \
+ --transform 's|^|$(NAME)/|' \
-cvf -
-../$(TARFILE).list:
+$(TARFILE).list:
find * \! -name STATUS \! -name TABLE \! -name '*.o' \! -name '*.a' \
\! -name '*.so' \! -name '*.so.*' \! -name 'openssl' \
- \! -name '*test' \! -name '.#*' \! -name '*~' \
- | sort > ../$(TARFILE).list
+ \( \! -name '*test' -o -name bctest -o -name pod2mantest \) \
+ \! -name '.#*' \! -name '*~' \! -type l \
+ | sort > $(TARFILE).list
-tar: ../$(TARFILE).list
+tar: $(TARFILE).list
find . -type d -print | xargs chmod 755
find . -type f -print | xargs chmod a+r
find . -type f -perm -0100 -print | xargs chmod a+x
- $(TAR_COMMAND) | gzip --best >../$(TARFILE).gz
- rm -f ../$(TARFILE).list
- ls -l ../$(TARFILE).gz
+ $(TAR_COMMAND) | gzip --best > $(TARFILE).gz
+ rm -f $(TARFILE).list
+ ls -l $(TARFILE).gz
-tar-snap: ../$(TARFILE).list
- $(TAR_COMMAND) > ../$(TARFILE)
- rm -f ../$(TARFILE).list
- ls -l ../$(TARFILE)
+tar-snap: $(TARFILE).list
+ $(TAR_COMMAND) > $(TARFILE)
+ rm -f $(TARFILE).list
+ ls -l $(TARFILE)
dist:
$(PERL) Configure dist
- @$(MAKE) dist_pem_h
@$(MAKE) SDIRS='$(SDIRS)' clean
- @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' tar
-
-dist_pem_h:
- (cd crypto/pem; $(MAKE) -e $(BUILDENV) pem.h; $(MAKE) clean)
+ @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' $(DISTTARVARS) tar
install: all install_docs install_sw
diff --git a/crypto/openssl/Makefile.org b/crypto/openssl/Makefile.org
index f16770d69b22..15c1c9f54428 100644
--- a/crypto/openssl/Makefile.org
+++ b/crypto/openssl/Makefile.org
@@ -180,8 +180,7 @@ SHARED_LDFLAGS=
GENERAL= Makefile
BASENAME= openssl
NAME= $(BASENAME)-$(VERSION)
-TARFILE= $(NAME).tar
-WTARFILE= $(NAME)-win.tar
+TARFILE= ../$(NAME).tar
EXHEADER= e_os2.h
HEADER= e_os.h
@@ -499,38 +498,35 @@ TABLE: Configure
# would occur. Therefore the list of files is temporarily stored into a file
# and read directly, requiring GNU-Tar. Call "make TAR=gtar dist" if the normal
# tar does not support the --files-from option.
-TAR_COMMAND=$(TAR) $(TARFLAGS) --files-from ../$(TARFILE).list \
- --owner openssl:0 --group openssl:0 \
- --transform 's|^|openssl-$(VERSION)/|' \
+TAR_COMMAND=$(TAR) $(TARFLAGS) --files-from $(TARFILE).list \
+ --owner 0 --group 0 \
+ --transform 's|^|$(NAME)/|' \
-cvf -
-../$(TARFILE).list:
+$(TARFILE).list:
find * \! -name STATUS \! -name TABLE \! -name '*.o' \! -name '*.a' \
\! -name '*.so' \! -name '*.so.*' \! -name 'openssl' \
- \! -name '*test' \! -name '.#*' \! -name '*~' \
- | sort > ../$(TARFILE).list
+ \( \! -name '*test' -o -name bctest -o -name pod2mantest \) \
+ \! -name '.#*' \! -name '*~' \! -type l \
+ | sort > $(TARFILE).list
-tar: ../$(TARFILE).list
+tar: $(TARFILE).list
find . -type d -print | xargs chmod 755
find . -type f -print | xargs chmod a+r
find . -type f -perm -0100 -print | xargs chmod a+x
- $(TAR_COMMAND) | gzip --best >../$(TARFILE).gz
- rm -f ../$(TARFILE).list
- ls -l ../$(TARFILE).gz
+ $(TAR_COMMAND) | gzip --best > $(TARFILE).gz
+ rm -f $(TARFILE).list
+ ls -l $(TARFILE).gz
-tar-snap: ../$(TARFILE).list
- $(TAR_COMMAND) > ../$(TARFILE)
- rm -f ../$(TARFILE).list
- ls -l ../$(TARFILE)
+tar-snap: $(TARFILE).list
+ $(TAR_COMMAND) > $(TARFILE)
+ rm -f $(TARFILE).list
+ ls -l $(TARFILE)
dist:
$(PERL) Configure dist
- @$(MAKE) dist_pem_h
@$(MAKE) SDIRS='$(SDIRS)' clean
- @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' tar
-
-dist_pem_h:
- (cd crypto/pem; $(MAKE) -e $(BUILDENV) pem.h; $(MAKE) clean)
+ @$(MAKE) TAR='$(TAR)' TARFLAGS='$(TARFLAGS)' $(DISTTARVARS) tar
install: all install_docs install_sw
diff --git a/crypto/openssl/NEWS b/crypto/openssl/NEWS
index e1c78f834f08..06c77025e999 100644
--- a/crypto/openssl/NEWS
+++ b/crypto/openssl/NEWS
@@ -5,6 +5,11 @@
This file gives a brief overview of the major changes between each OpenSSL
release. For more details please read the CHANGES file.
+ Major changes between OpenSSL 1.0.2e and OpenSSL 1.0.2f [28 Jan 2016]
+
+ o DH small subgroups (CVE-2016-0701)
+ o SSLv2 doesn't block disabled ciphers (CVE-2015-3197)
+
Major changes between OpenSSL 1.0.2d and OpenSSL 1.0.2e [3 Dec 2015]
o BN_mod_exp may produce incorrect results on x86_64 (CVE-2015-3193)
diff --git a/crypto/openssl/README b/crypto/openssl/README
index 49c4c9f147c3..1e9869daee00 100644
--- a/crypto/openssl/README
+++ b/crypto/openssl/README
@@ -1,5 +1,5 @@
- OpenSSL 1.0.2e 3 Dec 2015
+ OpenSSL 1.0.2f 28 Jan 2016
Copyright (c) 1998-2015 The OpenSSL Project
Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
@@ -90,11 +90,12 @@
In order to avoid spam, this is a moderated mailing list, and it might
take a day for the ticket to show up. (We also scan posts to make sure
- that security disclosures aren't publically posted by mistake.) Mail to
- this address is recorded in the public RT (request tracker) database (see
- https://www.openssl.org/support/rt.html for details) and also forwarded
- the public openssl-dev mailing list. Confidential mail may be sent to
- openssl-security@openssl.org (PGP key available from the key servers).
+ that security disclosures aren't publically posted by mistake.) Mail
+ to this address is recorded in the public RT (request tracker) database
+ (see https://www.openssl.org/community/index.html#bugs for details) and
+ also forwarded the public openssl-dev mailing list. Confidential mail
+ may be sent to openssl-security@openssl.org (PGP key available from the
+ key servers).
Please do NOT use this for general assistance or support queries.
Just because something doesn't work the way you expect does not mean it
diff --git a/crypto/openssl/apps/engine.c b/crypto/openssl/apps/engine.c
index 460ec60cb14c..f54631b50d81 100644
--- a/crypto/openssl/apps/engine.c
+++ b/crypto/openssl/apps/engine.c
@@ -1,4 +1,4 @@
-/* apps/engine.c -*- mode: C; c-file-style: "eay" -*- */
+/* apps/engine.c */
/*
* Written by Richard Levitte <richard@levitte.org> for the OpenSSL project
* 2000.
diff --git a/crypto/openssl/apps/ocsp.c b/crypto/openssl/apps/ocsp.c
index 6ed255d4b563..5da51df5148c 100644
--- a/crypto/openssl/apps/ocsp.c
+++ b/crypto/openssl/apps/ocsp.c
@@ -1041,7 +1041,7 @@ static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req,
bs = OCSP_BASICRESP_new();
thisupd = X509_gmtime_adj(NULL, 0);
if (ndays != -1)
- nextupd = X509_gmtime_adj(NULL, nmin * 60 + ndays * 3600 * 24);
+ nextupd = X509_time_adj_ex(NULL, ndays, nmin * 60, NULL);
/* Examine each certificate id in the request */
for (i = 0; i < id_count; i++) {
diff --git a/crypto/openssl/apps/pkcs12.c b/crypto/openssl/apps/pkcs12.c
index e41b445a50b0..cbb75b7d5fe4 100644
--- a/crypto/openssl/apps/pkcs12.c
+++ b/crypto/openssl/apps/pkcs12.c
@@ -79,7 +79,8 @@ const EVP_CIPHER *enc;
# define CLCERTS 0x8
# define CACERTS 0x10
-int get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain);
+static int get_cert_chain(X509 *cert, X509_STORE *store,
+ STACK_OF(X509) **chain);
int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen,
int options, char *pempass);
int dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags,
@@ -594,7 +595,7 @@ int MAIN(int argc, char **argv)
vret = get_cert_chain(ucert, store, &chain2);
X509_STORE_free(store);
- if (!vret) {
+ if (vret == X509_V_OK) {
/* Exclude verified certificate */
for (i = 1; i < sk_X509_num(chain2); i++)
sk_X509_push(certs, sk_X509_value(chain2, i));
@@ -602,7 +603,7 @@ int MAIN(int argc, char **argv)
X509_free(sk_X509_value(chain2, 0));
sk_X509_free(chain2);
} else {
- if (vret >= 0)
+ if (vret != X509_V_ERR_UNSPECIFIED)
BIO_printf(bio_err, "Error %s getting chain.\n",
X509_verify_cert_error_string(vret));
else
@@ -906,36 +907,25 @@ int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass,
/* Given a single certificate return a verified chain or NULL if error */
-/* Hope this is OK .... */
-
-int get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain)
+static int get_cert_chain(X509 *cert, X509_STORE *store,
+ STACK_OF(X509) **chain)
{
X509_STORE_CTX store_ctx;
- STACK_OF(X509) *chn;
+ STACK_OF(X509) *chn = NULL;
int i = 0;
- /*
- * FIXME: Should really check the return status of X509_STORE_CTX_init
- * for an error, but how that fits into the return value of this function
- * is less obvious.
- */
- X509_STORE_CTX_init(&store_ctx, store, cert, NULL);
- if (X509_verify_cert(&store_ctx) <= 0) {
- i = X509_STORE_CTX_get_error(&store_ctx);
- if (i == 0)
- /*
- * avoid returning 0 if X509_verify_cert() did not set an
- * appropriate error value in the context
- */
- i = -1;
- chn = NULL;
- goto err;
- } else
+ if (!X509_STORE_CTX_init(&store_ctx, store, cert, NULL)) {
+ *chain = NULL;
+ return X509_V_ERR_UNSPECIFIED;
+ }
+
+ if (X509_verify_cert(&store_ctx) > 0)
chn = X509_STORE_CTX_get1_chain(&store_ctx);
- err:
+ else if ((i = X509_STORE_CTX_get_error(&store_ctx)) == 0)
+ i = X509_V_ERR_UNSPECIFIED;
+
X509_STORE_CTX_cleanup(&store_ctx);
*chain = chn;
-
return i;
}
diff --git a/crypto/openssl/apps/pkeyutl.c b/crypto/openssl/apps/pkeyutl.c
index aaa90740ad4d..c8d513b44ac4 100644
--- a/crypto/openssl/apps/pkeyutl.c
+++ b/crypto/openssl/apps/pkeyutl.c
@@ -74,10 +74,11 @@ static void usage(void);
static EVP_PKEY_CTX *init_ctx(int *pkeysize,
char *keyfile, int keyform, int key_type,
- char *passargin, int pkey_op, ENGINE *e);
+ char *passargin, int pkey_op, ENGINE *e,
+ int impl);
static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform,
- const char *file);
+ const char *file, ENGINE* e);
static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
unsigned char *out, size_t *poutlen,
@@ -97,6 +98,7 @@ int MAIN(int argc, char **argv)
EVP_PKEY_CTX *ctx = NULL;
char *passargin = NULL;
int keysize = -1;
+ int engine_impl = 0;
unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
size_t buf_outlen;
@@ -137,7 +139,7 @@ int MAIN(int argc, char **argv)
else {
ctx = init_ctx(&keysize,
*(++argv), keyform, key_type,
- passargin, pkey_op, e);
+ passargin, pkey_op, e, engine_impl);
if (!ctx) {
BIO_puts(bio_err, "Error initializing context\n");
ERR_print_errors(bio_err);
@@ -147,7 +149,7 @@ int MAIN(int argc, char **argv)
} else if (!strcmp(*argv, "-peerkey")) {
if (--argc < 1)
badarg = 1;
- else if (!setup_peer(bio_err, ctx, peerform, *(++argv)))
+ else if (!setup_peer(bio_err, ctx, peerform, *(++argv), e))
badarg = 1;
} else if (!strcmp(*argv, "-passin")) {
if (--argc < 1)
@@ -171,6 +173,8 @@ int MAIN(int argc, char **argv)
badarg = 1;
else
e = setup_engine(bio_err, *(++argv), 0);
+ } else if (!strcmp(*argv, "-engine_impl")) {
+ engine_impl = 1;
}
#endif
else if (!strcmp(*argv, "-pubin"))
@@ -368,7 +372,8 @@ static void usage()
BIO_printf(bio_err, "-hexdump hex dump output\n");
#ifndef OPENSSL_NO_ENGINE
BIO_printf(bio_err,
- "-engine e use engine e, possibly a hardware device.\n");
+ "-engine e use engine e, maybe a hardware device, for loading keys.\n");
+ BIO_printf(bio_err, "-engine_impl also use engine given by -engine for crypto operations\n");
#endif
BIO_printf(bio_err, "-passin arg pass phrase source\n");
@@ -376,10 +381,12 @@ static void usage()
static EVP_PKEY_CTX *init_ctx(int *pkeysize,
char *keyfile, int keyform, int key_type,
- char *passargin, int pkey_op, ENGINE *e)
+ char *passargin, int pkey_op, ENGINE *e,
+ int engine_impl)
{
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
+ ENGINE *impl = NULL;
char *passin = NULL;
int rv = -1;
X509 *x;
@@ -418,9 +425,14 @@ static EVP_PKEY_CTX *init_ctx(int *pkeysize,
if (!pkey)
goto end;
-
- ctx = EVP_PKEY_CTX_new(pkey, e);
-
+
+#ifndef OPENSSL_NO_ENGINE
+ if (engine_impl)
+ impl = e;
+#endif
+
+ ctx = EVP_PKEY_CTX_new(pkey, impl);
+
EVP_PKEY_free(pkey);
if (!ctx)
@@ -467,16 +479,20 @@ static EVP_PKEY_CTX *init_ctx(int *pkeysize,
}
static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform,
- const char *file)
+ const char *file, ENGINE* e)
{
EVP_PKEY *peer = NULL;
+ ENGINE* engine = NULL;
int ret;
if (!ctx) {
BIO_puts(err, "-peerkey command before -inkey\n");
return 0;
}
- peer = load_pubkey(bio_err, file, peerform, 0, NULL, NULL, "Peer Key");
+ if (peerform == FORMAT_ENGINE)
+ engine = e;
+
+ peer = load_pubkey(bio_err, file, peerform, 0, NULL, engine, "Peer Key");
if (!peer) {
BIO_printf(bio_err, "Error reading peer key %s\n", file);
diff --git a/crypto/openssl/apps/s_client.c b/crypto/openssl/apps/s_client.c
index f80711fd5e58..caf76d35dc5a 100644
--- a/crypto/openssl/apps/s_client.c
+++ b/crypto/openssl/apps/s_client.c
@@ -308,7 +308,7 @@ static void sc_usage(void)
" -connect host:port - who to connect to (default is %s:%s)\n",
SSL_HOST_NAME, PORT_STR);
BIO_printf(bio_err,
- " -verify_host host - check peer certificate matches \"host\"\n");
+ " -verify_hostname host - check peer certificate matches \"host\"\n");
BIO_printf(bio_err,
" -verify_email email - check peer certificate matches \"email\"\n");
BIO_printf(bio_err,
diff --git a/crypto/openssl/apps/s_server.c b/crypto/openssl/apps/s_server.c
index f19532b75fab..65cbaaf6eb9b 100644
--- a/crypto/openssl/apps/s_server.c
+++ b/crypto/openssl/apps/s_server.c
@@ -498,7 +498,7 @@ static void sv_usage(void)
BIO_printf(bio_err,
" -accept arg - port to accept on (default is %d)\n", PORT);
BIO_printf(bio_err,
- " -verify_host host - check peer certificate matches \"host\"\n");
+ " -verify_hostname host - check peer certificate matches \"host\"\n");
BIO_printf(bio_err,
" -verify_email email - check peer certificate matches \"email\"\n");
BIO_printf(bio_err,
diff --git a/crypto/openssl/apps/speed.c b/crypto/openssl/apps/speed.c
index 3697b71ec18b..95adcc19cc15 100644
--- a/crypto/openssl/apps/speed.c
+++ b/crypto/openssl/apps/speed.c
@@ -1,4 +1,4 @@
-/* apps/speed.c -*- mode:C; c-file-style: "eay" -*- */
+/* apps/speed.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
diff --git a/crypto/openssl/apps/x509.c b/crypto/openssl/apps/x509.c
index 864a60dda2e7..7c215bced001 100644
--- a/crypto/openssl/apps/x509.c
+++ b/crypto/openssl/apps/x509.c
@@ -1226,12 +1226,7 @@ static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
goto err;
- /* Lets just make it 12:00am GMT, Jan 1 1970 */
- /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
- /* 28 days to be certified */
-
- if (X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * days) ==
- NULL)
+ if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
goto err;
if (!X509_set_pubkey(x, pkey))
diff --git a/crypto/openssl/crypto/aes/aes.h b/crypto/openssl/crypto/aes/aes.h
index 87bf60f6f2bf..faa66c49148f 100644
--- a/crypto/openssl/crypto/aes/aes.h
+++ b/crypto/openssl/crypto/aes/aes.h
@@ -1,4 +1,4 @@
-/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes.h */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/aes/aes_cbc.c b/crypto/openssl/crypto/aes/aes_cbc.c
index e39231f17cb8..805d0e260a6f 100644
--- a/crypto/openssl/crypto/aes/aes_cbc.c
+++ b/crypto/openssl/crypto/aes/aes_cbc.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_cbc.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_cbc.c */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/aes/aes_cfb.c b/crypto/openssl/crypto/aes/aes_cfb.c
index 1c79ce2dbaa1..1225000963ea 100644
--- a/crypto/openssl/crypto/aes/aes_cfb.c
+++ b/crypto/openssl/crypto/aes/aes_cfb.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_cfb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_cfb.c */
/* ====================================================================
* Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/aes/aes_core.c b/crypto/openssl/crypto/aes/aes_core.c
index 2ddb0860d78a..7019b5d7aa3a 100644
--- a/crypto/openssl/crypto/aes/aes_core.c
+++ b/crypto/openssl/crypto/aes/aes_core.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_core.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_core.c */
/**
* rijndael-alg-fst.c
*
diff --git a/crypto/openssl/crypto/aes/aes_ctr.c b/crypto/openssl/crypto/aes/aes_ctr.c
index 3ee382299881..9e760c4b12ad 100644
--- a/crypto/openssl/crypto/aes/aes_ctr.c
+++ b/crypto/openssl/crypto/aes/aes_ctr.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_ctr.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_ctr.c */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/aes/aes_ecb.c b/crypto/openssl/crypto/aes/aes_ecb.c
index 2e0d20ca224e..52151a5c70f4 100644
--- a/crypto/openssl/crypto/aes/aes_ecb.c
+++ b/crypto/openssl/crypto/aes/aes_ecb.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_ecb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_ecb.c */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/aes/aes_ige.c b/crypto/openssl/crypto/aes/aes_ige.c
index cf31c9bba44a..8f2b7706472a 100644
--- a/crypto/openssl/crypto/aes/aes_ige.c
+++ b/crypto/openssl/crypto/aes/aes_ige.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_ige.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_ige.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/aes/aes_locl.h b/crypto/openssl/crypto/aes/aes_locl.h
index fabfd02ac095..7acd74ec1603 100644
--- a/crypto/openssl/crypto/aes/aes_locl.h
+++ b/crypto/openssl/crypto/aes/aes_locl.h
@@ -1,4 +1,4 @@
-/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes.h */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/aes/aes_misc.c b/crypto/openssl/crypto/aes/aes_misc.c
index ab948ad85eb4..fafad4d6f57a 100644
--- a/crypto/openssl/crypto/aes/aes_misc.c
+++ b/crypto/openssl/crypto/aes/aes_misc.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_misc.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_misc.c */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/aes/aes_ofb.c b/crypto/openssl/crypto/aes/aes_ofb.c
index e6153f99ba70..64a08caaec6d 100644
--- a/crypto/openssl/crypto/aes/aes_ofb.c
+++ b/crypto/openssl/crypto/aes/aes_ofb.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_ofb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_ofb.c */
/* ====================================================================
* Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/aes/aes_x86core.c b/crypto/openssl/crypto/aes/aes_x86core.c
index c869ed719852..b5dd6976772a 100644
--- a/crypto/openssl/crypto/aes/aes_x86core.c
+++ b/crypto/openssl/crypto/aes/aes_x86core.c
@@ -1,4 +1,4 @@
-/* crypto/aes/aes_core.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/aes/aes_core.c */
/**
* rijndael-alg-fst.c
*
diff --git a/crypto/openssl/crypto/aes/asm/aesni-mb-x86_64.pl b/crypto/openssl/crypto/aes/asm/aesni-mb-x86_64.pl
index 5a100fa8983b..d7ad7882c4ee 100755
--- a/crypto/openssl/crypto/aes/asm/aesni-mb-x86_64.pl
+++ b/crypto/openssl/crypto/aes/asm/aesni-mb-x86_64.pl
@@ -63,7 +63,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
$avx = ($1>=10) + ($1>=11);
}
-if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) {
+if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) {
$avx = ($2>=3.0) + ($2>3.0);
}
diff --git a/crypto/openssl/crypto/aes/asm/aesni-sha1-x86_64.pl b/crypto/openssl/crypto/aes/asm/aesni-sha1-x86_64.pl
index c803cdebc112..8c84260856e1 100755
--- a/crypto/openssl/crypto/aes/asm/aesni-sha1-x86_64.pl
+++ b/crypto/openssl/crypto/aes/asm/aesni-sha1-x86_64.pl
@@ -94,7 +94,7 @@ $avx=1 if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
$avx=1 if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
`ml64 2>&1` =~ /Version ([0-9]+)\./ &&
$1>=10);
-$avx=1 if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/ && $2>=3.0);
+$avx=1 if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/ && $2>=3.0);
$shaext=1; ### set to zero if compiling for 1.0.1
diff --git a/crypto/openssl/crypto/aes/asm/aesni-sha256-x86_64.pl b/crypto/openssl/crypto/aes/asm/aesni-sha256-x86_64.pl
index bfe29268c781..72f44ecf6253 100755
--- a/crypto/openssl/crypto/aes/asm/aesni-sha256-x86_64.pl
+++ b/crypto/openssl/crypto/aes/asm/aesni-sha256-x86_64.pl
@@ -59,7 +59,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
$avx = ($1>=10) + ($1>=12);
}
-if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) {
+if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) {
$avx = ($2>=3.0) + ($2>3.0);
}
diff --git a/crypto/openssl/crypto/bio/bio.h b/crypto/openssl/crypto/bio/bio.h
index f78796b069f5..6e2293bc66da 100644
--- a/crypto/openssl/crypto/bio/bio.h
+++ b/crypto/openssl/crypto/bio/bio.h
@@ -479,11 +479,11 @@ struct bio_dgram_sctp_prinfo {
# define BIO_get_conn_hostname(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0)
# define BIO_get_conn_port(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1)
# define BIO_get_conn_ip(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2)
-# define BIO_get_conn_int_port(b) BIO_int_ctrl(b,BIO_C_GET_CONNECT,3,0)
+# define BIO_get_conn_int_port(b) BIO_ctrl(b,BIO_C_GET_CONNECT,3,0,NULL)
# define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL)
-/* BIO_s_accept_socket() */
+/* BIO_s_accept() */
# define BIO_set_accept_port(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0,(char *)name)
# define BIO_get_accept_port(b) BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0)
/* #define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) */
@@ -496,6 +496,7 @@ struct bio_dgram_sctp_prinfo {
# define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL)
# define BIO_get_bind_mode(b,mode) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL)
+/* BIO_s_accept() and BIO_s_connect() */
# define BIO_do_connect(b) BIO_do_handshake(b)
# define BIO_do_accept(b) BIO_do_handshake(b)
# define BIO_do_handshake(b) BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL)
@@ -515,12 +516,15 @@ struct bio_dgram_sctp_prinfo {
# define BIO_get_url(b,url) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,2,(char *)(url))
# define BIO_get_no_connect_return(b) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,5,NULL)
+/* BIO_s_datagram(), BIO_s_fd(), BIO_s_socket(), BIO_s_accept() and BIO_s_connect() */
# define BIO_set_fd(b,fd,c) BIO_int_ctrl(b,BIO_C_SET_FD,c,fd)
# define BIO_get_fd(b,c) BIO_ctrl(b,BIO_C_GET_FD,0,(char *)c)
+/* BIO_s_file() */
# define BIO_set_fp(b,fp,c) BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)fp)
# define BIO_get_fp(b,fpp) BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)fpp)
+/* BIO_s_fd() and BIO_s_file() */
# define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL)
# define BIO_tell(b) (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL)
diff --git a/crypto/openssl/crypto/bio/bss_bio.c b/crypto/openssl/crypto/bio/bss_bio.c
index d629a37a5a1d..4d8727f8f890 100644
--- a/crypto/openssl/crypto/bio/bss_bio.c
+++ b/crypto/openssl/crypto/bio/bss_bio.c
@@ -1,4 +1,4 @@
-/* crypto/bio/bss_bio.c -*- Mode: C; c-file-style: "eay" -*- */
+/* crypto/bio/bss_bio.c */
/* ====================================================================
* Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/bio/bss_conn.c b/crypto/openssl/crypto/bio/bss_conn.c
index 42d0afffbc6c..7d15ad29dcd7 100644
--- a/crypto/openssl/crypto/bio/bss_conn.c
+++ b/crypto/openssl/crypto/bio/bss_conn.c
@@ -419,7 +419,7 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
{
BIO *dbio;
int *ip;
- const char **pptr;
+ const char **pptr = NULL;
long ret = 1;
BIO_CONNECT *data;
@@ -442,19 +442,28 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
case BIO_C_GET_CONNECT:
if (ptr != NULL) {
pptr = (const char **)ptr;
- if (num == 0) {
- *pptr = data->param_hostname;
+ }
- } else if (num == 1) {
- *pptr = data->param_port;
- } else if (num == 2) {
- *pptr = (char *)&(data->ip[0]);
- } else if (num == 3) {
- *((int *)ptr) = data->port;
+ if (b->init) {
+ if (pptr != NULL) {
+ ret = 1;
+ if (num == 0) {
+ *pptr = data->param_hostname;
+ } else if (num == 1) {
+ *pptr = data->param_port;
+ } else if (num == 2) {
+ *pptr = (char *)&(data->ip[0]);
+ } else {
+ ret = 0;
+ }
+ }
+ if (num == 3) {
+ ret = data->port;
}
- if ((!b->init) || (ptr == NULL))
+ } else {
+ if (pptr != NULL)
*pptr = "not initialized";
- ret = 1;
+ ret = 0;
}
break;
case BIO_C_SET_CONNECT:
diff --git a/crypto/openssl/crypto/bio/bss_dgram.c b/crypto/openssl/crypto/bio/bss_dgram.c
index 7fcd831da06b..bdd7bf88ea0e 100644
--- a/crypto/openssl/crypto/bio/bss_dgram.c
+++ b/crypto/openssl/crypto/bio/bss_dgram.c
@@ -519,10 +519,8 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
switch (cmd) {
case BIO_CTRL_RESET:
num = 0;
- case BIO_C_FILE_SEEK:
ret = 0;
break;
- case BIO_C_FILE_TELL:
case BIO_CTRL_INFO:
ret = 0;
break;
diff --git a/crypto/openssl/crypto/bn/asm/rsaz-x86_64.pl b/crypto/openssl/crypto/bn/asm/rsaz-x86_64.pl
index 12b571c282dc..091cdc2069da 100755
--- a/crypto/openssl/crypto/bn/asm/rsaz-x86_64.pl
+++ b/crypto/openssl/crypto/bn/asm/rsaz-x86_64.pl
@@ -113,7 +113,7 @@ if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
$addx = ($1>=12);
}
-if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9])\.([0-9]+)/) {
+if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) {
my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10
$addx = ($ver>=3.03);
}
diff --git a/crypto/openssl/crypto/bn/asm/x86_64-mont.pl b/crypto/openssl/crypto/bn/asm/x86_64-mont.pl
index 725833d022e2..e82e451388c7 100755
--- a/crypto/openssl/crypto/bn/asm/x86_64-mont.pl
+++ b/crypto/openssl/crypto/bn/asm/x86_64-mont.pl
@@ -68,7 +68,7 @@ if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
$addx = ($1>=12);
}
-if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9])\.([0-9]+)/) {
+if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) {
my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10
$addx = ($ver>=3.03);
}
diff --git a/crypto/openssl/crypto/bn/asm/x86_64-mont5.pl b/crypto/openssl/crypto/bn/asm/x86_64-mont5.pl
index 64e668f140c2..292409c4ffb8 100755
--- a/crypto/openssl/crypto/bn/asm/x86_64-mont5.pl
+++ b/crypto/openssl/crypto/bn/asm/x86_64-mont5.pl
@@ -53,7 +53,7 @@ if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
$addx = ($1>=12);
}
-if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9])\.([0-9]+)/) {
+if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) {
my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10
$addx = ($ver>=3.03);
}
diff --git a/crypto/openssl/crypto/bn/bn_exp.c b/crypto/openssl/crypto/bn/bn_exp.c
index 50cf3231b07b..6d30d1e0fff5 100644
--- a/crypto/openssl/crypto/bn/bn_exp.c
+++ b/crypto/openssl/crypto/bn/bn_exp.c
@@ -282,9 +282,14 @@ int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
}
bits = BN_num_bits(p);
-
if (bits == 0) {
- ret = BN_one(r);
+ /* x**0 mod 1 is still zero. */
+ if (BN_is_one(m)) {
+ ret = 1;
+ BN_zero(r);
+ } else {
+ ret = BN_one(r);
+ }
return ret;
}
@@ -418,7 +423,13 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
}
bits = BN_num_bits(p);
if (bits == 0) {
- ret = BN_one(rr);
+ /* x**0 mod 1 is still zero. */
+ if (BN_is_one(m)) {
+ ret = 1;
+ BN_zero(rr);
+ } else {
+ ret = BN_one(rr);
+ }
return ret;
}
@@ -639,7 +650,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top,
* precomputation memory layout to limit data-dependency to a minimum to
* protect secret exponents (cf. the hyper-threading timing attacks pointed
* out by Colin Percival,
- * http://www.daemong-consideredperthreading-considered-harmful/)
+ * http://www.daemonology.net/hyperthreading-considered-harmful/)
*/
int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx,
@@ -671,7 +682,13 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
bits = BN_num_bits(p);
if (bits == 0) {
- ret = BN_one(rr);
+ /* x**0 mod 1 is still zero. */
+ if (BN_is_one(m)) {
+ ret = 1;
+ BN_zero(rr);
+ } else {
+ ret = BN_one(rr);
+ }
return ret;
}
@@ -1182,8 +1199,9 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
if (BN_is_one(m)) {
ret = 1;
BN_zero(rr);
- } else
+ } else {
ret = BN_one(rr);
+ }
return ret;
}
if (a == 0) {
@@ -1297,9 +1315,14 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
}
bits = BN_num_bits(p);
-
- if (bits == 0) {
- ret = BN_one(r);
+ if (bits == 0) {
+ /* x**0 mod 1 is still zero. */
+ if (BN_is_one(m)) {
+ ret = 1;
+ BN_zero(r);
+ } else {
+ ret = BN_one(r);
+ }
return ret;
}
diff --git a/crypto/openssl/crypto/bn/exptest.c b/crypto/openssl/crypto/bn/exptest.c
index 8b3a4bae4328..ac611c2e2614 100644
--- a/crypto/openssl/crypto/bn/exptest.c
+++ b/crypto/openssl/crypto/bn/exptest.c
@@ -73,14 +73,34 @@ static const char rnd_seed[] =
"string to make the random number generator think it has entropy";
/*
+ * Test that r == 0 in test_exp_mod_zero(). Returns one on success,
+ * returns zero and prints debug output otherwise.
+ */
+static int a_is_zero_mod_one(const char *method, const BIGNUM *r,
+ const BIGNUM *a) {
+ if (!BN_is_zero(r)) {
+ fprintf(stderr, "%s failed:\n", method);
+ fprintf(stderr, "a ** 0 mod 1 = r (should be 0)\n");
+ fprintf(stderr, "a = ");
+ BN_print_fp(stderr, a);
+ fprintf(stderr, "\nr = ");
+ BN_print_fp(stderr, r);
+ fprintf(stderr, "\n");
+ return 0;
+ }
+ return 1;
+}
+
+/*
* test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success.
*/
static int test_exp_mod_zero()
{
BIGNUM a, p, m;
BIGNUM r;
+ BN_ULONG one_word = 1;
BN_CTX *ctx = BN_CTX_new();
- int ret = 1;
+ int ret = 1, failed = 0;
BN_init(&m);
BN_one(&m);
@@ -92,21 +112,65 @@ static int test_exp_mod_zero()
BN_zero(&p);
BN_init(&r);
- BN_mod_exp(&r, &a, &p, &m, ctx);
- BN_CTX_free(ctx);
- if (BN_is_zero(&r))
- ret = 0;
- else {
- printf("1**0 mod 1 = ");
- BN_print_fp(stdout, &r);
- printf(", should be 0\n");
+ if (!BN_rand(&a, 1024, 0, 0))
+ goto err;
+
+ if (!BN_mod_exp(&r, &a, &p, &m, ctx))
+ goto err;
+
+ if (!a_is_zero_mod_one("BN_mod_exp", &r, &a))
+ failed = 1;
+
+ if (!BN_mod_exp_recp(&r, &a, &p, &m, ctx))
+ goto err;
+
+ if (!a_is_zero_mod_one("BN_mod_exp_recp", &r, &a))
+ failed = 1;
+
+ if (!BN_mod_exp_simple(&r, &a, &p, &m, ctx))
+ goto err;
+
+ if (!a_is_zero_mod_one("BN_mod_exp_simple", &r, &a))
+ failed = 1;
+
+ if (!BN_mod_exp_mont(&r, &a, &p, &m, ctx, NULL))
+ goto err;
+
+ if (!a_is_zero_mod_one("BN_mod_exp_mont", &r, &a))
+ failed = 1;
+
+ if (!BN_mod_exp_mont_consttime(&r, &a, &p, &m, ctx, NULL)) {
+ goto err;
+ }
+
+ if (!a_is_zero_mod_one("BN_mod_exp_mont_consttime", &r, &a))
+ failed = 1;
+
+ /*
+ * A different codepath exists for single word multiplication
+ * in non-constant-time only.
+ */
+ if (!BN_mod_exp_mont_word(&r, one_word, &p, &m, ctx, NULL))
+ goto err;
+
+ if (!BN_is_zero(&r)) {
+ fprintf(stderr, "BN_mod_exp_mont_word failed:\n");
+ fprintf(stderr, "1 ** 0 mod 1 = r (should be 0)\n");
+ fprintf(stderr, "r = ");
+ BN_print_fp(stderr, &r);
+ fprintf(stderr, "\n");
+ return 0;
}
+ ret = failed;
+
+ err:
BN_free(&r);
BN_free(&a);
BN_free(&p);
BN_free(&m);
+ BN_CTX_free(ctx);
return ret;
}
diff --git a/crypto/openssl/crypto/camellia/camellia.c b/crypto/openssl/crypto/camellia/camellia.c
index b4a6766c623c..719fa61cf627 100644
--- a/crypto/openssl/crypto/camellia/camellia.c
+++ b/crypto/openssl/crypto/camellia/camellia.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia.c */
/* ====================================================================
* Copyright 2006 NTT (Nippon Telegraph and Telephone Corporation) .
* ALL RIGHTS RESERVED.
@@ -67,7 +67,7 @@
/*
* Algorithm Specification
- * http://info.isl.llia/specicrypt/eng/camellia/specifications.html
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
*/
/*
diff --git a/crypto/openssl/crypto/camellia/camellia.h b/crypto/openssl/crypto/camellia/camellia.h
index 9be7c0fd9996..45e8d25b1dd5 100644
--- a/crypto/openssl/crypto/camellia/camellia.h
+++ b/crypto/openssl/crypto/camellia/camellia.h
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia.h */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/camellia/cmll_cbc.c b/crypto/openssl/crypto/camellia/cmll_cbc.c
index a4907ca05f78..4017e00d9272 100644
--- a/crypto/openssl/crypto/camellia/cmll_cbc.c
+++ b/crypto/openssl/crypto/camellia/cmll_cbc.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia_cbc.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia_cbc.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/camellia/cmll_cfb.c b/crypto/openssl/crypto/camellia/cmll_cfb.c
index 59b85225c35e..78f2ae4566b1 100644
--- a/crypto/openssl/crypto/camellia/cmll_cfb.c
+++ b/crypto/openssl/crypto/camellia/cmll_cfb.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia_cfb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia_cfb.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/camellia/cmll_ctr.c b/crypto/openssl/crypto/camellia/cmll_ctr.c
index b8f523d44648..95e26621b7d8 100644
--- a/crypto/openssl/crypto/camellia/cmll_ctr.c
+++ b/crypto/openssl/crypto/camellia/cmll_ctr.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia_ctr.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia_ctr.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/camellia/cmll_ecb.c b/crypto/openssl/crypto/camellia/cmll_ecb.c
index 16f1af86ac38..b030791b275c 100644
--- a/crypto/openssl/crypto/camellia/cmll_ecb.c
+++ b/crypto/openssl/crypto/camellia/cmll_ecb.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia_ecb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia_ecb.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/camellia/cmll_locl.h b/crypto/openssl/crypto/camellia/cmll_locl.h
index 4e4707b6213e..2bd79b8c4eb3 100644
--- a/crypto/openssl/crypto/camellia/cmll_locl.h
+++ b/crypto/openssl/crypto/camellia/cmll_locl.h
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia_locl.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia_locl.h */
/* ====================================================================
* Copyright 2006 NTT (Nippon Telegraph and Telephone Corporation) .
* ALL RIGHTS RESERVED.
diff --git a/crypto/openssl/crypto/camellia/cmll_misc.c b/crypto/openssl/crypto/camellia/cmll_misc.c
index cbd250227bec..694d2fac8f1f 100644
--- a/crypto/openssl/crypto/camellia/cmll_misc.c
+++ b/crypto/openssl/crypto/camellia/cmll_misc.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia_misc.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia_misc.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/camellia/cmll_ofb.c b/crypto/openssl/crypto/camellia/cmll_ofb.c
index 46c3ae2af737..85eb8921568f 100644
--- a/crypto/openssl/crypto/camellia/cmll_ofb.c
+++ b/crypto/openssl/crypto/camellia/cmll_ofb.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/camellia_ofb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/camellia_ofb.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/camellia/cmll_utl.c b/crypto/openssl/crypto/camellia/cmll_utl.c
index d19ee19317ce..d5eb6b4d68b1 100644
--- a/crypto/openssl/crypto/camellia/cmll_utl.c
+++ b/crypto/openssl/crypto/camellia/cmll_utl.c
@@ -1,4 +1,4 @@
-/* crypto/camellia/cmll_utl.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/camellia/cmll_utl.c */
/* ====================================================================
* Copyright (c) 2011 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/des/des_old.c b/crypto/openssl/crypto/des/des_old.c
index 54b0968e663b..c5c5a00f00c1 100644
--- a/crypto/openssl/crypto/des/des_old.c
+++ b/crypto/openssl/crypto/des/des_old.c
@@ -1,4 +1,4 @@
-/* crypto/des/des_old.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/des/des_old.c */
/*-
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
diff --git a/crypto/openssl/crypto/des/des_old.h b/crypto/openssl/crypto/des/des_old.h
index f1e1e2cb09cf..ee7607a2415f 100644
--- a/crypto/openssl/crypto/des/des_old.h
+++ b/crypto/openssl/crypto/des/des_old.h
@@ -1,4 +1,4 @@
-/* crypto/des/des_old.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/des/des_old.h */
/*-
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
diff --git a/crypto/openssl/crypto/des/des_old2.c b/crypto/openssl/crypto/des/des_old2.c
index f7d28a671355..247ff8dcf85f 100644
--- a/crypto/openssl/crypto/des/des_old2.c
+++ b/crypto/openssl/crypto/des/des_old2.c
@@ -1,4 +1,4 @@
-/* crypto/des/des_old.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/des/des_old.c */
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING The
diff --git a/crypto/openssl/crypto/dh/dh.h b/crypto/openssl/crypto/dh/dh.h
index b17767328183..5498a9dc1060 100644
--- a/crypto/openssl/crypto/dh/dh.h
+++ b/crypto/openssl/crypto/dh/dh.h
@@ -174,6 +174,7 @@ struct dh_st {
/* DH_check_pub_key error codes */
# define DH_CHECK_PUBKEY_TOO_SMALL 0x01
# define DH_CHECK_PUBKEY_TOO_LARGE 0x02
+# define DH_CHECK_PUBKEY_INVALID 0x03
/*
* primes p where (p-1)/2 is prime too are called "safe"; we define this for
diff --git a/crypto/openssl/crypto/dh/dh_check.c b/crypto/openssl/crypto/dh/dh_check.c
index 347467c6a433..5adedc0d264e 100644
--- a/crypto/openssl/crypto/dh/dh_check.c
+++ b/crypto/openssl/crypto/dh/dh_check.c
@@ -151,23 +151,38 @@ int DH_check(const DH *dh, int *ret)
int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
{
int ok = 0;
- BIGNUM *q = NULL;
+ BIGNUM *tmp = NULL;
+ BN_CTX *ctx = NULL;
*ret = 0;
- q = BN_new();
- if (q == NULL)
+ ctx = BN_CTX_new();
+ if (ctx == NULL)
goto err;
- BN_set_word(q, 1);
- if (BN_cmp(pub_key, q) <= 0)
+ BN_CTX_start(ctx);
+ tmp = BN_CTX_get(ctx);
+ if (tmp == NULL)
+ goto err;
+ BN_set_word(tmp, 1);
+ if (BN_cmp(pub_key, tmp) <= 0)
*ret |= DH_CHECK_PUBKEY_TOO_SMALL;
- BN_copy(q, dh->p);
- BN_sub_word(q, 1);
- if (BN_cmp(pub_key, q) >= 0)
+ BN_copy(tmp, dh->p);
+ BN_sub_word(tmp, 1);
+ if (BN_cmp(pub_key, tmp) >= 0)
*ret |= DH_CHECK_PUBKEY_TOO_LARGE;
+ if (dh->q != NULL) {
+ /* Check pub_key^q == 1 mod p */
+ if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx))
+ goto err;
+ if (!BN_is_one(tmp))
+ *ret |= DH_CHECK_PUBKEY_INVALID;
+ }
+
ok = 1;
err:
- if (q != NULL)
- BN_free(q);
+ if (ctx != NULL) {
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ }
return (ok);
}
diff --git a/crypto/openssl/crypto/dh/dhtest.c b/crypto/openssl/crypto/dh/dhtest.c
index 6fe8ff4c0c49..c5d3d87ea549 100644
--- a/crypto/openssl/crypto/dh/dhtest.c
+++ b/crypto/openssl/crypto/dh/dhtest.c
@@ -471,6 +471,31 @@ static const unsigned char dhtest_2048_256_Z[] = {
0xC2, 0x6C, 0x5D, 0x7C
};
+static const unsigned char dhtest_rfc5114_2048_224_bad_y[] = {
+ 0x45, 0x32, 0x5F, 0x51, 0x07, 0xE5, 0xDF, 0x1C, 0xD6, 0x02, 0x82, 0xB3,
+ 0x32, 0x8F, 0xA4, 0x0F, 0x87, 0xB8, 0x41, 0xFE, 0xB9, 0x35, 0xDE, 0xAD,
+ 0xC6, 0x26, 0x85, 0xB4, 0xFF, 0x94, 0x8C, 0x12, 0x4C, 0xBF, 0x5B, 0x20,
+ 0xC4, 0x46, 0xA3, 0x26, 0xEB, 0xA4, 0x25, 0xB7, 0x68, 0x8E, 0xCC, 0x67,
+ 0xBA, 0xEA, 0x58, 0xD0, 0xF2, 0xE9, 0xD2, 0x24, 0x72, 0x60, 0xDA, 0x88,
+ 0x18, 0x9C, 0xE0, 0x31, 0x6A, 0xAD, 0x50, 0x6D, 0x94, 0x35, 0x8B, 0x83,
+ 0x4A, 0x6E, 0xFA, 0x48, 0x73, 0x0F, 0x83, 0x87, 0xFF, 0x6B, 0x66, 0x1F,
+ 0xA8, 0x82, 0xC6, 0x01, 0xE5, 0x80, 0xB5, 0xB0, 0x52, 0xD0, 0xE9, 0xD8,
+ 0x72, 0xF9, 0x7D, 0x5B, 0x8B, 0xA5, 0x4C, 0xA5, 0x25, 0x95, 0x74, 0xE2,
+ 0x7A, 0x61, 0x4E, 0xA7, 0x8F, 0x12, 0xE2, 0xD2, 0x9D, 0x8C, 0x02, 0x70,
+ 0x34, 0x44, 0x32, 0xC7, 0xB2, 0xF3, 0xB9, 0xFE, 0x17, 0x2B, 0xD6, 0x1F,
+ 0x8B, 0x7E, 0x4A, 0xFA, 0xA3, 0xB5, 0x3E, 0x7A, 0x81, 0x9A, 0x33, 0x66,
+ 0x62, 0xA4, 0x50, 0x18, 0x3E, 0xA2, 0x5F, 0x00, 0x07, 0xD8, 0x9B, 0x22,
+ 0xE4, 0xEC, 0x84, 0xD5, 0xEB, 0x5A, 0xF3, 0x2A, 0x31, 0x23, 0xD8, 0x44,
+ 0x22, 0x2A, 0x8B, 0x37, 0x44, 0xCC, 0xC6, 0x87, 0x4B, 0xBE, 0x50, 0x9D,
+ 0x4A, 0xC4, 0x8E, 0x45, 0xCF, 0x72, 0x4D, 0xC0, 0x89, 0xB3, 0x72, 0xED,
+ 0x33, 0x2C, 0xBC, 0x7F, 0x16, 0x39, 0x3B, 0xEB, 0xD2, 0xDD, 0xA8, 0x01,
+ 0x73, 0x84, 0x62, 0xB9, 0x29, 0xD2, 0xC9, 0x51, 0x32, 0x9E, 0x7A, 0x6A,
+ 0xCF, 0xC1, 0x0A, 0xDB, 0x0E, 0xE0, 0x62, 0x77, 0x6F, 0x59, 0x62, 0x72,
+ 0x5A, 0x69, 0xA6, 0x5B, 0x70, 0xCA, 0x65, 0xC4, 0x95, 0x6F, 0x9A, 0xC2,
+ 0xDF, 0x72, 0x6D, 0xB1, 0x1E, 0x54, 0x7B, 0x51, 0xB4, 0xEF, 0x7F, 0x89,
+ 0x93, 0x74, 0x89, 0x59
+};
+
typedef struct {
DH *(*get_param) (void);
const unsigned char *xA;
@@ -503,10 +528,15 @@ static const rfc5114_td rfctd[] = {
static int run_rfc5114_tests(void)
{
int i;
+ DH *dhA = NULL;
+ DH *dhB = NULL;
+ unsigned char *Z1 = NULL;
+ unsigned char *Z2 = NULL;
+ const rfc5114_td *td = NULL;
+ BIGNUM *bady = NULL;
+
for (i = 0; i < (int)(sizeof(rfctd) / sizeof(rfc5114_td)); i++) {
- DH *dhA, *dhB;
- unsigned char *Z1 = NULL, *Z2 = NULL;
- const rfc5114_td *td = rfctd + i;
+ td = rfctd + i;
/* Set up DH structures setting key components */
dhA = td->get_param();
dhB = td->get_param();
@@ -549,14 +579,63 @@ static int run_rfc5114_tests(void)
DH_free(dhB);
OPENSSL_free(Z1);
OPENSSL_free(Z2);
+ dhA = NULL;
+ dhB = NULL;
+ Z1 = NULL;
+ Z2 = NULL;
+ }
+ /* Now i == OSSL_NELEM(rfctd) */
+ /* RFC5114 uses unsafe primes, so now test an invalid y value */
+ dhA = DH_get_2048_224();
+ if (dhA == NULL)
+ goto bad_err;
+ Z1 = OPENSSL_malloc(DH_size(dhA));
+ if (Z1 == NULL)
+ goto bad_err;
+
+ bady = BN_bin2bn(dhtest_rfc5114_2048_224_bad_y,
+ sizeof(dhtest_rfc5114_2048_224_bad_y), NULL);
+ if (bady == NULL)
+ goto bad_err;
+
+ if (!DH_generate_key(dhA))
+ goto bad_err;
+
+ if (DH_compute_key(Z1, bady, dhA) != -1) {
+ /*
+ * DH_compute_key should fail with -1. If we get here we unexpectedly
+ * allowed an invalid y value
+ */
+ goto err;
}
+ /* We'll have a stale error on the queue from the above test so clear it */
+ ERR_clear_error();
+
+ printf("RFC5114 parameter test %d OK\n", i + 1);
+
+ BN_free(bady);
+ DH_free(dhA);
+ OPENSSL_free(Z1);
+
return 1;
bad_err:
+ BN_free(bady);
+ DH_free(dhA);
+ DH_free(dhB);
+ OPENSSL_free(Z1);
+ OPENSSL_free(Z2);
+
fprintf(stderr, "Initalisation error RFC5114 set %d\n", i + 1);
ERR_print_errors_fp(stderr);
return 0;
err:
+ BN_free(bady);
+ DH_free(dhA);
+ DH_free(dhB);
+ OPENSSL_free(Z1);
+ OPENSSL_free(Z2);
+
fprintf(stderr, "Test failed RFC5114 set %d\n", i + 1);
return 0;
}
diff --git a/crypto/openssl/crypto/dsa/dsa_ossl.c b/crypto/openssl/crypto/dsa/dsa_ossl.c
index f0ec8faa84cc..efc4f1b6aeba 100644
--- a/crypto/openssl/crypto/dsa/dsa_ossl.c
+++ b/crypto/openssl/crypto/dsa/dsa_ossl.c
@@ -187,9 +187,6 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
if (!BN_mod_mul(s, s, kinv, dsa->q, ctx))
goto err;
- ret = DSA_SIG_new();
- if (ret == NULL)
- goto err;
/*
* Redo if r or s is zero as required by FIPS 186-3: this is very
* unlikely.
@@ -201,11 +198,14 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
}
goto redo;
}
+ ret = DSA_SIG_new();
+ if (ret == NULL)
+ goto err;
ret->r = r;
ret->s = s;
err:
- if (!ret) {
+ if (ret == NULL) {
DSAerr(DSA_F_DSA_DO_SIGN, reason);
BN_free(r);
BN_free(s);
diff --git a/crypto/openssl/crypto/dso/dso.h b/crypto/openssl/crypto/dso/dso.h
index 7c4a1dc4a620..c9013f5cea8b 100644
--- a/crypto/openssl/crypto/dso/dso.h
+++ b/crypto/openssl/crypto/dso/dso.h
@@ -1,4 +1,4 @@
-/* dso.h -*- mode:C; c-file-style: "eay" -*- */
+/* dso.h */
/*
* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
* 2000.
diff --git a/crypto/openssl/crypto/dso/dso_dl.c b/crypto/openssl/crypto/dso/dso_dl.c
index 0087ac54afe1..ceedf66e8856 100644
--- a/crypto/openssl/crypto/dso/dso_dl.c
+++ b/crypto/openssl/crypto/dso/dso_dl.c
@@ -1,4 +1,4 @@
-/* dso_dl.c -*- mode:C; c-file-style: "eay" -*- */
+/* dso_dl.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2000.
diff --git a/crypto/openssl/crypto/dso/dso_dlfcn.c b/crypto/openssl/crypto/dso/dso_dlfcn.c
index f629f0380d8c..78df723ffbae 100644
--- a/crypto/openssl/crypto/dso/dso_dlfcn.c
+++ b/crypto/openssl/crypto/dso/dso_dlfcn.c
@@ -1,4 +1,4 @@
-/* dso_dlfcn.c -*- mode:C; c-file-style: "eay" -*- */
+/* dso_dlfcn.c */
/*
* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
* 2000.
diff --git a/crypto/openssl/crypto/dso/dso_lib.c b/crypto/openssl/crypto/dso/dso_lib.c
index 09b8eafccacc..3312450eae67 100644
--- a/crypto/openssl/crypto/dso/dso_lib.c
+++ b/crypto/openssl/crypto/dso/dso_lib.c
@@ -1,4 +1,4 @@
-/* dso_lib.c -*- mode:C; c-file-style: "eay" -*- */
+/* dso_lib.c */
/*
* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
* 2000.
diff --git a/crypto/openssl/crypto/ec/asm/ecp_nistz256-x86_64.pl b/crypto/openssl/crypto/ec/asm/ecp_nistz256-x86_64.pl
index 648c969be621..e6acfd59f0d4 100755
--- a/crypto/openssl/crypto/ec/asm/ecp_nistz256-x86_64.pl
+++ b/crypto/openssl/crypto/ec/asm/ecp_nistz256-x86_64.pl
@@ -81,7 +81,7 @@ if (!$addx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
$addx = ($1>=12);
}
-if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9])\.([0-9]+)/) {
+if (!$addx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9])\.([0-9]+)/) {
my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10
$avx = ($ver>=3.0) + ($ver>=3.01);
$addx = ($ver>=3.03);
diff --git a/crypto/openssl/crypto/ec/ec2_smpl.c b/crypto/openssl/crypto/ec/ec2_smpl.c
index 077c7fc8dda5..5b27b91fcc94 100644
--- a/crypto/openssl/crypto/ec/ec2_smpl.c
+++ b/crypto/openssl/crypto/ec/ec2_smpl.c
@@ -746,6 +746,7 @@ int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
goto err;
if (!BN_one(&point->Z))
goto err;
+ point->Z_is_one = 1;
ret = 1;
diff --git a/crypto/openssl/crypto/ec/ec_key.c b/crypto/openssl/crypto/ec/ec_key.c
index c784b6fd30a3..bc94ab5661ff 100644
--- a/crypto/openssl/crypto/ec/ec_key.c
+++ b/crypto/openssl/crypto/ec/ec_key.c
@@ -387,6 +387,8 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
tx = BN_CTX_get(ctx);
ty = BN_CTX_get(ctx);
+ if (ty == NULL)
+ goto err;
#ifndef OPENSSL_NO_EC2M
tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group));
diff --git a/crypto/openssl/crypto/ec/ecp_nistz256_table.c b/crypto/openssl/crypto/ec/ecp_nistz256_table.c
index 216d024e0120..2f0797db6b9b 100644
--- a/crypto/openssl/crypto/ec/ecp_nistz256_table.c
+++ b/crypto/openssl/crypto/ec/ecp_nistz256_table.c
@@ -17,7 +17,7 @@ __attribute((aligned(4096)))
#elif defined(_MSC_VER)
__declspec(align(4096))
#elif defined(__SUNPRO_C)
-# pragma align 4096(ecp_nistz256_precomputed)
+# pragma align 64(ecp_nistz256_precomputed)
#endif
static const BN_ULONG ecp_nistz256_precomputed[37][64 *
sizeof(P256_POINT_AFFINE) /
diff --git a/crypto/openssl/crypto/ec/ectest.c b/crypto/openssl/crypto/ec/ectest.c
index fede530bc139..efab0b07b1d2 100644
--- a/crypto/openssl/crypto/ec/ectest.c
+++ b/crypto/openssl/crypto/ec/ectest.c
@@ -1591,7 +1591,7 @@ struct nistp_test_params {
int degree;
/*
* Qx, Qy and D are taken from
- * http://csrcdocut.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf
* Otherwise, values are standard curve parameters from FIPS 180-3
*/
const char *p, *a, *b, *Qx, *Qy, *Gx, *Gy, *order, *d;
diff --git a/crypto/openssl/crypto/engine/eng_all.c b/crypto/openssl/crypto/engine/eng_all.c
index 195a3a95542a..48ad0d26b41e 100644
--- a/crypto/openssl/crypto/engine/eng_all.c
+++ b/crypto/openssl/crypto/engine/eng_all.c
@@ -1,4 +1,4 @@
-/* crypto/engine/eng_all.c -*- mode: C; c-file-style: "eay" -*- */
+/* crypto/engine/eng_all.c */
/*
* Written by Richard Levitte <richard@levitte.org> for the OpenSSL project
* 2000.
diff --git a/crypto/openssl/crypto/evp/e_camellia.c b/crypto/openssl/crypto/evp/e_camellia.c
index f9c84013675d..f273f9c9475a 100644
--- a/crypto/openssl/crypto/evp/e_camellia.c
+++ b/crypto/openssl/crypto/evp/e_camellia.c
@@ -1,4 +1,4 @@
-/* crypto/evp/e_camellia.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/evp/e_camellia.c */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/evp/e_old.c b/crypto/openssl/crypto/evp/e_old.c
index c93f5a548163..a23d143b7fae 100644
--- a/crypto/openssl/crypto/evp/e_old.c
+++ b/crypto/openssl/crypto/evp/e_old.c
@@ -1,4 +1,4 @@
-/* crypto/evp/e_old.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/evp/e_old.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2004.
diff --git a/crypto/openssl/crypto/evp/e_seed.c b/crypto/openssl/crypto/evp/e_seed.c
index c948a8f3914f..7249d1b1eecb 100644
--- a/crypto/openssl/crypto/evp/e_seed.c
+++ b/crypto/openssl/crypto/evp/e_seed.c
@@ -1,4 +1,4 @@
-/* crypto/evp/e_seed.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/evp/e_seed.c */
/* ====================================================================
* Copyright (c) 2007 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/mem_clr.c b/crypto/openssl/crypto/mem_clr.c
index 1a06636d0ce8..ab85344eef38 100644
--- a/crypto/openssl/crypto/mem_clr.c
+++ b/crypto/openssl/crypto/mem_clr.c
@@ -1,4 +1,4 @@
-/* crypto/mem_clr.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/mem_clr.c */
/*
* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
* 2002.
diff --git a/crypto/openssl/crypto/modes/asm/aesni-gcm-x86_64.pl b/crypto/openssl/crypto/modes/asm/aesni-gcm-x86_64.pl
index 4be25571ea28..bd6bf72fe487 100755
--- a/crypto/openssl/crypto/modes/asm/aesni-gcm-x86_64.pl
+++ b/crypto/openssl/crypto/modes/asm/aesni-gcm-x86_64.pl
@@ -56,7 +56,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
$avx = ($1>=10) + ($1>=11);
}
-if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) {
+if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) {
$avx = ($2>=3.0) + ($2>3.0);
}
diff --git a/crypto/openssl/crypto/modes/asm/ghash-x86_64.pl b/crypto/openssl/crypto/modes/asm/ghash-x86_64.pl
index 0bcb6d4e028b..4ff2d39aa7b2 100755
--- a/crypto/openssl/crypto/modes/asm/ghash-x86_64.pl
+++ b/crypto/openssl/crypto/modes/asm/ghash-x86_64.pl
@@ -105,7 +105,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
$avx = ($1>=10) + ($1>=11);
}
-if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) {
+if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) {
$avx = ($2>=3.0) + ($2>3.0);
}
diff --git a/crypto/openssl/crypto/o_dir.c b/crypto/openssl/crypto/o_dir.c
index 26242444c885..f9dbed871127 100644
--- a/crypto/openssl/crypto/o_dir.c
+++ b/crypto/openssl/crypto/o_dir.c
@@ -1,4 +1,4 @@
-/* crypto/o_dir.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/o_dir.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2004.
diff --git a/crypto/openssl/crypto/o_dir.h b/crypto/openssl/crypto/o_dir.h
index d55431194ef2..bf45a14d02ec 100644
--- a/crypto/openssl/crypto/o_dir.h
+++ b/crypto/openssl/crypto/o_dir.h
@@ -1,4 +1,4 @@
-/* crypto/o_dir.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/o_dir.h */
/*
* Copied from Richard Levitte's (richard@levitte.org) LP library. All
* symbol names have been changed, with permission from the author.
diff --git a/crypto/openssl/crypto/o_dir_test.c b/crypto/openssl/crypto/o_dir_test.c
index 7cdbbbc403e7..60436b72ce37 100644
--- a/crypto/openssl/crypto/o_dir_test.c
+++ b/crypto/openssl/crypto/o_dir_test.c
@@ -1,4 +1,4 @@
-/* crypto/o_dir.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/o_dir.h */
/*
* Copied from Richard Levitte's (richard@levitte.org) LP library. All
* symbol names have been changed, with permission from the author.
diff --git a/crypto/openssl/crypto/o_str.c b/crypto/openssl/crypto/o_str.c
index 4e2d096704f0..7e61cde85a27 100644
--- a/crypto/openssl/crypto/o_str.c
+++ b/crypto/openssl/crypto/o_str.c
@@ -1,4 +1,4 @@
-/* crypto/o_str.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/o_str.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2003.
diff --git a/crypto/openssl/crypto/o_str.h b/crypto/openssl/crypto/o_str.h
index 5313528ed926..fa512eb39784 100644
--- a/crypto/openssl/crypto/o_str.h
+++ b/crypto/openssl/crypto/o_str.h
@@ -1,4 +1,4 @@
-/* crypto/o_str.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/o_str.h */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2003.
diff --git a/crypto/openssl/crypto/o_time.c b/crypto/openssl/crypto/o_time.c
index 58413fe97d09..635dae184d2f 100644
--- a/crypto/openssl/crypto/o_time.c
+++ b/crypto/openssl/crypto/o_time.c
@@ -1,4 +1,4 @@
-/* crypto/o_time.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/o_time.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2001.
diff --git a/crypto/openssl/crypto/o_time.h b/crypto/openssl/crypto/o_time.h
index a83a3d247d41..f192c6dccf37 100644
--- a/crypto/openssl/crypto/o_time.h
+++ b/crypto/openssl/crypto/o_time.h
@@ -1,4 +1,4 @@
-/* crypto/o_time.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/o_time.h */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2001.
diff --git a/crypto/openssl/crypto/opensslv.h b/crypto/openssl/crypto/opensslv.h
index 5b9d7183719b..b315d5ef97ee 100644
--- a/crypto/openssl/crypto/opensslv.h
+++ b/crypto/openssl/crypto/opensslv.h
@@ -30,11 +30,11 @@ extern "C" {
* (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
* major minor fix final patch/beta)
*/
-# define OPENSSL_VERSION_NUMBER 0x1000205fL
+# define OPENSSL_VERSION_NUMBER 0x1000206fL
# ifdef OPENSSL_FIPS
-# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2e-fips 3 Dec 2015"
+# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2f-fips 28 Jan 2016"
# else
-# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2e-freebsd 3 Dec 2015"
+# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2f-freebsd 28 Jan 2016"
# endif
# define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT
diff --git a/crypto/openssl/crypto/rc4/rc4_utl.c b/crypto/openssl/crypto/rc4/rc4_utl.c
index 7c6a15f1c71f..cbd4a24e4b4d 100644
--- a/crypto/openssl/crypto/rc4/rc4_utl.c
+++ b/crypto/openssl/crypto/rc4/rc4_utl.c
@@ -1,4 +1,4 @@
-/* crypto/rc4/rc4_utl.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/rc4/rc4_utl.c */
/* ====================================================================
* Copyright (c) 2011 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/rsa/rsa_chk.c b/crypto/openssl/crypto/rsa/rsa_chk.c
index f4383860b58b..607faa00171e 100644
--- a/crypto/openssl/crypto/rsa/rsa_chk.c
+++ b/crypto/openssl/crypto/rsa/rsa_chk.c
@@ -1,4 +1,4 @@
-/* crypto/rsa/rsa_chk.c -*- Mode: C; c-file-style: "eay" -*- */
+/* crypto/rsa/rsa_chk.c */
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/rsa/rsa_sign.c b/crypto/openssl/crypto/rsa/rsa_sign.c
index 82ca8324dfbc..ed63a1d8b0e3 100644
--- a/crypto/openssl/crypto/rsa/rsa_sign.c
+++ b/crypto/openssl/crypto/rsa/rsa_sign.c
@@ -84,7 +84,7 @@ int RSA_sign(int type, const unsigned char *m, unsigned int m_len,
return 0;
}
#endif
- if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_sign) {
+ if (rsa->meth->rsa_sign) {
return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa);
}
/* Special case: SSL signature, just check the length */
@@ -293,7 +293,7 @@ int RSA_verify(int dtype, const unsigned char *m, unsigned int m_len,
const unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
{
- if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_verify) {
+ if (rsa->meth->rsa_verify) {
return rsa->meth->rsa_verify(dtype, m, m_len, sigbuf, siglen, rsa);
}
diff --git a/crypto/openssl/crypto/seed/seed_cbc.c b/crypto/openssl/crypto/seed/seed_cbc.c
index 33e6887740e9..ee1115b4c113 100644
--- a/crypto/openssl/crypto/seed/seed_cbc.c
+++ b/crypto/openssl/crypto/seed/seed_cbc.c
@@ -1,4 +1,4 @@
-/* crypto/seed/seed_cbc.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/seed/seed_cbc.c */
/* ====================================================================
* Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/seed/seed_cfb.c b/crypto/openssl/crypto/seed/seed_cfb.c
index 3437d7b4e111..b6a5648b35fd 100644
--- a/crypto/openssl/crypto/seed/seed_cfb.c
+++ b/crypto/openssl/crypto/seed/seed_cfb.c
@@ -1,4 +1,4 @@
-/* crypto/seed/seed_cfb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/seed/seed_cfb.c */
/* ====================================================================
* Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/seed/seed_ecb.c b/crypto/openssl/crypto/seed/seed_ecb.c
index 937a31b42a87..9363d5508044 100644
--- a/crypto/openssl/crypto/seed/seed_ecb.c
+++ b/crypto/openssl/crypto/seed/seed_ecb.c
@@ -1,4 +1,4 @@
-/* crypto/seed/seed_ecb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/seed/seed_ecb.c */
/* ====================================================================
* Copyright (c) 2007 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/seed/seed_ofb.c b/crypto/openssl/crypto/seed/seed_ofb.c
index 6974302ce80f..48b71224c52c 100644
--- a/crypto/openssl/crypto/seed/seed_ofb.c
+++ b/crypto/openssl/crypto/seed/seed_ofb.c
@@ -1,4 +1,4 @@
-/* crypto/seed/seed_ofb.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/seed/seed_ofb.c */
/* ====================================================================
* Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/sha/asm/sha1-mb-x86_64.pl b/crypto/openssl/crypto/sha/asm/sha1-mb-x86_64.pl
index f856bb888b0e..a8d8708d4b75 100755
--- a/crypto/openssl/crypto/sha/asm/sha1-mb-x86_64.pl
+++ b/crypto/openssl/crypto/sha/asm/sha1-mb-x86_64.pl
@@ -58,7 +58,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
$avx = ($1>=10) + ($1>=11);
}
-if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) {
+if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) {
$avx = ($2>=3.0) + ($2>3.0);
}
diff --git a/crypto/openssl/crypto/sha/asm/sha1-x86_64.pl b/crypto/openssl/crypto/sha/asm/sha1-x86_64.pl
index 9a6acc347d33..5f375fc6886b 100755
--- a/crypto/openssl/crypto/sha/asm/sha1-x86_64.pl
+++ b/crypto/openssl/crypto/sha/asm/sha1-x86_64.pl
@@ -107,7 +107,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
$avx = ($1>=10) + ($1>=11);
}
-if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([2-9]\.[0-9]+)/) {
+if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([2-9]\.[0-9]+)/) {
$avx = ($2>=3.0) + ($2>3.0);
}
diff --git a/crypto/openssl/crypto/sha/asm/sha256-mb-x86_64.pl b/crypto/openssl/crypto/sha/asm/sha256-mb-x86_64.pl
index 3d37ae31ad3e..9770286b9596 100755
--- a/crypto/openssl/crypto/sha/asm/sha256-mb-x86_64.pl
+++ b/crypto/openssl/crypto/sha/asm/sha256-mb-x86_64.pl
@@ -59,7 +59,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
$avx = ($1>=10) + ($1>=11);
}
-if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) {
+if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) {
$avx = ($2>=3.0) + ($2>3.0);
}
diff --git a/crypto/openssl/crypto/sha/asm/sha512-x86_64.pl b/crypto/openssl/crypto/sha/asm/sha512-x86_64.pl
index 58665667f149..78e445f3fe4a 100755
--- a/crypto/openssl/crypto/sha/asm/sha512-x86_64.pl
+++ b/crypto/openssl/crypto/sha/asm/sha512-x86_64.pl
@@ -124,7 +124,7 @@ if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
$avx = ($1>=10) + ($1>=11);
}
-if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|based on LLVM) ([3-9]\.[0-9]+)/) {
+if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) {
$avx = ($2>=3.0) + ($2>3.0);
}
diff --git a/crypto/openssl/crypto/sha/sha1test.c b/crypto/openssl/crypto/sha/sha1test.c
index 0052a95c7dd4..551a348df37f 100644
--- a/crypto/openssl/crypto/sha/sha1test.c
+++ b/crypto/openssl/crypto/sha/sha1test.c
@@ -157,8 +157,8 @@ int main(int argc, char *argv[])
if (err)
printf("ERROR: %d\n", err);
# endif
- EXIT(err);
EVP_MD_CTX_cleanup(&c);
+ EXIT(err);
return (0);
}
diff --git a/crypto/openssl/crypto/store/store.h b/crypto/openssl/crypto/store/store.h
index 834334104907..ce3709d9f00b 100644
--- a/crypto/openssl/crypto/store/store.h
+++ b/crypto/openssl/crypto/store/store.h
@@ -1,4 +1,4 @@
-/* crypto/store/store.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/store/store.h */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2003.
diff --git a/crypto/openssl/crypto/store/str_lib.c b/crypto/openssl/crypto/store/str_lib.c
index 227b797b5949..e3d5da938868 100644
--- a/crypto/openssl/crypto/store/str_lib.c
+++ b/crypto/openssl/crypto/store/str_lib.c
@@ -1,4 +1,4 @@
-/* crypto/store/str_lib.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/store/str_lib.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2003.
diff --git a/crypto/openssl/crypto/store/str_locl.h b/crypto/openssl/crypto/store/str_locl.h
index ac55784df0aa..c0b40f0db674 100644
--- a/crypto/openssl/crypto/store/str_locl.h
+++ b/crypto/openssl/crypto/store/str_locl.h
@@ -1,4 +1,4 @@
-/* crypto/store/str_locl.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/store/str_locl.h */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2003.
diff --git a/crypto/openssl/crypto/store/str_mem.c b/crypto/openssl/crypto/store/str_mem.c
index 8edd0eb41b12..6eee5bba2922 100644
--- a/crypto/openssl/crypto/store/str_mem.c
+++ b/crypto/openssl/crypto/store/str_mem.c
@@ -1,4 +1,4 @@
-/* crypto/store/str_mem.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/store/str_mem.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2003.
diff --git a/crypto/openssl/crypto/store/str_meth.c b/crypto/openssl/crypto/store/str_meth.c
index d83a6de0fc47..c83fbc565aac 100644
--- a/crypto/openssl/crypto/store/str_meth.c
+++ b/crypto/openssl/crypto/store/str_meth.c
@@ -1,4 +1,4 @@
-/* crypto/store/str_meth.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/store/str_meth.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2003.
diff --git a/crypto/openssl/crypto/ts/ts_rsp_verify.c b/crypto/openssl/crypto/ts/ts_rsp_verify.c
index da8991173ced..29aa5a497e89 100644
--- a/crypto/openssl/crypto/ts/ts_rsp_verify.c
+++ b/crypto/openssl/crypto/ts/ts_rsp_verify.c
@@ -255,7 +255,8 @@ static int TS_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted,
/* chain is an out argument. */
*chain = NULL;
- X509_STORE_CTX_init(&cert_ctx, store, signer, untrusted);
+ if (!X509_STORE_CTX_init(&cert_ctx, store, signer, untrusted))
+ return 0;
X509_STORE_CTX_set_purpose(&cert_ctx, X509_PURPOSE_TIMESTAMP_SIGN);
i = X509_verify_cert(&cert_ctx);
if (i <= 0) {
diff --git a/crypto/openssl/crypto/ui/ui.h b/crypto/openssl/crypto/ui/ui.h
index b917edab3a7a..0dc16330b870 100644
--- a/crypto/openssl/crypto/ui/ui.h
+++ b/crypto/openssl/crypto/ui/ui.h
@@ -1,4 +1,4 @@
-/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/ui/ui.h */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2001.
diff --git a/crypto/openssl/crypto/ui/ui_compat.c b/crypto/openssl/crypto/ui/ui_compat.c
index 0ca5284f91c0..e79d54eea682 100644
--- a/crypto/openssl/crypto/ui/ui_compat.c
+++ b/crypto/openssl/crypto/ui/ui_compat.c
@@ -1,4 +1,4 @@
-/* crypto/ui/ui_compat.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/ui/ui_compat.c */
/* ====================================================================
* Copyright (c) 2001-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/ui/ui_compat.h b/crypto/openssl/crypto/ui/ui_compat.h
index 42fb9ff6500f..bf541542c041 100644
--- a/crypto/openssl/crypto/ui/ui_compat.h
+++ b/crypto/openssl/crypto/ui/ui_compat.h
@@ -1,4 +1,4 @@
-/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/ui/ui.h */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2001.
diff --git a/crypto/openssl/crypto/ui/ui_lib.c b/crypto/openssl/crypto/ui/ui_lib.c
index 5ddd7317e52b..2f580352ce8f 100644
--- a/crypto/openssl/crypto/ui/ui_lib.c
+++ b/crypto/openssl/crypto/ui/ui_lib.c
@@ -1,4 +1,4 @@
-/* crypto/ui/ui_lib.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/ui/ui_lib.c */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2001.
diff --git a/crypto/openssl/crypto/ui/ui_locl.h b/crypto/openssl/crypto/ui/ui_locl.h
index 0d919cd7b1cc..bebc13abfc52 100644
--- a/crypto/openssl/crypto/ui/ui_locl.h
+++ b/crypto/openssl/crypto/ui/ui_locl.h
@@ -1,4 +1,4 @@
-/* crypto/ui/ui.h -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/ui/ui.h */
/*
* Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
* 2001.
diff --git a/crypto/openssl/crypto/ui/ui_openssl.c b/crypto/openssl/crypto/ui/ui_openssl.c
index 5d66276418fc..9ab259b8f605 100644
--- a/crypto/openssl/crypto/ui/ui_openssl.c
+++ b/crypto/openssl/crypto/ui/ui_openssl.c
@@ -1,4 +1,4 @@
-/* crypto/ui/ui_openssl.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/ui/ui_openssl.c */
/*
* Written by Richard Levitte (richard@levitte.org) and others for the
* OpenSSL project 2001.
diff --git a/crypto/openssl/crypto/ui/ui_util.c b/crypto/openssl/crypto/ui/ui_util.c
index f65f80d71de6..0f290115d0f8 100644
--- a/crypto/openssl/crypto/ui/ui_util.c
+++ b/crypto/openssl/crypto/ui/ui_util.c
@@ -1,4 +1,4 @@
-/* crypto/ui/ui_util.c -*- mode:C; c-file-style: "eay" -*- */
+/* crypto/ui/ui_util.c */
/* ====================================================================
* Copyright (c) 2001-2002 The OpenSSL Project. All rights reserved.
*
diff --git a/crypto/openssl/crypto/x509/x509_vfy.c b/crypto/openssl/crypto/x509/x509_vfy.c
index ab94948f0135..0429767032fd 100644
--- a/crypto/openssl/crypto/x509/x509_vfy.c
+++ b/crypto/openssl/crypto/x509/x509_vfy.c
@@ -2283,9 +2283,10 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
ctx->current_reasons = 0;
ctx->tree = NULL;
ctx->parent = NULL;
+ /* Zero ex_data to make sure we're cleanup-safe */
+ memset(&ctx->ex_data, 0, sizeof(ctx->ex_data));
ctx->param = X509_VERIFY_PARAM_new();
-
if (!ctx->param) {
X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE);
return 0;
@@ -2294,7 +2295,6 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
/*
* Inherit callbacks and flags from X509_STORE if not set use defaults.
*/
-
if (store)
ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
else
@@ -2302,6 +2302,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
if (store) {
ctx->verify_cb = store->verify_cb;
+ /* Seems to always be 0 in OpenSSL, else must be idempotent */
ctx->cleanup = store->cleanup;
} else
ctx->cleanup = 0;
@@ -2312,7 +2313,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
if (ret == 0) {
X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE);
- return 0;
+ goto err;
}
if (store && store->check_issued)
@@ -2367,19 +2368,18 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
ctx->check_policy = check_policy;
+ if (CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
+ &ctx->ex_data))
+ return 1;
+ X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE);
+
+ err:
/*
- * This memset() can't make any sense anyway, so it's removed. As
- * X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a
- * corresponding "new" here and remove this bogus initialisation.
+ * On error clean up allocated storage, if the store context was not
+ * allocated with X509_STORE_CTX_new() this is our last chance to do so.
*/
- /* memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); */
- if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
- &(ctx->ex_data))) {
- OPENSSL_free(ctx);
- X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- return 1;
+ X509_STORE_CTX_cleanup(ctx);
+ return 0;
}
/*
@@ -2395,8 +2395,17 @@ void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
{
- if (ctx->cleanup)
+ /*
+ * We need to be idempotent because, unfortunately, free() also calls
+ * cleanup(), so the natural call sequence new(), init(), cleanup(), free()
+ * calls cleanup() for the same object twice! Thus we must zero the
+ * pointers below after they're freed!
+ */
+ /* Seems to always be 0 in OpenSSL, do this at most once. */
+ if (ctx->cleanup != NULL) {
ctx->cleanup(ctx);
+ ctx->cleanup = NULL;
+ }
if (ctx->param != NULL) {
if (ctx->parent == NULL)
X509_VERIFY_PARAM_free(ctx->param);
diff --git a/crypto/openssl/crypto/x509/x509_vfy.h b/crypto/openssl/crypto/x509/x509_vfy.h
index bd8613c62ba4..2663e1c0a362 100644
--- a/crypto/openssl/crypto/x509/x509_vfy.h
+++ b/crypto/openssl/crypto/x509/x509_vfy.h
@@ -313,7 +313,7 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL)
# define X509_V_OK 0
-/* illegal error (for uninitialized values, to avoid X509_V_OK): 1 */
+# define X509_V_ERR_UNSPECIFIED 1
# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2
# define X509_V_ERR_UNABLE_TO_GET_CRL 3
diff --git a/crypto/openssl/crypto/x509/x509_vpm.c b/crypto/openssl/crypto/x509/x509_vpm.c
index 592a8a5f6a5c..1ac15a881a10 100644
--- a/crypto/openssl/crypto/x509/x509_vpm.c
+++ b/crypto/openssl/crypto/x509/x509_vpm.c
@@ -94,11 +94,11 @@ static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode,
* Refuse names with embedded NUL bytes, except perhaps as final byte.
* XXX: Do we need to push an error onto the error stack?
*/
- if (namelen == 0)
+ if (namelen == 0 || name == NULL)
namelen = name ? strlen(name) : 0;
else if (name && memchr(name, '\0', namelen > 1 ? namelen - 1 : namelen))
return 0;
- if (name && name[namelen - 1] == '\0')
+ if (namelen > 0 && name[namelen - 1] == '\0')
--namelen;
if (mode == SET_HOST && id->hosts) {
diff --git a/crypto/openssl/crypto/x509v3/v3_pci.c b/crypto/openssl/crypto/x509v3/v3_pci.c
index 48ac0959cb10..34cad53cb5f0 100644
--- a/crypto/openssl/crypto/x509v3/v3_pci.c
+++ b/crypto/openssl/crypto/x509v3/v3_pci.c
@@ -1,4 +1,4 @@
-/* v3_pci.c -*- mode:C; c-file-style: "eay" -*- */
+/* v3_pci.c */
/*
* Contributed to the OpenSSL Project 2004 by Richard Levitte
* (richard@levitte.org)
diff --git a/crypto/openssl/crypto/x509v3/v3_pcia.c b/crypto/openssl/crypto/x509v3/v3_pcia.c
index 43fd362aeda0..e53c82e8dc79 100644
--- a/crypto/openssl/crypto/x509v3/v3_pcia.c
+++ b/crypto/openssl/crypto/x509v3/v3_pcia.c
@@ -1,4 +1,4 @@
-/* v3_pcia.c -*- mode:C; c-file-style: "eay" -*- */
+/* v3_pcia.c */
/*
* Contributed to the OpenSSL Project 2004 by Richard Levitte
* (richard@levitte.org)
diff --git a/crypto/openssl/crypto/x509v3/v3_utl.c b/crypto/openssl/crypto/x509v3/v3_utl.c
index 4d1ecc58bf94..43b9cb9c5861 100644
--- a/crypto/openssl/crypto/x509v3/v3_utl.c
+++ b/crypto/openssl/crypto/x509v3/v3_utl.c
@@ -841,7 +841,8 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len,
state = LABEL_START;
++dots;
} else if (p[i] == '-') {
- if ((state & LABEL_HYPHEN) != 0)
+ /* no domain/subdomain starts with '-' */
+ if ((state & LABEL_START) != 0)
return NULL;
state |= LABEL_HYPHEN;
} else
diff --git a/crypto/openssl/crypto/x509v3/v3nametest.c b/crypto/openssl/crypto/x509v3/v3nametest.c
index 7b5c1c8e5127..ac5c9ff432d9 100644
--- a/crypto/openssl/crypto/x509v3/v3nametest.c
+++ b/crypto/openssl/crypto/x509v3/v3nametest.c
@@ -6,12 +6,16 @@
static const char *const names[] = {
"a", "b", ".", "*", "@",
".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..",
+ "-example.com", "example-.com",
"@@", "**", "*.com", "*com", "*.*.com", "*com", "com*", "*example.com",
"*@example.com", "test@*.example.com", "example.com", "www.example.com",
"test.www.example.com", "*.example.com", "*.www.example.com",
"test.*.example.com", "www.*.com",
".www.example.com", "*www.example.com",
"example.net", "xn--rger-koa.example.com",
+ "*.xn--rger-koa.example.com", "www.xn--rger-koa.example.com",
+ "*.good--example.com", "www.good--example.com",
+ "*.xn--bar.com", "xn--foo.xn--bar.com",
"a.example.com", "b.example.com",
"postmaster@example.com", "Postmaster@example.com",
"postmaster@EXAMPLE.COM",
@@ -27,6 +31,9 @@ static const char *const exceptions[] = {
"set CN: host: [*.www.example.com] matches [.www.example.com]",
"set CN: host: [*www.example.com] matches [www.example.com]",
"set CN: host: [test.www.example.com] matches [.www.example.com]",
+ "set CN: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
+ "set CN: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
+ "set CN: host: [*.good--example.com] matches [www.good--example.com]",
"set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
"set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
"set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]",
@@ -43,6 +50,9 @@ static const char *const exceptions[] = {
"set dnsName: host: [*.www.example.com] matches [.www.example.com]",
"set dnsName: host: [*www.example.com] matches [www.example.com]",
"set dnsName: host: [test.www.example.com] matches [.www.example.com]",
+ "set dnsName: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
+ "set dnsName: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
+ "set dnsName: host: [*.good--example.com] matches [www.good--example.com]",
"set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]",
"set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]",
"set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
diff --git a/crypto/openssl/doc/apps/s_time.pod b/crypto/openssl/doc/apps/s_time.pod
index 5a38aa2e0394..9082d876feeb 100644
--- a/crypto/openssl/doc/apps/s_time.pod
+++ b/crypto/openssl/doc/apps/s_time.pod
@@ -26,7 +26,7 @@ B<openssl> B<s_time>
=head1 DESCRIPTION
-The B<s_client> command implements a generic SSL/TLS client which connects to a
+The B<s_time> command implements a generic SSL/TLS client which connects to a
remote host using SSL/TLS. It can request a page from the server and includes
the time to transfer the payload data in its timing measurements. It measures
the number of connections within a given timeframe, the amount of data
@@ -127,7 +127,7 @@ and the link speed determine how many connections B<s_time> can establish.
=head1 NOTES
-B<s_client> can be used to measure the performance of an SSL connection.
+B<s_time> can be used to measure the performance of an SSL connection.
To connect to an SSL HTTP server and get the default page the command
openssl s_time -connect servername:443 -www / -CApath yourdir -CAfile yourfile.pem -cipher commoncipher [-ssl3]
diff --git a/crypto/openssl/doc/crypto/BIO_s_connect.pod b/crypto/openssl/doc/crypto/BIO_s_connect.pod
index 18ece4c91f66..345a468a5d74 100644
--- a/crypto/openssl/doc/crypto/BIO_s_connect.pod
+++ b/crypto/openssl/doc/crypto/BIO_s_connect.pod
@@ -21,8 +21,8 @@ BIO_set_nbio, BIO_do_connect - connect BIO
long BIO_set_conn_int_port(BIO *b, char *port);
char *BIO_get_conn_hostname(BIO *b);
char *BIO_get_conn_port(BIO *b);
- char *BIO_get_conn_ip(BIO *b, dummy);
- long BIO_get_conn_int_port(BIO *b, int port);
+ char *BIO_get_conn_ip(BIO *b);
+ long BIO_get_conn_int_port(BIO *b);
long BIO_set_nbio(BIO *b, long n);
diff --git a/crypto/openssl/doc/ssl/SSL_CTX_set1_verify_cert_store.pod b/crypto/openssl/doc/ssl/SSL_CTX_set1_verify_cert_store.pod
index 493cca481940..3e3a4fa90c0e 100644
--- a/crypto/openssl/doc/ssl/SSL_CTX_set1_verify_cert_store.pod
+++ b/crypto/openssl/doc/ssl/SSL_CTX_set1_verify_cert_store.pod
@@ -17,10 +17,10 @@ verification or chain store
int SSL_CTX_set0_chain_cert_store(SSL_CTX *ctx, X509_STORE *st);
int SSL_CTX_set1_chain_cert_store(SSL_CTX *ctx, X509_STORE *st);
- int SSL_set0_verify_cert_store(SSL_CTX *ctx, X509_STORE *st);
- int SSL_set1_verify_cert_store(SSL_CTX *ctx, X509_STORE *st);
- int SSL_set0_chain_cert_store(SSL_CTX *ctx, X509_STORE *st);
- int SSL_set1_chain_cert_store(SSL_CTX *ctx, X509_STORE *st);
+ int SSL_set0_verify_cert_store(SSL *ctx, X509_STORE *st);
+ int SSL_set1_verify_cert_store(SSL *ctx, X509_STORE *st);
+ int SSL_set0_chain_cert_store(SSL *ctx, X509_STORE *st);
+ int SSL_set1_chain_cert_store(SSL *ctx, X509_STORE *st);
=head1 DESCRIPTION
diff --git a/crypto/openssl/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod b/crypto/openssl/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod
new file mode 100644
index 000000000000..b8147baecf98
--- /dev/null
+++ b/crypto/openssl/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod
@@ -0,0 +1,73 @@
+=pod
+
+=head1 NAME
+
+SSL_CTX_set_tlsext_status_cb, SSL_CTX_set_tlsext_status_arg,
+SSL_set_tlsext_status_type, SSL_get_tlsext_status_ocsp_resp,
+SSL_set_tlsext_status_ocsp_resp - OCSP Certificate Status Request functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/tls1.h>
+
+ long SSL_CTX_set_tlsext_status_cb(SSL_CTX *ctx,
+ int (*callback)(SSL *, void *));
+ long SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg);
+
+ long SSL_set_tlsext_status_type(SSL *s, int type);
+
+ long SSL_get_tlsext_status_ocsp_resp(ssl, unsigned char **resp);
+ long SSL_set_tlsext_status_ocsp_resp(ssl, unsigned char *resp, int len);
+
+=head1 DESCRIPTION
+
+A client application may request that a server send back an OCSP status response
+(also known as OCSP stapling). To do so the client should call the
+SSL_set_tlsext_status_type() function prior to the start of the handshake.
+Currently the only supported type is B<TLSEXT_STATUSTYPE_ocsp>. This value
+should be passed in the B<type> argument. The client should additionally provide
+a callback function to decide what to do with the returned OCSP response by
+calling SSL_CTX_set_tlsext_status_cb(). The callback function should determine
+whether the returned OCSP response is acceptable or not. The callback will be
+passed as an argument the value previously set via a call to
+SSL_CTX_set_tlsext_status_arg(). Note that the callback will not be called in
+the event of a handshake where session resumption occurs (because there are no
+Certificates exchanged in such a handshake).
+
+The response returned by the server can be obtained via a call to
+SSL_get_tlsext_status_ocsp_resp(). The value B<*resp> will be updated to point
+to the OCSP response data and the return value will be the length of that data.
+Typically a callback would obtain an OCSP_RESPONSE object from this data via a
+call to the d2i_OCSP_RESPONSE() function. If the server has not provided any
+response data then B<*resp> will be NULL and the return value from
+SSL_get_tlsext_status_ocsp_resp() will be -1.
+
+A server application must also call the SSL_CTX_set_tlsext_status_cb() function
+if it wants to be able to provide clients with OCSP Certificate Status
+responses. Typically the server callback would obtain the server certificate
+that is being sent back to the client via a call to SSL_get_certificate();
+obtain the OCSP response to be sent back; and then set that response data by
+calling SSL_set_tlsext_status_ocsp_resp(). A pointer to the response data should
+be provided in the B<resp> argument, and the length of that data should be in
+the B<len> argument.
+
+=head1 RETURN VALUES
+
+The callback when used on the client side should return a negative value on
+error; 0 if the response is not acceptable (in which case the handshake will
+fail) or a positive value if it is acceptable.
+
+The callback when used on the server side should return with either
+SSL_TLSEXT_ERR_OK (meaning that the OCSP response that has been set should be
+returned), SSL_TLSEXT_ERR_NOACK (meaning that an OCSP response should not be
+returned) or SSL_TLSEXT_ERR_ALERT_FATAL (meaning that a fatal error has
+occurred).
+
+SSL_CTX_set_tlsext_status_cb(), SSL_CTX_set_tlsext_status_arg(),
+SSL_set_tlsext_status_type() and SSL_set_tlsext_status_ocsp_resp() return 0 on
+error or 1 on success.
+
+SSL_get_tlsext_status_ocsp_resp() returns the length of the OCSP response data
+or -1 if there is no OCSP response data.
+
+=cut
diff --git a/crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod b/crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod
index b754c16a86e6..234fbc845002 100644
--- a/crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod
+++ b/crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod
@@ -48,25 +48,8 @@ even if he gets hold of the normal (certified) key, as this key was
only used for signing.
In order to perform a DH key exchange the server must use a DH group
-(DH parameters) and generate a DH key.
-The server will always generate a new DH key during the negotiation
-if either the DH parameters are supplied via callback or the
-SSL_OP_SINGLE_DH_USE option of SSL_CTX_set_options(3) is set (or both).
-It will immediately create a DH key if DH parameters are supplied via
-SSL_CTX_set_tmp_dh() and SSL_OP_SINGLE_DH_USE is not set.
-In this case,
-it may happen that a key is generated on initialization without later
-being needed, while on the other hand the computer time during the
-negotiation is being saved.
-
-If "strong" primes were used to generate the DH parameters, it is not strictly
-necessary to generate a new key for each handshake but it does improve forward
-secrecy. If it is not assured that "strong" primes were used,
-SSL_OP_SINGLE_DH_USE must be used in order to prevent small subgroup
-attacks. Always using SSL_OP_SINGLE_DH_USE has an impact on the
-computer time needed during negotiation, but it is not very large, so
-application authors/users should consider always enabling this option.
-The option is required to implement perfect forward secrecy (PFS).
+(DH parameters) and generate a DH key. The server will always generate
+a new DH key during the negotiation.
As generating DH parameters is extremely time consuming, an application
should not generate the parameters on the fly but supply the parameters.
@@ -93,10 +76,9 @@ can supply the DH parameters via a callback function.
Previous versions of the callback used B<is_export> and B<keylength>
parameters to control parameter generation for export and non-export
cipher suites. Modern servers that do not support export ciphersuites
-are advised to either use SSL_CTX_set_tmp_dh() in combination with
-SSL_OP_SINGLE_DH_USE, or alternatively, use the callback but ignore
-B<keylength> and B<is_export> and simply supply at least 2048-bit
-parameters in the callback.
+are advised to either use SSL_CTX_set_tmp_dh() or alternatively, use
+the callback but ignore B<keylength> and B<is_export> and simply
+supply at least 2048-bit parameters in the callback.
=head1 EXAMPLES
@@ -128,7 +110,6 @@ partly left out.)
if (SSL_CTX_set_tmp_dh(ctx, dh_2048) != 1) {
/* Error. */
}
- SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
...
=head1 RETURN VALUES
diff --git a/crypto/openssl/engines/e_chil.c b/crypto/openssl/engines/e_chil.c
index 72d14fe383a4..5dfab5134527 100644
--- a/crypto/openssl/engines/e_chil.c
+++ b/crypto/openssl/engines/e_chil.c
@@ -1,4 +1,4 @@
-/* crypto/engine/e_chil.c -*- mode: C; c-file-style: "eay" -*- */
+/* crypto/engine/e_chil.c */
/*
* Written by Richard Levitte (richard@levitte.org), Geoff Thorpe
* (geoff@geoffthorpe.net) and Dr Stephen N Henson (steve@openssl.org) for
diff --git a/crypto/openssl/ssl/d1_both.c b/crypto/openssl/ssl/d1_both.c
index c2c8d57e9d9c..d1fc716d5c5c 100644
--- a/crypto/openssl/ssl/d1_both.c
+++ b/crypto/openssl/ssl/d1_both.c
@@ -295,8 +295,44 @@ int dtls1_do_write(SSL *s, int type)
blocksize = 0;
frag_off = 0;
+ s->rwstate = SSL_NOTHING;
+
/* s->init_num shouldn't ever be < 0...but just in case */
while (s->init_num > 0) {
+ if (type == SSL3_RT_HANDSHAKE && s->init_off != 0) {
+ /* We must be writing a fragment other than the first one */
+
+ if (frag_off > 0) {
+ /* This is the first attempt at writing out this fragment */
+
+ if (s->init_off <= DTLS1_HM_HEADER_LENGTH) {
+ /*
+ * Each fragment that was already sent must at least have
+ * contained the message header plus one other byte.
+ * Therefore |init_off| must have progressed by at least
+ * |DTLS1_HM_HEADER_LENGTH + 1| bytes. If not something went
+ * wrong.
+ */
+ return -1;
+ }
+
+ /*
+ * Adjust |init_off| and |init_num| to allow room for a new
+ * message header for this fragment.
+ */
+ s->init_off -= DTLS1_HM_HEADER_LENGTH;
+ s->init_num += DTLS1_HM_HEADER_LENGTH;
+ } else {
+ /*
+ * We must have been called again after a retry so use the
+ * fragment offset from our last attempt. We do not need
+ * to adjust |init_off| and |init_num| as above, because
+ * that should already have been done before the retry.
+ */
+ frag_off = s->d1->w_msg_hdr.frag_off;
+ }
+ }
+
used_len = BIO_wpending(SSL_get_wbio(s)) + DTLS1_RT_HEADER_LENGTH
+ mac_size + blocksize;
if (s->d1->mtu > used_len)
@@ -309,8 +345,10 @@ int dtls1_do_write(SSL *s, int type)
* grr.. we could get an error if MTU picked was wrong
*/
ret = BIO_flush(SSL_get_wbio(s));
- if (ret <= 0)
+ if (ret <= 0) {
+ s->rwstate = SSL_WRITING;
return ret;
+ }
used_len = DTLS1_RT_HEADER_LENGTH + mac_size + blocksize;
if (s->d1->mtu > used_len + DTLS1_HM_HEADER_LENGTH) {
curr_mtu = s->d1->mtu - used_len;
@@ -336,25 +374,6 @@ int dtls1_do_write(SSL *s, int type)
* XDTLS: this function is too long. split out the CCS part
*/
if (type == SSL3_RT_HANDSHAKE) {
- if (s->init_off != 0) {
- OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH);
- s->init_off -= DTLS1_HM_HEADER_LENGTH;
- s->init_num += DTLS1_HM_HEADER_LENGTH;
-
- /*
- * We just checked that s->init_num > 0 so this cast should
- * be safe
- */
- if (((unsigned int)s->init_num) > curr_mtu)
- len = curr_mtu;
- else
- len = s->init_num;
- }
-
- /* Shouldn't ever happen */
- if (len > INT_MAX)
- len = INT_MAX;
-
if (len < DTLS1_HM_HEADER_LENGTH) {
/*
* len is so small that we really can't do anything sensible
@@ -442,7 +461,16 @@ int dtls1_do_write(SSL *s, int type)
}
s->init_off += ret;
s->init_num -= ret;
- frag_off += (ret -= DTLS1_HM_HEADER_LENGTH);
+ ret -= DTLS1_HM_HEADER_LENGTH;
+ frag_off += ret;
+
+ /*
+ * We save the fragment offset for the next fragment so we have it
+ * available in case of an IO retry. We don't know the length of the
+ * next fragment yet so just set that to 0 for now. It will be
+ * updated again later.
+ */
+ dtls1_fix_message_header(s, frag_off, 0);
}
}
return (0);
diff --git a/crypto/openssl/ssl/kssl.c b/crypto/openssl/ssl/kssl.c
index cf585679dccc..f2839bdcd7f5 100644
--- a/crypto/openssl/ssl/kssl.c
+++ b/crypto/openssl/ssl/kssl.c
@@ -1,4 +1,4 @@
-/* ssl/kssl.c -*- mode: C; c-file-style: "eay" -*- */
+/* ssl/kssl.c */
/*
* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project
* 2000.
diff --git a/crypto/openssl/ssl/kssl.h b/crypto/openssl/ssl/kssl.h
index 9a5767280150..ae8a51f472da 100644
--- a/crypto/openssl/ssl/kssl.h
+++ b/crypto/openssl/ssl/kssl.h
@@ -1,4 +1,4 @@
-/* ssl/kssl.h -*- mode: C; c-file-style: "eay" -*- */
+/* ssl/kssl.h */
/*
* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project
* 2000. project 2000.
diff --git a/crypto/openssl/ssl/kssl_lcl.h b/crypto/openssl/ssl/kssl_lcl.h
index 46dcef22d16c..8e6a6d69e949 100644
--- a/crypto/openssl/ssl/kssl_lcl.h
+++ b/crypto/openssl/ssl/kssl_lcl.h
@@ -1,4 +1,4 @@
-/* ssl/kssl.h -*- mode: C; c-file-style: "eay" -*- */
+/* ssl/kssl.h */
/*
* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project
* 2000. project 2000.
diff --git a/crypto/openssl/ssl/s2_srvr.c b/crypto/openssl/ssl/s2_srvr.c
index 4289272b73d3..07e9df82820a 100644
--- a/crypto/openssl/ssl/s2_srvr.c
+++ b/crypto/openssl/ssl/s2_srvr.c
@@ -402,7 +402,7 @@ static int get_client_master_key(SSL *s)
}
cp = ssl2_get_cipher_by_char(p);
- if (cp == NULL) {
+ if (cp == NULL || sk_SSL_CIPHER_find(s->session->ciphers, cp) < 0) {
ssl2_return_error(s, SSL2_PE_NO_CIPHER);
SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_NO_CIPHER_MATCH);
return (-1);
@@ -598,6 +598,11 @@ static int get_client_hello(SSL *s)
s->s2->tmp.cipher_spec_length = i;
n2s(p, i);
s->s2->tmp.session_id_length = i;
+ if ((i < 0) || (i > SSL_MAX_SSL_SESSION_ID_LENGTH)) {
+ ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
+ SSLerr(SSL_F_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
+ return -1;
+ }
n2s(p, i);
s->s2->challenge_length = i;
if ((i < SSL2_MIN_CHALLENGE_LENGTH) ||
@@ -687,8 +692,12 @@ static int get_client_hello(SSL *s)
prio = cs;
allow = cl;
}
+
+ /* Generate list of SSLv2 ciphers shared between client and server */
for (z = 0; z < sk_SSL_CIPHER_num(prio); z++) {
- if (sk_SSL_CIPHER_find(allow, sk_SSL_CIPHER_value(prio, z)) < 0) {
+ const SSL_CIPHER *cp = sk_SSL_CIPHER_value(prio, z);
+ if ((cp->algorithm_ssl & SSL_SSLV2) == 0 ||
+ sk_SSL_CIPHER_find(allow, cp) < 0) {
(void)sk_SSL_CIPHER_delete(prio, z);
z--;
}
@@ -697,6 +706,13 @@ static int get_client_hello(SSL *s)
sk_SSL_CIPHER_free(s->session->ciphers);
s->session->ciphers = prio;
}
+
+ /* Make sure we have at least one cipher in common */
+ if (sk_SSL_CIPHER_num(s->session->ciphers) == 0) {
+ ssl2_return_error(s, SSL2_PE_NO_CIPHER);
+ SSLerr(SSL_F_GET_CLIENT_HELLO, SSL_R_NO_CIPHER_MATCH);
+ return -1;
+ }
/*
* s->session->ciphers should now have a list of ciphers that are on
* both the client and server. This list is ordered by the order the
diff --git a/crypto/openssl/ssl/s3_clnt.c b/crypto/openssl/ssl/s3_clnt.c
index bc5254c81160..04cc9f54a92d 100644
--- a/crypto/openssl/ssl/s3_clnt.c
+++ b/crypto/openssl/ssl/s3_clnt.c
@@ -2350,37 +2350,44 @@ int ssl3_get_cert_status(SSL *s)
n = s->method->ssl_get_message(s,
SSL3_ST_CR_CERT_STATUS_A,
SSL3_ST_CR_CERT_STATUS_B,
- SSL3_MT_CERTIFICATE_STATUS, 16384, &ok);
+ -1, 16384, &ok);
if (!ok)
return ((int)n);
- if (n < 4) {
- /* need at least status type + length */
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
- goto f_err;
- }
- p = (unsigned char *)s->init_msg;
- if (*p++ != TLSEXT_STATUSTYPE_ocsp) {
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_UNSUPPORTED_STATUS_TYPE);
- goto f_err;
- }
- n2l3(p, resplen);
- if (resplen + 4 != n) {
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
- goto f_err;
- }
- if (s->tlsext_ocsp_resp)
- OPENSSL_free(s->tlsext_ocsp_resp);
- s->tlsext_ocsp_resp = BUF_memdup(p, resplen);
- if (!s->tlsext_ocsp_resp) {
- al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_SSL3_GET_CERT_STATUS, ERR_R_MALLOC_FAILURE);
- goto f_err;
+
+ if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_STATUS) {
+ /*
+ * The CertificateStatus message is optional even if
+ * tlsext_status_expected is set
+ */
+ s->s3->tmp.reuse_message = 1;
+ } else {
+ if (n < 4) {
+ /* need at least status type + length */
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ p = (unsigned char *)s->init_msg;
+ if (*p++ != TLSEXT_STATUSTYPE_ocsp) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_UNSUPPORTED_STATUS_TYPE);
+ goto f_err;
+ }
+ n2l3(p, resplen);
+ if (resplen + 4 != n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ s->tlsext_ocsp_resp = BUF_memdup(p, resplen);
+ if (s->tlsext_ocsp_resp == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CERT_STATUS, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+ s->tlsext_ocsp_resplen = resplen;
}
- s->tlsext_ocsp_resplen = resplen;
if (s->ctx->tlsext_status_cb) {
int ret;
ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
@@ -3603,7 +3610,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
DH_free(dh_srvr);
}
- if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 768)
+ if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 1024)
|| (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 512)) {
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_DH_KEY_TOO_SMALL);
goto f_err;
diff --git a/crypto/openssl/ssl/s3_lib.c b/crypto/openssl/ssl/s3_lib.c
index 64793d6af34f..f846cb5b7b01 100644
--- a/crypto/openssl/ssl/s3_lib.c
+++ b/crypto/openssl/ssl/s3_lib.c
@@ -3206,13 +3206,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB);
return (ret);
}
- if (!(s->options & SSL_OP_SINGLE_DH_USE)) {
- if (!DH_generate_key(dh)) {
- DH_free(dh);
- SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB);
- return (ret);
- }
- }
if (s->cert->dh_tmp != NULL)
DH_free(s->cert->dh_tmp);
s->cert->dh_tmp = dh;
@@ -3263,6 +3256,8 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
#ifndef OPENSSL_NO_TLSEXT
case SSL_CTRL_SET_TLSEXT_HOSTNAME:
if (larg == TLSEXT_NAMETYPE_host_name) {
+ size_t len;
+
if (s->tlsext_hostname != NULL)
OPENSSL_free(s->tlsext_hostname);
s->tlsext_hostname = NULL;
@@ -3270,7 +3265,8 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
ret = 1;
if (parg == NULL)
break;
- if (strlen((char *)parg) > TLSEXT_MAXLEN_host_name) {
+ len = strlen((char *)parg);
+ if (len == 0 || len > TLSEXT_MAXLEN_host_name) {
SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME);
return 0;
}
@@ -3710,13 +3706,6 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_DH_LIB);
return 0;
}
- if (!(ctx->options & SSL_OP_SINGLE_DH_USE)) {
- if (!DH_generate_key(new)) {
- SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_DH_LIB);
- DH_free(new);
- return 0;
- }
- }
if (cert->dh_tmp != NULL)
DH_free(cert->dh_tmp);
cert->dh_tmp = new;
@@ -4337,6 +4326,21 @@ int ssl3_shutdown(SSL *s)
}
#endif
} else if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) {
+ if (SSL_in_init(s)) {
+ /*
+ * We can't shutdown properly if we are in the middle of a
+ * handshake. Doing so is problematic because the peer may send a
+ * CCS before it acts on our close_notify. However we should not
+ * continue to process received handshake messages or CCS once our
+ * close_notify has been sent. Therefore any close_notify from
+ * the peer will be unreadable because we have not moved to the next
+ * cipher state. Its best just to avoid this can-of-worms. Return
+ * an error if we are wanting to wait for a close_notify from the
+ * peer and we are in init.
+ */
+ SSLerr(SSL_F_SSL3_SHUTDOWN, SSL_R_SHUTDOWN_WHILE_IN_INIT);
+ return -1;
+ }
/*
* If we are waiting for a close from our peer, we are closed
*/
diff --git a/crypto/openssl/ssl/s3_srvr.c b/crypto/openssl/ssl/s3_srvr.c
index ee83105b75bf..ab28702ee972 100644
--- a/crypto/openssl/ssl/s3_srvr.c
+++ b/crypto/openssl/ssl/s3_srvr.c
@@ -1,4 +1,4 @@
-/* ssl/s3_srvr.c -*- mode:C; c-file-style: "eay" -*- */
+/* ssl/s3_srvr.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -1004,6 +1004,12 @@ int ssl3_get_client_hello(SSL *s)
goto f_err;
}
+ if ((j < 0) || (j > SSL_MAX_SSL_SESSION_ID_LENGTH)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
s->hit = 0;
/*
* Versions before 0.9.7 always allow clients to resume sessions in
@@ -1681,20 +1687,9 @@ int ssl3_send_server_key_exchange(SSL *s)
}
s->s3->tmp.dh = dh;
- if ((dhp->pub_key == NULL ||
- dhp->priv_key == NULL ||
- (s->options & SSL_OP_SINGLE_DH_USE))) {
- if (!DH_generate_key(dh)) {
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB);
- goto err;
- }
- } else {
- dh->pub_key = BN_dup(dhp->pub_key);
- dh->priv_key = BN_dup(dhp->priv_key);
- if ((dh->pub_key == NULL) || (dh->priv_key == NULL)) {
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB);
- goto err;
- }
+ if (!DH_generate_key(dh)) {
+ SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB);
+ goto err;
}
r[0] = dh->p;
r[1] = dh->g;
diff --git a/crypto/openssl/ssl/ssl.h b/crypto/openssl/ssl/ssl.h
index afec1f5bf29f..ae8c92575e03 100644
--- a/crypto/openssl/ssl/ssl.h
+++ b/crypto/openssl/ssl/ssl.h
@@ -625,7 +625,7 @@ struct ssl_session_st {
# define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L
/* If set, always create a new key when using tmp_ecdh parameters */
# define SSL_OP_SINGLE_ECDH_USE 0x00080000L
-/* If set, always create a new key when using tmp_dh parameters */
+/* Does nothing: retained for compatibility */
# define SSL_OP_SINGLE_DH_USE 0x00100000L
/* Does nothing: retained for compatibiity */
# define SSL_OP_EPHEMERAL_RSA 0x0
@@ -2092,7 +2092,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
# define SSL_CTX_set1_sigalgs_list(ctx, s) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)s)
# define SSL_set1_sigalgs(ctx, slist, slistlen) \
- SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS,clistlen,(int *)slist)
+ SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)slist)
# define SSL_set1_sigalgs_list(ctx, s) \
SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)s)
# define SSL_CTX_set1_client_sigalgs(ctx, slist, slistlen) \
@@ -2713,6 +2713,7 @@ void ERR_load_SSL_strings(void);
# define SSL_F_SSL3_SETUP_KEY_BLOCK 157
# define SSL_F_SSL3_SETUP_READ_BUFFER 156
# define SSL_F_SSL3_SETUP_WRITE_BUFFER 291
+# define SSL_F_SSL3_SHUTDOWN 396
# define SSL_F_SSL3_WRITE_BYTES 158
# define SSL_F_SSL3_WRITE_PENDING 159
# define SSL_F_SSL_ADD_CERT_CHAIN 318
@@ -3056,6 +3057,7 @@ void ERR_load_SSL_strings(void);
# define SSL_R_SERVERHELLO_TLSEXT 275
# define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 277
# define SSL_R_SHORT_READ 219
+# define SSL_R_SHUTDOWN_WHILE_IN_INIT 407
# define SSL_R_SIGNATURE_ALGORITHMS_ERROR 360
# define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220
# define SSL_R_SRP_A_CALC 361
diff --git a/crypto/openssl/ssl/ssl_err.c b/crypto/openssl/ssl/ssl_err.c
index 6d1366f2a59d..dd3b2afd1ea6 100644
--- a/crypto/openssl/ssl/ssl_err.c
+++ b/crypto/openssl/ssl/ssl_err.c
@@ -206,6 +206,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
{ERR_FUNC(SSL_F_SSL3_SETUP_KEY_BLOCK), "ssl3_setup_key_block"},
{ERR_FUNC(SSL_F_SSL3_SETUP_READ_BUFFER), "ssl3_setup_read_buffer"},
{ERR_FUNC(SSL_F_SSL3_SETUP_WRITE_BUFFER), "ssl3_setup_write_buffer"},
+ {ERR_FUNC(SSL_F_SSL3_SHUTDOWN), "ssl3_shutdown"},
{ERR_FUNC(SSL_F_SSL3_WRITE_BYTES), "ssl3_write_bytes"},
{ERR_FUNC(SSL_F_SSL3_WRITE_PENDING), "ssl3_write_pending"},
{ERR_FUNC(SSL_F_SSL_ADD_CERT_CHAIN), "ssl_add_cert_chain"},
@@ -647,6 +648,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
{ERR_REASON(SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED),
"session id context uninitialized"},
{ERR_REASON(SSL_R_SHORT_READ), "short read"},
+ {ERR_REASON(SSL_R_SHUTDOWN_WHILE_IN_INIT), "shutdown while in init"},
{ERR_REASON(SSL_R_SIGNATURE_ALGORITHMS_ERROR),
"signature algorithms error"},
{ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE),
diff --git a/crypto/openssl/ssl/ssl_lib.c b/crypto/openssl/ssl/ssl_lib.c
index f2071db93702..2744be8ad8ce 100644
--- a/crypto/openssl/ssl/ssl_lib.c
+++ b/crypto/openssl/ssl/ssl_lib.c
@@ -1060,10 +1060,7 @@ int SSL_shutdown(SSL *s)
return -1;
}
- if ((s != NULL) && !SSL_in_init(s))
- return (s->method->ssl_shutdown(s));
- else
- return (1);
+ return s->method->ssl_shutdown(s);
}
int SSL_renegotiate(SSL *s)
diff --git a/crypto/openssl/ssl/ssl_sess.c b/crypto/openssl/ssl/ssl_sess.c
index 68390d310809..b18299834384 100644
--- a/crypto/openssl/ssl/ssl_sess.c
+++ b/crypto/openssl/ssl/ssl_sess.c
@@ -573,9 +573,6 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
int r;
#endif
- if (len < 0 || len > SSL_MAX_SSL_SESSION_ID_LENGTH)
- goto err;
-
if (session_id + len > limit) {
fatal = 1;
goto err;
diff --git a/crypto/openssl/ssl/t1_enc.c b/crypto/openssl/ssl/t1_enc.c
index f46544b4d713..514fcb3e4e74 100644
--- a/crypto/openssl/ssl/t1_enc.c
+++ b/crypto/openssl/ssl/t1_enc.c
@@ -1155,7 +1155,7 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
so = s->s3->server_opaque_prf_input;
/*
* must be same as col (see
- * draft-resc-00.txts-opaque-prf-input-00.txt, section 3.1)
+ * draft-rescorla-tls-opaque-prf-input-00.txt, section 3.1)
*/
sol = s->s3->client_opaque_prf_input_len;
}
diff --git a/crypto/openssl/ssl/t1_lib.c b/crypto/openssl/ssl/t1_lib.c
index 3176d1e3baba..d9ba99d73584 100644
--- a/crypto/openssl/ssl/t1_lib.c
+++ b/crypto/openssl/ssl/t1_lib.c
@@ -3157,22 +3157,20 @@ int ssl_check_serverhello_tlsext(SSL *s)
}
# endif
+ OPENSSL_free(s->tlsext_ocsp_resp);
+ s->tlsext_ocsp_resp = NULL;
+ s->tlsext_ocsp_resplen = -1;
/*
* If we've requested certificate status and we wont get one tell the
* callback
*/
if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected)
- && s->ctx && s->ctx->tlsext_status_cb) {
+ && !(s->hit) && s->ctx && s->ctx->tlsext_status_cb) {
int r;
/*
- * Set resp to NULL, resplen to -1 so callback knows there is no
- * response.
+ * Call callback with resp == NULL and resplen == -1 so callback
+ * knows there is no response
*/
- if (s->tlsext_ocsp_resp) {
- OPENSSL_free(s->tlsext_ocsp_resp);
- s->tlsext_ocsp_resp = NULL;
- }
- s->tlsext_ocsp_resplen = -1;
r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
if (r == 0) {
al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
@@ -3583,7 +3581,7 @@ static int tls12_get_pkey_idx(unsigned char sig_alg)
static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid,
int *psignhash_nid, const unsigned char *data)
{
- int sign_nid = 0, hash_nid = 0;
+ int sign_nid = NID_undef, hash_nid = NID_undef;
if (!phash_nid && !psign_nid && !psignhash_nid)
return;
if (phash_nid || psignhash_nid) {
@@ -3599,9 +3597,9 @@ static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid,
*psign_nid = sign_nid;
}
if (psignhash_nid) {
- if (sign_nid && hash_nid)
- OBJ_find_sigid_by_algs(psignhash_nid, hash_nid, sign_nid);
- else
+ if (sign_nid == NID_undef || hash_nid == NID_undef
+ || OBJ_find_sigid_by_algs(psignhash_nid, hash_nid,
+ sign_nid) <= 0)
*psignhash_nid = NID_undef;
}
}
diff --git a/crypto/openssl/util/domd b/crypto/openssl/util/domd
index 6a628c7f96c2..95bb1b06e257 100755
--- a/crypto/openssl/util/domd
+++ b/crypto/openssl/util/domd
@@ -14,8 +14,8 @@ if [ "$MAKEDEPEND" = "" ]; then MAKEDEPEND=makedepend; fi
cp Makefile Makefile.save
# fake the presence of Kerberos
touch $TOP/krb5.h
-if ${MAKEDEPEND} --version 2>&1 | grep -q "clang" ||
- echo $MAKEDEPEND | grep -q "gcc"; then
+if ${MAKEDEPEND} --version 2>&1 | grep "clang" > /dev/null ||
+ echo $MAKEDEPEND | grep "gcc" > /dev/null; then
args=""
while [ $# -gt 0 ]; do
if [ "$1" != "--" ]; then args="$args $1"; fi
diff --git a/crypto/openssl/util/pl/VC-32.pl b/crypto/openssl/util/pl/VC-32.pl
index 284fe0381ed9..0f5547f056c2 100644
--- a/crypto/openssl/util/pl/VC-32.pl
+++ b/crypto/openssl/util/pl/VC-32.pl
@@ -361,9 +361,13 @@ sub do_link_rule
$ret.="$target: $files $dep_libs";
if ($standalone == 1)
{
- $ret.=" \$(OBJ_D)${o}applink.obj\n";
+ $ret.=" \$(OBJ_D)${o}applink.obj" if $shlib;
+ $ret.="\n";
$ret.=" \$(LINK) \$(LFLAGS) $efile$target @<<\n\t";
- $ret.= "\$(EX_LIBS) \$(OBJ_D)${o}applink.obj " if ($files =~ /O_FIPSCANISTER/ && !$fipscanisterbuild);
+ if ($files =~ /O_FIPSCANISTER/ && !$fipscanisterbuild) {
+ $ret.= "\$(EX_LIBS) ";
+ $ret.= "\$(OBJ_D)${o}applink.obj " if $shlib;
+ }
$ret.="$files $libs\n<<\n";
}
elsif ($standalone == 2)
diff --git a/crypto/openssl/util/pod2mantest b/crypto/openssl/util/pod2mantest
new file mode 100755
index 000000000000..384e683df4cc
--- /dev/null
+++ b/crypto/openssl/util/pod2mantest
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+# This script is used by test/Makefile to check whether a sane 'pod2man'
+# is installed.
+# ('make install' should not try to run 'pod2man' if it does not exist or if
+# it is a broken 'pod2man' version that is known to cause trouble. if we find
+# the system 'pod2man' to be broken, we use our own copy instead)
+#
+# In any case, output an appropriate command line for running (or not
+# running) pod2man.
+
+
+IFS=:
+if test "$OSTYPE" = "msdosdjgpp"; then IFS=";"; fi
+
+try_without_dir=true
+# First we try "pod2man", then "$dir/pod2man" for each item in $PATH.
+for dir in dummy${IFS}$PATH; do
+ if [ "$try_without_dir" = true ]; then
+ # first iteration
+ pod2man=pod2man
+ try_without_dir=false
+ else
+ # second and later iterations
+ pod2man="$dir/pod2man"
+ if [ ! -f "$pod2man" ]; then # '-x' is not available on Ultrix
+ pod2man=''
+ fi
+ fi
+
+ if [ ! "$pod2man" = '' ]; then
+ failure=none
+
+ if "$pod2man" --section=1 --center=OpenSSL --release=dev pod2mantest.pod | fgrep OpenSSL >/dev/null; then
+ :
+ else
+ failure=BasicTest
+ fi
+
+ if [ "$failure" = none ]; then
+ if "$pod2man" --section=1 --center=OpenSSL --release=dev pod2mantest.pod | grep '^MARKER - ' >/dev/null; then
+ failure=MultilineTest
+ fi
+ fi
+
+
+ if [ "$failure" = none ]; then
+ echo "$pod2man"
+ exit 0
+ fi
+
+ echo "$pod2man does not work properly ('$failure' failed). Looking for another pod2man ..." >&2
+ fi
+done
+
+echo "No working pod2man found. Consider installing a new version." >&2
+echo "As a workaround, we'll use a bundled old copy of pod2man.pl." >&2
+echo "$1 ../../util/pod2man.pl"
diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf
index a674acb97532..69b6d0f77bd0 100644
--- a/etc/defaults/rc.conf
+++ b/etc/defaults/rc.conf
@@ -716,5 +716,18 @@ if [ -z "${source_rc_confs_defined}" ]; then
;;
esac
done
+ # Re-do process to pick up [possibly] redefined $rc_conf_files
+ for i in ${rc_conf_files}; do
+ case ${sourced_files} in
+ *:$i:*)
+ ;;
+ *)
+ sourced_files="${sourced_files}:$i:"
+ if [ -r $i ]; then
+ . $i
+ fi
+ ;;
+ esac
+ done
}
fi
diff --git a/etc/periodic/daily/800.scrub-zfs b/etc/periodic/daily/800.scrub-zfs
index 359be13b227a..64eac99c38a1 100755
--- a/etc/periodic/daily/800.scrub-zfs
+++ b/etc/periodic/daily/800.scrub-zfs
@@ -63,6 +63,11 @@ case "$daily_scrub_zfs_enable" in
_last_scrub=$(zpool history ${pool} | \
sed -ne '2s/ .*$//p')
fi
+ if [ -z "${_last_scrub}" ]; then
+ echo " skipping scrubbing of pool '${pool}':"
+ echo " can't get last scrubbing date"
+ continue
+ fi
# Now minus last scrub (both in seconds) converted to days.
_scrub_diff=$(expr -e \( $(date +%s) - \
@@ -73,11 +78,14 @@ case "$daily_scrub_zfs_enable" in
continue
fi
- _status="$(zpool status ${pool} | grep scrub:)"
+ _status="$(zpool status ${pool} | grep scan:)"
case "${_status}" in
*"scrub in progress"*)
echo " scrubbing of pool '${pool}' already in progress, skipping:"
;;
+ *"resilver in progress"*)
+ echo " resilvering of pool '${pool}' is in progress, skipping:"
+ ;;
*"none requested"*)
echo " starting first scrub (since reboot) of pool '${pool}':"
zpool scrub ${pool}
diff --git a/etc/periodic/security/security.functions b/etc/periodic/security/security.functions
index bc2bcba16877..c2c757a3789d 100644
--- a/etc/periodic/security/security.functions
+++ b/etc/periodic/security/security.functions
@@ -51,7 +51,7 @@ check_diff() {
rc=0
if [ "$1" = "new_only" ]; then
shift
- filter="grep '^[>+]'"
+ filter="grep '^[>+][^+]'"
else
filter="cat"
fi
diff --git a/etc/rc.d/jail b/etc/rc.d/jail
index fa0bc46be6ee..b33f1b9a2c23 100755
--- a/etc/rc.d/jail
+++ b/etc/rc.d/jail
@@ -563,7 +563,7 @@ jail_warn()
# To relieve confusion, show a warning message.
case $_confwarn in
1) warn "Per-jail configuration via jail_* variables " \
- "is obsolete. Please consider to migrate to $jail_conf."
+ "is obsolete. Please consider migrating to $jail_conf."
;;
esac
}
diff --git a/lib/libbluetooth/bluetooth.h b/lib/libbluetooth/bluetooth.h
index 0435b4e2f232..85059972cbb1 100644
--- a/lib/libbluetooth/bluetooth.h
+++ b/lib/libbluetooth/bluetooth.h
@@ -178,7 +178,7 @@ int bt_devfilter_evt_tst(struct bt_devfilter const *filter, uint8_t event);
int bt_devinquiry(char const *devname, time_t length, int num_rsp,
struct bt_devinquiry **ii);
int bt_devinfo (struct bt_devinfo *di);
-int bt_devenum (bt_devenum_cb_t *cb, void *arg);
+int bt_devenum (bt_devenum_cb_t cb, void *arg);
/*
* bdaddr utility functions (from NetBSD)
diff --git a/lib/libc/db/hash/hash.h b/lib/libc/db/hash/hash.h
index cd11a3ae98eb..663ecdd10f8f 100644
--- a/lib/libc/db/hash/hash.h
+++ b/lib/libc/db/hash/hash.h
@@ -138,11 +138,11 @@ typedef struct htab { /* Memory resident data structure */
#define ALL_SET ((u_int32_t)0xFFFFFFFF)
#define ALL_CLEAR 0
-#define PTROF(X) ((BUFHEAD *)((ptrdiff_t)(X)&~0x3))
-#define ISMOD(X) ((u_int32_t)(ptrdiff_t)(X)&0x1)
-#define DOMOD(X) ((X) = (char *)((ptrdiff_t)(X)|0x1))
-#define ISDISK(X) ((u_int32_t)(ptrdiff_t)(X)&0x2)
-#define DODISK(X) ((X) = (char *)((ptrdiff_t)(X)|0x2))
+#define PTROF(X) ((BUFHEAD *)((intptr_t)(X)&~0x3))
+#define ISMOD(X) ((u_int32_t)(intptr_t)(X)&0x1)
+#define DOMOD(X) ((X) = (char *)((intptr_t)(X)|0x1))
+#define ISDISK(X) ((u_int32_t)(intptr_t)(X)&0x2)
+#define DODISK(X) ((X) = (char *)((intptr_t)(X)|0x2))
#define BITS_PER_MAP 32
diff --git a/lib/libc/db/hash/hash_buf.c b/lib/libc/db/hash/hash_buf.c
index 4445fc52b043..e79e7b3efcfa 100644
--- a/lib/libc/db/hash/hash_buf.c
+++ b/lib/libc/db/hash/hash_buf.c
@@ -138,7 +138,7 @@ __get_buf(HTAB *hashp, u_int32_t addr,
return (NULL);
if (!prev_bp)
segp[segment_ndx] =
- (BUFHEAD *)((ptrdiff_t)bp | is_disk_mask);
+ (BUFHEAD *)((intptr_t)bp | is_disk_mask);
} else {
BUF_REMOVE(bp);
MRU_INSERT(bp);
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index b44846131f45..7de8ce33d647 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -99,11 +99,13 @@ SRCS+= __getosreldate.c \
raise.c \
readdir.c \
readpassphrase.c \
+ recvmmsg.c \
rewinddir.c \
scandir.c \
seed48.c \
seekdir.c \
semctl.c \
+ sendmmsg.c \
setdomainname.c \
sethostname.c \
setjmperr.c \
@@ -451,10 +453,12 @@ MLINKS+=rand48.3 _rand48.3 \
rand48.3 nrand48.3 \
rand48.3 seed48.3 \
rand48.3 srand48.3
+MLINKS+=recv.2 recvmmsg.2
MLINKS+=scandir.3 alphasort.3
MLINKS+=sem_open.3 sem_close.3 \
sem_open.3 sem_unlink.3
MLINKS+=sem_wait.3 sem_trywait.3
+MLINKS+=send.2 sendmmsg.2
MLINKS+=setjmp.3 _longjmp.3 \
setjmp.3 _setjmp.3 \
setjmp.3 longjmp.3 \
diff --git a/lib/libc/gen/recvmmsg.c b/lib/libc/gen/recvmmsg.c
new file mode 100644
index 000000000000..0db9e1acab17
--- /dev/null
+++ b/lib/libc/gen/recvmmsg.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016 Boris Astardzhiev, Smartcom-Bulgaria AD
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice(s), this list of conditions and the following disclaimer as
+ * the first lines of this file unmodified other than the possible
+ * addition of one or more copyright notices.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice(s), this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <poll.h>
+#include <stddef.h>
+#include "libc_private.h"
+
+ssize_t
+recvmmsg(int s, struct mmsghdr *__restrict msgvec, size_t vlen, int flags,
+ const struct timespec *__restrict timeout)
+{
+ struct pollfd pfd[1];
+ size_t i, rcvd;
+ ssize_t ret;
+ int res;
+ short ev;
+
+ if (timeout != NULL) {
+ pfd[0].fd = s;
+ pfd[0].revents = 0;
+ pfd[0].events = ev = POLLIN | POLLRDNORM | POLLRDBAND |
+ POLLPRI;
+ res = ppoll(&pfd[0], 1, timeout, NULL);
+ if (res == -1 || res == 0)
+ return (res);
+ if (pfd[0].revents & POLLNVAL) {
+ errno = EBADF;
+ return (-1);
+ }
+ if ((pfd[0].revents & ev) == 0) {
+ errno = ETIMEDOUT;
+ return (-1);
+ }
+ }
+
+ ret = __sys_recvmsg(s, &msgvec[0].msg_hdr, flags);
+ if (ret == -1)
+ return (ret);
+
+ /*
+ * Do non-blocking receive for second and later messages if
+ * WAITFORONE is set.
+ */
+ if (flags & MSG_WAITFORONE)
+ flags |= MSG_DONTWAIT;
+
+ rcvd = 1;
+ for (i = rcvd; i < vlen; i++, rcvd++) {
+ ret = __sys_recvmsg(s, &msgvec[i].msg_hdr, flags);
+ if (ret == -1) {
+ /* We have received messages. Let caller know
+ * about the data received, socket
+ * error is returned on next
+ * invocation.
+ */
+ return (rcvd);
+ }
+
+ /* Save received bytes. */
+ msgvec[i].msg_len = ret;
+ }
+
+ return (rcvd);
+}
diff --git a/lib/libc/gen/sendmmsg.c b/lib/libc/gen/sendmmsg.c
new file mode 100644
index 000000000000..7b3e8f357613
--- /dev/null
+++ b/lib/libc/gen/sendmmsg.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016 Boris Astardzhiev, Smartcom-Bulgaria AD
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice(s), this list of conditions and the following disclaimer as
+ * the first lines of this file unmodified other than the possible
+ * addition of one or more copyright notices.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice(s), this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include "libc_private.h"
+
+ssize_t
+sendmmsg(int s, struct mmsghdr *__restrict msgvec, size_t vlen, int flags)
+{
+ size_t i, sent;
+ ssize_t ret;
+
+ sent = 0;
+ for (i = 0; i < vlen; i++, sent++) {
+ ret = __sys_sendmsg(s, &msgvec[i].msg_hdr, flags);
+ if (ret == -1) {
+ if (sent != 0) {
+ /*
+ * We have sent messages. Let caller
+ * know about the data sent, socket
+ * error is returned on next
+ * invocation.
+ */
+ return (sent);
+ }
+ return (ret);
+ }
+
+ /* Save sent bytes. */
+ msgvec[i].msg_len = ret;
+ }
+
+ return (sent);
+}
diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h
index 739d7b112392..c95829e401f1 100644
--- a/lib/libc/include/namespace.h
+++ b/lib/libc/include/namespace.h
@@ -208,6 +208,7 @@
#define readv _readv
#define recvfrom _recvfrom
#define recvmsg _recvmsg
+#define recvmmsg _recvmmsg
#define select _select
#define sem_close _sem_close
#define sem_destroy _sem_destroy
@@ -220,6 +221,7 @@
#define sem_unlink _sem_unlink
#define sem_wait _sem_wait
#define sendmsg _sendmsg
+#define sendmmsg _sendmmsg
#define sendto _sendto
#define setsockopt _setsockopt
/*#define sigaction _sigaction*/
diff --git a/lib/libc/include/un-namespace.h b/lib/libc/include/un-namespace.h
index f31fa7ade9e7..023334858572 100644
--- a/lib/libc/include/un-namespace.h
+++ b/lib/libc/include/un-namespace.h
@@ -189,6 +189,7 @@
#undef readv
#undef recvfrom
#undef recvmsg
+#undef recvmmsg
#undef select
#undef sem_close
#undef sem_destroy
@@ -201,6 +202,7 @@
#undef sem_unlink
#undef sem_wait
#undef sendmsg
+#undef sendmmsg
#undef sendto
#undef setsockopt
#undef sigaction
diff --git a/lib/libc/nls/msgcat.c b/lib/libc/nls/msgcat.c
index 0cba460403b3..3df76b60b4bd 100644
--- a/lib/libc/nls/msgcat.c
+++ b/lib/libc/nls/msgcat.c
@@ -325,6 +325,21 @@ notfound:
return ((char *)s);
}
+static void
+catfree(struct catentry *np)
+{
+
+ if (np->catd != NULL && np->catd != NLERR) {
+ munmap(np->catd->__data, (size_t)np->catd->__size);
+ free(np->catd);
+ }
+ SLIST_REMOVE(&cache, np, catentry, list);
+ free(np->name);
+ free(np->path);
+ free(np->lang);
+ free(np);
+}
+
int
catclose(nl_catd catd)
{
@@ -341,15 +356,8 @@ catclose(nl_catd catd)
SLIST_FOREACH(np, &cache, list) {
if (catd == np->catd) {
np->refcount--;
- if (np->refcount == 0) {
- munmap(catd->__data, (size_t)catd->__size);
- free(catd);
- SLIST_REMOVE(&cache, np, catentry, list);
- free(np->name);
- free(np->path);
- free(np->lang);
- free(np);
- }
+ if (np->refcount == 0)
+ catfree(np);
break;
}
}
diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map
index 7b3257c6a812..dc2ed0ed6e57 100644
--- a/lib/libc/sys/Symbol.map
+++ b/lib/libc/sys/Symbol.map
@@ -399,6 +399,8 @@ FBSD_1.4 {
utimensat;
numa_setaffinity;
numa_getaffinity;
+ sendmmsg;
+ recvmmsg;
};
FBSDprivate_1.0 {
diff --git a/lib/libc/sys/connect.2 b/lib/libc/sys/connect.2
index e3e57831475a..80f440715b83 100644
--- a/lib/libc/sys/connect.2
+++ b/lib/libc/sys/connect.2
@@ -28,7 +28,7 @@
.\" @(#)connect.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd September 29, 2014
+.Dd February 4, 2016
.Dt CONNECT 2
.Os
.Sh NAME
@@ -58,6 +58,14 @@ another socket.
The other socket is specified by
.Fa name ,
which is an address in the communications space of the socket.
+.Fa namelen
+indicates the amount of space pointed to by
+.Fa name ,
+in bytes; the
+.Fa sa_len
+member of
+.Fa name
+is ignored.
Each communications space interprets the
.Fa name
argument in its own way.
diff --git a/lib/libc/sys/recv.2 b/lib/libc/sys/recv.2
index 326e7ffd130a..4867ea77e3e5 100644
--- a/lib/libc/sys/recv.2
+++ b/lib/libc/sys/recv.2
@@ -28,14 +28,15 @@
.\" @(#)recv.2 8.3 (Berkeley) 2/21/94
.\" $FreeBSD$
.\"
-.Dd October 15, 2014
+.Dd January 29, 2016
.Dt RECV 2
.Os
.Sh NAME
.Nm recv ,
.Nm recvfrom ,
-.Nm recvmsg
-.Nd receive a message from a socket
+.Nm recvmsg ,
+.Nm recvmmsg
+.Nd receive message(s) from a socket
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -47,11 +48,14 @@
.Fn recvfrom "int s" "void *buf" "size_t len" "int flags" "struct sockaddr * restrict from" "socklen_t * restrict fromlen"
.Ft ssize_t
.Fn recvmsg "int s" "struct msghdr *msg" "int flags"
+.Ft ssize_t
+.Fn recvmmsg "int s" "struct mmsghdr * restrict msgvec" "size_t vlen" "int flags" "const struct timespec * restrict timeout"
.Sh DESCRIPTION
The
-.Fn recvfrom
+.Fn recvfrom ,
+.Fn recvmsg ,
and
-.Fn recvmsg
+.Fn recvmmsg
system calls
are used to receive messages from a socket,
and may be used to receive data on a socket whether or not
@@ -84,8 +88,39 @@ null pointer passed as its
.Fa from
argument.
.Pp
-All three routines return the length of the message on successful
-completion.
+The
+.Fn recvmmsg
+function is used to receive multiple
+messages at a call.
+Their number is supplied by
+.Fa vlen .
+The messages are placed in the buffers described by
+.Fa msgvec
+vector, after reception.
+The size of each received message is placed in the
+.Fa msg_len
+field of each element of the vector.
+If
+.Fa timeout
+is NULL the call blocks until the data is available for each
+supplied message buffer.
+Otherwise it waits for data for the specified amount of time.
+If the timeout expired and there is no data received,
+a value 0 is returned.
+The
+.Xr ppoll 2
+system call is used to implement the timeout mechanism,
+before first receive is performed.
+.Pp
+The
+.Fn recv ,
+.Fn recvfrom
+and
+.Fn recvmsg
+return the length of the message on successful
+completion, whereas
+.Fn recvmmsg
+returns the number of received messages.
If a message is too long to fit in the supplied buffer,
excess bytes may be discarded depending on the type of socket
the message is received from (see
@@ -100,7 +135,9 @@ in which case the value
.Va errno
is set to
.Er EAGAIN .
-The receive calls normally return any data available,
+The receive calls except
+.Fn recvmmsg
+normally return any data available,
up to the requested amount,
rather than waiting for receipt of the full amount requested;
this behavior is affected by the socket-level options
@@ -109,6 +146,9 @@ and
.Dv SO_RCVTIMEO
described in
.Xr getsockopt 2 .
+The
+.Fn recvmmsg
+function implements this behaviour for each message in the vector.
.Pp
The
.Xr select 2
@@ -127,6 +167,10 @@ one or more of the values:
.It Dv MSG_WAITALL Ta wait for full request or error
.It Dv MSG_DONTWAIT Ta do not block
.It Dv MSG_CMSG_CLOEXEC Ta set received fds close-on-exec
+.It Dv MSG_WAITFORONE Ta do not block after receiving the first message
+(only for
+.Fn recvmmsg
+)
.El
.Pp
The
@@ -158,6 +202,11 @@ is set to
This flag is not available in strict
.Tn ANSI
or C99 compilation mode.
+The
+.Dv MSG_WAITFORONE
+flag sets MSG_DONTWAIT after the first message has been received.
+This flag is only relevant for
+.Fn recvmmsg .
.Pp
The
.Fn recvmsg
@@ -290,9 +339,31 @@ control data were discarded due to lack of space in the buffer
for ancillary data.
.Dv MSG_OOB
is returned to indicate that expedited or out-of-band data were received.
+.Pp
+The
+.Fn recvmmsg
+system call uses the
+.Fa mmsghdr
+structure, defined as follows in the
+.In sys/socket.h
+header :
+.Bd -literal
+struct mmsghdr {
+ struct msghdr msg_hdr; /* message header */
+ ssize_t msg_len; /* message length */
+};
+.Ed
+.Pp
+On data reception the
+.Fa msg_len
+field is updated to the length of the received message.
.Sh RETURN VALUES
-These calls return the number of bytes received, or -1
-if an error occurred.
+These calls except
+.Fn recvmmsg
+return the number of bytes received.
+.Fn recvmmsg
+returns the number of messages received.
+A value of -1 is returned if an error occurred.
.Sh ERRORS
The calls fail if:
.Bl -tag -width Er
@@ -347,3 +418,7 @@ The
.Fn recv
function appeared in
.Bx 4.2 .
+The
+.Fn recvmmsg
+function appeared in
+.Fx 11.0 .
diff --git a/lib/libc/sys/send.2 b/lib/libc/sys/send.2
index 8fa2c64354d0..db2f4ee2a880 100644
--- a/lib/libc/sys/send.2
+++ b/lib/libc/sys/send.2
@@ -28,14 +28,15 @@
.\" From: @(#)send.2 8.2 (Berkeley) 2/21/94
.\" $FreeBSD$
.\"
-.Dd February 5, 2009
+.Dd January 29, 2016
.Dt SEND 2
.Os
.Sh NAME
.Nm send ,
.Nm sendto ,
-.Nm sendmsg
-.Nd send a message from a socket
+.Nm sendmsg ,
+.Nm sendmmsg
+.Nd send message(s) from a socket
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -47,25 +48,33 @@
.Fn sendto "int s" "const void *msg" "size_t len" "int flags" "const struct sockaddr *to" "socklen_t tolen"
.Ft ssize_t
.Fn sendmsg "int s" "const struct msghdr *msg" "int flags"
+.Ft ssize_t
+.Fn sendmmsg "int s" "struct mmsghdr * restrict msgvec" "size_t vlen" "int flags"
.Sh DESCRIPTION
The
.Fn send
-function,
+and
+.Fn sendmmsg
+functions,
and
.Fn sendto
and
.Fn sendmsg
system calls
-are used to transmit a message to another socket.
+are used to transmit one or more messages (with the
+.Fn sendmmsg
+call) to
+another socket.
The
.Fn send
function
may be used only when the socket is in a
.Em connected
state, while
-.Fn sendto
-and
+.Fn sendto ,
.Fn sendmsg
+and
+.Fn sendmmsg
may be used at any time.
.Pp
The address of the target is given by
@@ -81,6 +90,18 @@ underlying protocol, the error
is returned, and
the message is not transmitted.
.Pp
+The
+.Fn sendmmsg
+function sends multiple messages at a call.
+They are given by the
+.Fa msgvec
+vector along with
+.Fa vlen
+specifying the vector size.
+The number of octets sent per each message is placed in the
+.Fa msg_len
+field of each processed element of the vector after transmission.
+.Pp
No indication of failure to deliver is implicit in a
.Fn send .
Locally detected errors are indicated by a return value of -1.
@@ -138,14 +159,27 @@ See
.Xr recv 2
for a description of the
.Fa msghdr
+structure and the
+.Fa mmsghdr
structure.
.Sh RETURN VALUES
-The call returns the number of characters sent, or -1
-if an error occurred.
+The
+.Fn send ,
+.Fn sendto
+and
+.Fn sendmsg
+calls
+return the number of octets sent.
+The
+.Fn sendmmsg
+call returns the number of messages sent.
+If an error occurred a value of -1 is returned.
.Sh ERRORS
The
.Fn send
-function and
+and
+.Fn sendmmsg
+functions and
.Fn sendto
and
.Fn sendmsg
@@ -215,6 +249,10 @@ The
.Fn send
function appeared in
.Bx 4.2 .
+The
+.Fn sendmmsg
+function appeared in
+.Fx 11.0 .
.Sh BUGS
Because
.Fn sendmsg
diff --git a/lib/libc/tests/gen/Makefile b/lib/libc/tests/gen/Makefile
index b700312d8128..083097730cc0 100644
--- a/lib/libc/tests/gen/Makefile
+++ b/lib/libc/tests/gen/Makefile
@@ -11,6 +11,7 @@ ATF_TESTS_C+= ftw_test
ATF_TESTS_C+= popen_test
ATF_TESTS_C+= posix_spawn_test
ATF_TESTS_C+= wordexp_test
+ATF_TESTS_C+= dlopen_empty_test
# TODO: t_closefrom, t_cpuset, t_fmtcheck, t_randomid, t_sleep
# TODO: t_siginfo (fixes require further inspection)
diff --git a/lib/libc/tests/gen/dlopen_empty_test.c b/lib/libc/tests/gen/dlopen_empty_test.c
new file mode 100644
index 000000000000..42f9269a10b2
--- /dev/null
+++ b/lib/libc/tests/gen/dlopen_empty_test.c
@@ -0,0 +1,97 @@
+/*-
+ * Copyright (c) 2016 Maksym Sobolyev
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/stat.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+static const char *funname;
+static char *soname;
+
+static void
+sigsegv_handler(int sig __unused)
+{
+ unlink(soname);
+ free(soname);
+ atf_tc_fail("got SIGSEGV in the %s(3)", funname);
+}
+
+ATF_TC(dlopen_empty_test);
+ATF_TC_HEAD(dlopen_empty_test, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests the dlopen() of an empty file "
+ "returns an error");
+}
+ATF_TC_BODY(dlopen_empty_test, tc)
+{
+ char tempname[] = "/tmp/temp.XXXXXX";
+ char *fname;
+ int fd;
+ void *dlh;
+ struct sigaction act, oact;
+
+ fname = mktemp(tempname);
+ ATF_REQUIRE_MSG(fname != NULL, "mktemp failed; errno=%d", errno);
+ asprintf(&soname, "%s.so", fname);
+ ATF_REQUIRE_MSG(soname != NULL, "asprintf failed; errno=%d", ENOMEM);
+ fd = open(soname, O_WRONLY | O_CREAT | O_TRUNC, DEFFILEMODE);
+ ATF_REQUIRE_MSG(fd != -1, "open(\"%s\") failed; errno=%d", soname, errno);
+ close(fd);
+
+ act.sa_handler = sigsegv_handler;
+ act.sa_flags = 0;
+ sigemptyset(&act.sa_mask);
+ ATF_CHECK_MSG(sigaction(SIGSEGV, &act, &oact) != -1,
+ "sigaction() failed");
+
+ funname = "dlopen";
+ dlh = dlopen(soname, RTLD_LAZY);
+ if (dlh != NULL) {
+ funname = "dlclose";
+ dlclose(dlh);
+ }
+ ATF_REQUIRE_MSG(dlh == NULL, "dlopen(\"%s\") did not fail", soname);
+ unlink(soname);
+ free(soname);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, dlopen_empty_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libdevctl/devctl.3 b/lib/libdevctl/devctl.3
index be869f9d9868..b2734cf4aa30 100644
--- a/lib/libdevctl/devctl.3
+++ b/lib/libdevctl/devctl.3
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 26, 2014
+.Dd February 2, 2016
.Dt DEVCTL 3
.Os
.Sh NAME
@@ -35,6 +35,7 @@
.Nm devctl_disable ,
.Nm devctl_enable ,
.Nm devctl_resume ,
+.Nm devctl_set_driver ,
.Nm devctl_suspend
.Nd device control library
.Sh LIBRARY
@@ -52,9 +53,9 @@
.Ft int
.Fn devctl_resume "const char *device"
.Ft int
-.Fn devctl_suspend "const char *device"
-.Ft int
.Fn devctl_set_driver "const char *device" "const char *driver" "bool force"
+.Ft int
+.Fn devctl_suspend "const char *device"
.Sh DESCRIPTION
The
.Nm
@@ -287,7 +288,7 @@ The new device driver failed to attach.
The
.Nm
library first appeared in
-.Fx 11.0 .
+.Fx 10.3 .
.Sh BUGS
If a device is suspended individually via
.Fn devctl_suspend
diff --git a/lib/libmemstat/memstat_uma.c b/lib/libmemstat/memstat_uma.c
index 8e89585300b0..20cd5208fdd6 100644
--- a/lib/libmemstat/memstat_uma.c
+++ b/lib/libmemstat/memstat_uma.c
@@ -29,6 +29,7 @@
#include <sys/param.h>
#include <sys/cpuset.h>
#include <sys/sysctl.h>
+#include <sys/_task.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
diff --git a/lib/libsysdecode/syscallnames.c b/lib/libsysdecode/syscallnames.c
index cfe50a6a6ea9..4ec2cd76ac73 100644
--- a/lib/libsysdecode/syscallnames.c
+++ b/lib/libsysdecode/syscallnames.c
@@ -70,30 +70,30 @@ sysdecode_syscallname(enum sysdecode_abi abi, unsigned int code)
{
switch (abi) {
- case FREEBSD:
+ case SYSDECODE_ABI_FREEBSD:
if (code < nitems(syscallnames))
return (syscallnames[code]);
break;
#if defined(__amd64__) || defined(__powerpc64__)
- case FREEBSD32:
+ case SYSDECODE_ABI_FREEBSD32:
if (code < nitems(freebsd32_syscallnames))
return (freebsd32_syscallnames[code]);
break;
#endif
#if defined(__amd64__) || defined(__i386__)
- case LINUX:
+ case SYSDECODE_ABI_LINUX:
if (code < nitems(linux_syscallnames))
return (linux_syscallnames[code]);
break;
#endif
#ifdef __amd64__
- case LINUX32:
+ case SYSDECODE_ABI_LINUX32:
if (code < nitems(linux32_syscallnames))
return (linux32_syscallnames[code]);
break;
#endif
#if defined(__amd64__) || defined(__aarch64__)
- case CLOUDABI64:
+ case SYSDECODE_ABI_CLOUDABI64:
if (code < nitems(cloudabi64_syscallnames))
return (cloudabi64_syscallnames[code]);
break;
diff --git a/lib/libsysdecode/sysdecode.3 b/lib/libsysdecode/sysdecode.3
index 994d278fe001..f058f59c60cf 100644
--- a/lib/libsysdecode/sysdecode.3
+++ b/lib/libsysdecode/sysdecode.3
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 24, 2016
+.Dd January 29, 2016
.Dt SYSDECODE 3
.Os
.Sh NAME
@@ -44,23 +44,23 @@ The supported ABIs are named by the
.Vt enum sysdecode_abi
enumeration.
.Pp
-.Bl -tag -width "Li UNKNOWN_ABI" -compact
-.It Li FREEBSD
+.Bl -tag -width "Li SYSDECODE_ABI_CLOUDABI64" -compact
+.It Li SYSDECODE_ABI_FREEBSD
Native FreeBSD binaries.
Supported on all platforms.
-.It Li FREEBSD32
+.It Li SYSDECODE_ABI_FREEBSD32
32-bit FreeBSD binaries.
Supported on amd64 and powerpc64.
-.It Li LINUX
+.It Li SYSDECODE_ABI_LINUX
Linux binaries of the same platform.
Supported on amd64 and i386.
-.It Li LINUX32
+.It Li SYSDECODE_ABI_LINUX32
32-bit Linux binaries.
Supported on amd64.
-.It Li CLOUDABI64
+.It Li SYSDECODE_ABI_CLOUDABI64
64-bit CloudABI binaries.
Supported on aarch64 and amd64.
-.It Li UNKNOWN_ABI
+.It Li SYSDECODE_ABI_UNKNOWN
A placeholder for use when the ABI is not known.
.El
.Sh SEE ALSO
diff --git a/lib/libsysdecode/sysdecode.h b/lib/libsysdecode/sysdecode.h
index c2c3a9e801e5..fa00716826db 100644
--- a/lib/libsysdecode/sysdecode.h
+++ b/lib/libsysdecode/sysdecode.h
@@ -30,12 +30,12 @@
#define __SYSDECODE_H__
enum sysdecode_abi {
- UNKNOWN_ABI = 0,
- FREEBSD,
- FREEBSD32,
- LINUX,
- LINUX32,
- CLOUDABI64
+ SYSDECODE_ABI_UNKNOWN = 0,
+ SYSDECODE_ABI_FREEBSD,
+ SYSDECODE_ABI_FREEBSD32,
+ SYSDECODE_ABI_LINUX,
+ SYSDECODE_ABI_LINUX32,
+ SYSDECODE_ABI_CLOUDABI64
};
const char *sysdecode_ioctlname(unsigned long _val);
diff --git a/libexec/atrun/atrun.c b/libexec/atrun/atrun.c
index 1e25766c41b1..7b11e7bb1997 100644
--- a/libexec/atrun/atrun.c
+++ b/libexec/atrun/atrun.c
@@ -459,8 +459,9 @@ main(int argc, char *argv[])
int c;
int run_batch;
#ifdef __FreeBSD__
- size_t ncpu, ncpusz;
+ size_t ncpusz;
double load_avg = -1;
+ int ncpu;
#else
double load_avg = LOADAVG_MX;
#endif
diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c
index 6012015bcc28..f4f6f4221816 100644
--- a/libexec/rtld-elf/map_object.c
+++ b/libexec/rtld-elf/map_object.c
@@ -38,7 +38,7 @@
#include "debug.h"
#include "rtld.h"
-static Elf_Ehdr *get_elf_header(int, const char *);
+static Elf_Ehdr *get_elf_header(int, const char *, const struct stat *);
static int convert_prot(int); /* Elf flags -> mmap protection */
static int convert_flags(int); /* Elf flags -> mmap flags */
@@ -91,7 +91,7 @@ map_object(int fd, const char *path, const struct stat *sb)
char *note_map;
size_t note_map_len;
- hdr = get_elf_header(fd, path);
+ hdr = get_elf_header(fd, path, sb);
if (hdr == NULL)
return (NULL);
@@ -324,10 +324,16 @@ error:
}
static Elf_Ehdr *
-get_elf_header(int fd, const char *path)
+get_elf_header(int fd, const char *path, const struct stat *sbp)
{
Elf_Ehdr *hdr;
+ /* Make sure file has enough data for the ELF header */
+ if (sbp != NULL && sbp->st_size < sizeof(Elf_Ehdr)) {
+ _rtld_error("%s: invalid file format", path);
+ return (NULL);
+ }
+
hdr = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE | MAP_PREFAULT_READ,
fd, 0);
if (hdr == (Elf_Ehdr *)MAP_FAILED) {
diff --git a/sbin/ggate/ggated/Makefile b/sbin/ggate/ggated/Makefile
index af5c9bdf796a..83516c675261 100644
--- a/sbin/ggate/ggated/Makefile
+++ b/sbin/ggate/ggated/Makefile
@@ -6,7 +6,7 @@ PROG= ggated
MAN= ggated.8
SRCS= ggated.c ggate.c
-LIBADD= pthread
+LIBADD= pthread util
CFLAGS+= -I${.CURDIR}/../shared
diff --git a/sbin/ggate/ggated/ggated.8 b/sbin/ggate/ggated/ggated.8
index dd6109aa61ef..f73e8a618eb1 100644
--- a/sbin/ggate/ggated/ggated.8
+++ b/sbin/ggate/ggated/ggated.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 14, 2015
+.Dd January 27, 2016
.Dt GGATED 8
.Os
.Sh NAME
@@ -37,6 +37,7 @@
.Op Fl v
.Op Fl a Ar address
.Op Fl p Ar port
+.Op Fl F Ar pidfile
.Op Fl R Ar rcvbuf
.Op Fl S Ar sndbuf
.Op Ar "exports file"
@@ -67,6 +68,10 @@ Port on which
.Nm
listens for connections.
Default is 3080.
+.It Fl F Ar pidfile
+PID file that
+.Nm
+uses.
.It Fl R Ar rcvbuf
Size of receive buffer to use.
Default is 131072 (128kB).
@@ -86,6 +91,13 @@ The format of an exports file is as follows:
1.2.3.0/24 RW /tmp/test.img
hostname WO /tmp/image
.Ed
+.Sh FILES
+.Bl -tag -width ".Pa /var/run/ggated.pid" -compact
+.It Pa /var/run/ggated.pid
+The default location of the
+.Nm
+PID file.
+.El
.Sh EXIT STATUS
Exit status is 0 on success, or 1 if the command fails.
To get details about the failure,
diff --git a/sbin/ggate/ggated/ggated.c b/sbin/ggate/ggated/ggated.c
index a340f01b1b5f..e234cb57b290 100644
--- a/sbin/ggate/ggated/ggated.c
+++ b/sbin/ggate/ggated/ggated.c
@@ -26,32 +26,34 @@
* $FreeBSD$
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <pthread.h>
#include <sys/param.h>
-#include <sys/queue.h>
+#include <sys/bio.h>
+#include <sys/disk.h>
#include <sys/endian.h>
-#include <sys/socket.h>
#include <sys/ioctl.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
-#include <sys/disk.h>
-#include <sys/bio.h>
+#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <signal.h>
#include <assert.h>
#include <err.h>
#include <errno.h>
-#include <string.h>
+#include <fcntl.h>
#include <libgen.h>
-#include <syslog.h>
+#include <libutil.h>
+#include <paths.h>
+#include <pthread.h>
+#include <signal.h>
#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
#include "ggate.h"
@@ -110,8 +112,8 @@ static void
usage(void)
{
- fprintf(stderr, "usage: %s [-nv] [-a address] [-p port] [-R rcvbuf] "
- "[-S sndbuf] [exports file]\n", getprogname());
+ fprintf(stderr, "usage: %s [-nv] [-a address] [-F pidfile] [-p port] "
+ "[-R rcvbuf] [-S sndbuf] [exports file]\n", getprogname());
exit(EXIT_FAILURE);
}
@@ -946,20 +948,18 @@ huphandler(int sig __unused)
int
main(int argc, char *argv[])
{
+ const char *ggated_pidfile = _PATH_VARRUN "/ggated.pid";
+ struct pidfh *pfh;
struct sockaddr_in serv;
struct sockaddr from;
socklen_t fromlen;
- int sfd, tmpsfd;
+ pid_t otherpid;
+ int ch, sfd, tmpsfd;
unsigned port;
bindaddr = htonl(INADDR_ANY);
port = G_GATE_PORT;
- for (;;) {
- int ch;
-
- ch = getopt(argc, argv, "a:hnp:R:S:v");
- if (ch == -1)
- break;
+ while ((ch = getopt(argc, argv, "a:hnp:F:R:S:v")) != -1) {
switch (ch) {
case 'a':
bindaddr = g_gate_str2ip(optarg);
@@ -968,6 +968,9 @@ main(int argc, char *argv[])
"Invalid IP/host name to bind to.");
}
break;
+ case 'F':
+ ggated_pidfile = optarg;
+ break;
case 'n':
nagle = 0;
break;
@@ -1004,12 +1007,23 @@ main(int argc, char *argv[])
exports_file = argv[0];
exports_get();
+ pfh = pidfile_open(ggated_pidfile, 0600, &otherpid);
+ if (pfh == NULL) {
+ if (errno == EEXIST) {
+ errx(EXIT_FAILURE, "Daemon already running, pid: %jd.",
+ (intmax_t)otherpid);
+ }
+ err(EXIT_FAILURE, "Cannot open/create pidfile");
+ }
+
if (!g_gate_verbose) {
/* Run in daemon mode. */
if (daemon(0, 0) == -1)
g_gate_xlog("Cannot daemonize: %s", strerror(errno));
}
+ pidfile_write(pfh);
+
signal(SIGCHLD, SIG_IGN);
sfd = socket(AF_INET, SOCK_STREAM, 0);
@@ -1046,5 +1060,6 @@ main(int argc, char *argv[])
close(tmpsfd);
}
close(sfd);
+ pidfile_remove(pfh);
exit(EXIT_SUCCESS);
}
diff --git a/sbin/nvmecontrol/Makefile b/sbin/nvmecontrol/Makefile
index ea60da3c2941..e8a23719a2a7 100644
--- a/sbin/nvmecontrol/Makefile
+++ b/sbin/nvmecontrol/Makefile
@@ -2,7 +2,7 @@
PROG= nvmecontrol
SRCS= nvmecontrol.c devlist.c firmware.c identify.c logpage.c \
- perftest.c reset.c nvme_util.c
+ perftest.c reset.c nvme_util.c power.c
MAN= nvmecontrol.8
.PATH: ${.CURDIR}/../../sys/dev/nvme
diff --git a/sbin/nvmecontrol/nvmecontrol.8 b/sbin/nvmecontrol/nvmecontrol.8
index 3b4b5c23aef3..ae8132ec5cbc 100644
--- a/sbin/nvmecontrol/nvmecontrol.8
+++ b/sbin/nvmecontrol/nvmecontrol.8
@@ -70,6 +70,11 @@
.Op Fl f Ar path_to_firmware
.Op Fl a
.Aq device id
+.Nm
+.Ic power
+.Op Fl l
+.Op Fl p power_state
+.Op fl w workload_hint
.Sh DESCRIPTION
NVM Express (NVMe) is a storage protocol standard, for SSDs and other
high-speed storage devices over PCI Express.
@@ -120,6 +125,18 @@ Activate the firmware in slot 4 of the nvme0 controller on the next reset.
.Pp
Download the firmware image contained in "/tmp/nvme_firmware" to slot 7 of the
nvme0 controller and activate it on the next reset.
+.Pp
+.Dl nvmecontrol power -l nvme0
+.Pp
+List all the current power modes.
+.Pp
+.Dl nvmecontrol power -p 3 nvme0
+.Pp
+Set the current power mode.
+.Pp
+.Dl nvmecontrol power nvme0
+.Pp
+Get the current power mode.
.Sh AUTHORS
.An -nosplit
.Nm
diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c
index 4dee1909280a..cd7c19d0165d 100644
--- a/sbin/nvmecontrol/nvmecontrol.c
+++ b/sbin/nvmecontrol/nvmecontrol.c
@@ -58,6 +58,7 @@ static struct nvme_function {
{"reset", reset, RESET_USAGE},
{"logpage", logpage, LOGPAGE_USAGE},
{"firmware", firmware, FIRMWARE_USAGE},
+ {"power", power, POWER_USAGE},
{NULL, NULL, NULL},
};
diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h
index 8401dd7ccda3..b3cecd26dcea 100644
--- a/sbin/nvmecontrol/nvmecontrol.h
+++ b/sbin/nvmecontrol/nvmecontrol.h
@@ -55,12 +55,16 @@
#define FIRMWARE_USAGE \
" nvmecontrol firmware [-s slot] [-f path_to_firmware] [-a] <controller id>\n"
+#define POWER_USAGE \
+" nvmecontrol power [-l] [-p new-state [-w workload-hint]] <controller id>\n"
+
void devlist(int argc, char *argv[]);
void identify(int argc, char *argv[]);
void perftest(int argc, char *argv[]);
void reset(int argc, char *argv[]);
void logpage(int argc, char *argv[]);
void firmware(int argc, char *argv[]);
+void power(int argc, char *argv[]);
int open_dev(const char *str, int *fd, int show_error, int exit_on_error);
void parse_ns_str(const char *ns_str, char *ctrlr_str, int *nsid);
diff --git a/sbin/nvmecontrol/power.c b/sbin/nvmecontrol/power.c
new file mode 100644
index 000000000000..e681ccd14dcc
--- /dev/null
+++ b/sbin/nvmecontrol/power.c
@@ -0,0 +1,185 @@
+/*-
+ * Copyright (c) 2016 Netflix, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/ioccom.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "nvmecontrol.h"
+
+_Static_assert(sizeof(struct nvme_power_state) == 256 / NBBY,
+ "nvme_power_state size wrong");
+
+static void
+power_usage(void)
+{
+ fprintf(stderr, "usage:\n");
+ fprintf(stderr, POWER_USAGE);
+ exit(1);
+}
+
+static void
+power_list_one(int i, struct nvme_power_state *nps)
+{
+ int mpower, apower, ipower;
+
+ mpower = nps->mp;
+ if (nps->mps == 0)
+ mpower *= 100;
+ ipower = nps->idlp;
+ if (nps->ips == 1)
+ ipower *= 100;
+ apower = nps->actp;
+ if (nps->aps == 1)
+ apower *= 100;
+ printf("%2d: %2d.%04dW%c %3d.%03dms %3d.%03dms %2d %2d %2d %2d %2d.%04dW %2d.%04dW %d\n",
+ i, mpower / 10000, mpower % 10000,
+ nps->nops ? '*' : ' ', nps->enlat / 1000, nps->enlat % 1000,
+ nps->exlat / 1000, nps->exlat % 1000, nps->rrt, nps->rrl,
+ nps->rwt, nps->rwl, ipower / 10000, ipower % 10000,
+ apower / 10000, apower % 10000, nps->apw);
+}
+
+static void
+power_list(struct nvme_controller_data *cdata)
+{
+ int i;
+
+ printf("\nPower States Supported: %d\n\n", cdata->npss + 1);
+ printf(" # Max pwr Enter Lat Exit Lat RT RL WT WL Idle Pwr Act Pwr Workloadd\n");
+ printf("-- -------- --------- --------- -- -- -- -- -------- -------- --\n");
+ for (i = 0; i <= cdata->npss; i++)
+ power_list_one(i, &cdata->power_state[i]);
+}
+
+static void
+power_set(int fd, int power, int workload, int perm)
+{
+ struct nvme_pt_command pt;
+ uint32_t p;
+
+ p = perm ? (1u << 31) : 0;
+ memset(&pt, 0, sizeof(pt));
+ pt.cmd.opc = NVME_OPC_SET_FEATURES;
+ pt.cmd.cdw10 = NVME_FEAT_POWER_MANAGEMENT | p;
+ pt.cmd.cdw11 = power | (workload << 5);
+
+ if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
+ err(1, "set feature power mgmt request failed");
+
+ if (nvme_completion_is_error(&pt.cpl))
+ errx(1, "set feature power mgmt request returned error");
+}
+
+static void
+power_show(int fd)
+{
+ struct nvme_pt_command pt;
+
+ memset(&pt, 0, sizeof(pt));
+ pt.cmd.opc = NVME_OPC_GET_FEATURES;
+ pt.cmd.cdw10 = NVME_FEAT_POWER_MANAGEMENT;
+
+ if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
+ err(1, "set feature power mgmt request failed");
+
+ if (nvme_completion_is_error(&pt.cpl))
+ errx(1, "set feature power mgmt request returned error");
+
+ printf("Current Power Mode is %d\n", pt.cpl.cdw0);
+}
+
+void
+power(int argc, char *argv[])
+{
+ struct nvme_controller_data cdata;
+ int ch, listflag = 0, powerflag = 0, power = 0, fd;
+ int workload = 0;
+ char *end;
+
+ while ((ch = getopt(argc, argv, "lp:w:")) != -1) {
+ switch ((char)ch) {
+ case 'l':
+ listflag = 1;
+ break;
+ case 'p':
+ powerflag = 1;
+ power = strtol(optarg, &end, 0);
+ if (*end != '\0') {
+ fprintf(stderr, "Invalid power state number: %s\n", optarg);
+ power_usage();
+ }
+ break;
+ case 'w':
+ workload = strtol(optarg, &end, 0);
+ if (*end != '\0') {
+ fprintf(stderr, "Invalid workload hint: %s\n", optarg);
+ power_usage();
+ }
+ break;
+ default:
+ power_usage();
+ }
+ }
+
+ /* Check that a controller was specified. */
+ if (optind >= argc)
+ power_usage();
+
+ if (listflag && powerflag) {
+ fprintf(stderr, "Can't set power and list power states\n");
+ power_usage();
+ }
+
+ open_dev(argv[optind], &fd, 1, 1);
+ read_controller_data(fd, &cdata);
+
+ if (listflag) {
+ power_list(&cdata);
+ goto out;
+ }
+
+ if (powerflag) {
+ power_set(fd, power, workload, 0);
+ goto out;
+ }
+ power_show(fd);
+
+out:
+ close(fd);
+ exit(0);
+}
diff --git a/sbin/pfctl/pf_print_state.c b/sbin/pfctl/pf_print_state.c
index 46d4523373d5..346e6236f320 100644
--- a/sbin/pfctl/pf_print_state.c
+++ b/sbin/pfctl/pf_print_state.c
@@ -208,22 +208,30 @@ void
print_state(struct pfsync_state *s, int opts)
{
struct pfsync_state_peer *src, *dst;
- struct pfsync_state_key *sk, *nk;
+ struct pfsync_state_key *key, *sk, *nk;
struct protoent *p;
int min, sec;
+#ifndef __NO_STRICT_ALIGNMENT
+ struct pfsync_state_key aligned_key[2];
+
+ bcopy(&s->key, aligned_key, sizeof(aligned_key));
+ key = aligned_key;
+#else
+ key = s->key;
+#endif
if (s->direction == PF_OUT) {
src = &s->src;
dst = &s->dst;
- sk = &s->key[PF_SK_STACK];
- nk = &s->key[PF_SK_WIRE];
+ sk = &key[PF_SK_STACK];
+ nk = &key[PF_SK_WIRE];
if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
sk->port[0] = nk->port[0];
} else {
src = &s->dst;
dst = &s->src;
- sk = &s->key[PF_SK_WIRE];
- nk = &s->key[PF_SK_STACK];
+ sk = &key[PF_SK_WIRE];
+ nk = &key[PF_SK_STACK];
if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
sk->port[1] = nk->port[1];
}
diff --git a/sbin/rcorder/rcorder.c b/sbin/rcorder/rcorder.c
index 1d10a40d961a..37faa2470e55 100644
--- a/sbin/rcorder/rcorder.c
+++ b/sbin/rcorder/rcorder.c
@@ -701,7 +701,7 @@ keep_ok(filenode *fnode)
static void
do_file(filenode *fnode)
{
- f_reqnode *r, *r_tmp;
+ f_reqnode *r;
f_provnode *p, *p_tmp;
provnode *pnode;
int was_set;
@@ -728,13 +728,8 @@ do_file(filenode *fnode)
*/
r = fnode->req_list;
while (r != NULL) {
- r_tmp = r;
satisfy_req(r, fnode->filename);
r = r->next;
-#if 0
- if (was_set == 0)
- free(r_tmp);
-#endif
}
fnode->req_list = NULL;
diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c
index f58143179c2f..03b2b09bf742 100644
--- a/sbin/swapon/swapon.c
+++ b/sbin/swapon/swapon.c
@@ -315,7 +315,7 @@ swap_on_geli_args(const char *mntops)
const char *aalgo, *ealgo, *keylen_str, *sectorsize_str;
const char *aflag, *eflag, *lflag, *Tflag, *sflag;
char *p, *args, *token, *string, *ops;
- int argsize, pagesize;
+ int pagesize;
size_t pagesize_len;
u_long ul;
@@ -389,7 +389,7 @@ swap_on_geli_args(const char *mntops)
sectorsize_str = p;
}
- argsize = asprintf(&args, "%s%s%s%s%s%s%s%s%s -d",
+ (void)asprintf(&args, "%s%s%s%s%s%s%s%s%s -d",
aflag, aalgo, eflag, ealgo, lflag, keylen_str, Tflag,
sflag, sectorsize_str);
diff --git a/secure/lib/libcrypto/Makefile.inc b/secure/lib/libcrypto/Makefile.inc
index 2eb862f20423..7b1401ff3975 100644
--- a/secure/lib/libcrypto/Makefile.inc
+++ b/secure/lib/libcrypto/Makefile.inc
@@ -3,8 +3,8 @@
.include <bsd.own.mk>
# OpenSSL version used for manual page generation
-OPENSSL_VER= 1.0.2e
-OPENSSL_DATE= 2015-12-03
+OPENSSL_VER= 1.0.2f
+OPENSSL_DATE= 2016-01-28
LCRYPTO_SRC= ${.CURDIR}/../../../crypto/openssl
LCRYPTO_DOC= ${LCRYPTO_SRC}/doc
diff --git a/secure/lib/libcrypto/man/ASN1_OBJECT_new.3 b/secure/lib/libcrypto/man/ASN1_OBJECT_new.3
index 67e7e4857231..0d7709d27aec 100644
--- a/secure/lib/libcrypto/man/ASN1_OBJECT_new.3
+++ b/secure/lib/libcrypto/man/ASN1_OBJECT_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ASN1_OBJECT_new 3"
-.TH ASN1_OBJECT_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ASN1_OBJECT_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ASN1_STRING_length.3 b/secure/lib/libcrypto/man/ASN1_STRING_length.3
index e2eb45ccea14..5ab4b086e883 100644
--- a/secure/lib/libcrypto/man/ASN1_STRING_length.3
+++ b/secure/lib/libcrypto/man/ASN1_STRING_length.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ASN1_STRING_length 3"
-.TH ASN1_STRING_length 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ASN1_STRING_length 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ASN1_STRING_new.3 b/secure/lib/libcrypto/man/ASN1_STRING_new.3
index f0c2c0a96116..1c0ca345906c 100644
--- a/secure/lib/libcrypto/man/ASN1_STRING_new.3
+++ b/secure/lib/libcrypto/man/ASN1_STRING_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ASN1_STRING_new 3"
-.TH ASN1_STRING_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ASN1_STRING_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ASN1_STRING_print_ex.3 b/secure/lib/libcrypto/man/ASN1_STRING_print_ex.3
index cc97d99616a2..0ef8712f8fff 100644
--- a/secure/lib/libcrypto/man/ASN1_STRING_print_ex.3
+++ b/secure/lib/libcrypto/man/ASN1_STRING_print_ex.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ASN1_STRING_print_ex 3"
-.TH ASN1_STRING_print_ex 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ASN1_STRING_print_ex 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ASN1_TIME_set.3 b/secure/lib/libcrypto/man/ASN1_TIME_set.3
index a7339697cb18..6cb1b1b47b8e 100644
--- a/secure/lib/libcrypto/man/ASN1_TIME_set.3
+++ b/secure/lib/libcrypto/man/ASN1_TIME_set.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ASN1_TIME_set 3"
-.TH ASN1_TIME_set 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ASN1_TIME_set 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ASN1_generate_nconf.3 b/secure/lib/libcrypto/man/ASN1_generate_nconf.3
index 37f279d6ce0a..1300cacf5c0b 100644
--- a/secure/lib/libcrypto/man/ASN1_generate_nconf.3
+++ b/secure/lib/libcrypto/man/ASN1_generate_nconf.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ASN1_generate_nconf 3"
-.TH ASN1_generate_nconf 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ASN1_generate_nconf 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_ctrl.3 b/secure/lib/libcrypto/man/BIO_ctrl.3
index 784d3072fa33..8fc642ab1bfd 100644
--- a/secure/lib/libcrypto/man/BIO_ctrl.3
+++ b/secure/lib/libcrypto/man/BIO_ctrl.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_ctrl 3"
-.TH BIO_ctrl 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_ctrl 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_f_base64.3 b/secure/lib/libcrypto/man/BIO_f_base64.3
index fb804bd7c20d..7922ffbd261a 100644
--- a/secure/lib/libcrypto/man/BIO_f_base64.3
+++ b/secure/lib/libcrypto/man/BIO_f_base64.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_f_base64 3"
-.TH BIO_f_base64 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_f_base64 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_f_buffer.3 b/secure/lib/libcrypto/man/BIO_f_buffer.3
index ace920f2a07a..65bf13c9f752 100644
--- a/secure/lib/libcrypto/man/BIO_f_buffer.3
+++ b/secure/lib/libcrypto/man/BIO_f_buffer.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_f_buffer 3"
-.TH BIO_f_buffer 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_f_buffer 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_f_cipher.3 b/secure/lib/libcrypto/man/BIO_f_cipher.3
index 46aa9aaeb492..44c7a36ebf2e 100644
--- a/secure/lib/libcrypto/man/BIO_f_cipher.3
+++ b/secure/lib/libcrypto/man/BIO_f_cipher.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_f_cipher 3"
-.TH BIO_f_cipher 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_f_cipher 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_f_md.3 b/secure/lib/libcrypto/man/BIO_f_md.3
index 39688fb4f76b..89d648a79755 100644
--- a/secure/lib/libcrypto/man/BIO_f_md.3
+++ b/secure/lib/libcrypto/man/BIO_f_md.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_f_md 3"
-.TH BIO_f_md 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_f_md 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_f_null.3 b/secure/lib/libcrypto/man/BIO_f_null.3
index 6fbb01072534..31c56d02308b 100644
--- a/secure/lib/libcrypto/man/BIO_f_null.3
+++ b/secure/lib/libcrypto/man/BIO_f_null.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_f_null 3"
-.TH BIO_f_null 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_f_null 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_f_ssl.3 b/secure/lib/libcrypto/man/BIO_f_ssl.3
index 6bed4fedf900..b8dec88a6749 100644
--- a/secure/lib/libcrypto/man/BIO_f_ssl.3
+++ b/secure/lib/libcrypto/man/BIO_f_ssl.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_f_ssl 3"
-.TH BIO_f_ssl 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_f_ssl 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_find_type.3 b/secure/lib/libcrypto/man/BIO_find_type.3
index 0ad3bb452a62..ea022e660c2e 100644
--- a/secure/lib/libcrypto/man/BIO_find_type.3
+++ b/secure/lib/libcrypto/man/BIO_find_type.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_find_type 3"
-.TH BIO_find_type 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_find_type 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_new.3 b/secure/lib/libcrypto/man/BIO_new.3
index dc11b3038fca..80f390692af3 100644
--- a/secure/lib/libcrypto/man/BIO_new.3
+++ b/secure/lib/libcrypto/man/BIO_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_new 3"
-.TH BIO_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_new_CMS.3 b/secure/lib/libcrypto/man/BIO_new_CMS.3
index 2b4c7a30433c..7841215a9db3 100644
--- a/secure/lib/libcrypto/man/BIO_new_CMS.3
+++ b/secure/lib/libcrypto/man/BIO_new_CMS.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_new_CMS 3"
-.TH BIO_new_CMS 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_new_CMS 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_push.3 b/secure/lib/libcrypto/man/BIO_push.3
index d9e132aaef39..3dc3a90cfa24 100644
--- a/secure/lib/libcrypto/man/BIO_push.3
+++ b/secure/lib/libcrypto/man/BIO_push.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_push 3"
-.TH BIO_push 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_push 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_read.3 b/secure/lib/libcrypto/man/BIO_read.3
index 54a99745abb7..5e621b3e1b5e 100644
--- a/secure/lib/libcrypto/man/BIO_read.3
+++ b/secure/lib/libcrypto/man/BIO_read.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_read 3"
-.TH BIO_read 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_read 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_s_accept.3 b/secure/lib/libcrypto/man/BIO_s_accept.3
index 8dfb1271b7fc..d454bf9c3781 100644
--- a/secure/lib/libcrypto/man/BIO_s_accept.3
+++ b/secure/lib/libcrypto/man/BIO_s_accept.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_s_accept 3"
-.TH BIO_s_accept 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_s_accept 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_s_bio.3 b/secure/lib/libcrypto/man/BIO_s_bio.3
index a94fbfdc55b9..353124b3a955 100644
--- a/secure/lib/libcrypto/man/BIO_s_bio.3
+++ b/secure/lib/libcrypto/man/BIO_s_bio.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_s_bio 3"
-.TH BIO_s_bio 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_s_bio 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_s_connect.3 b/secure/lib/libcrypto/man/BIO_s_connect.3
index 8e545f9cde37..6b258391628d 100644
--- a/secure/lib/libcrypto/man/BIO_s_connect.3
+++ b/secure/lib/libcrypto/man/BIO_s_connect.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_s_connect 3"
-.TH BIO_s_connect 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_s_connect 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@@ -158,8 +158,8 @@ BIO_set_nbio, BIO_do_connect \- connect BIO
\& long BIO_set_conn_int_port(BIO *b, char *port);
\& char *BIO_get_conn_hostname(BIO *b);
\& char *BIO_get_conn_port(BIO *b);
-\& char *BIO_get_conn_ip(BIO *b, dummy);
-\& long BIO_get_conn_int_port(BIO *b, int port);
+\& char *BIO_get_conn_ip(BIO *b);
+\& long BIO_get_conn_int_port(BIO *b);
\&
\& long BIO_set_nbio(BIO *b, long n);
\&
diff --git a/secure/lib/libcrypto/man/BIO_s_fd.3 b/secure/lib/libcrypto/man/BIO_s_fd.3
index e606e7428c36..43386d7b0c5c 100644
--- a/secure/lib/libcrypto/man/BIO_s_fd.3
+++ b/secure/lib/libcrypto/man/BIO_s_fd.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_s_fd 3"
-.TH BIO_s_fd 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_s_fd 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_s_file.3 b/secure/lib/libcrypto/man/BIO_s_file.3
index 0923f56e52c2..371eff0fb711 100644
--- a/secure/lib/libcrypto/man/BIO_s_file.3
+++ b/secure/lib/libcrypto/man/BIO_s_file.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_s_file 3"
-.TH BIO_s_file 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_s_file 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_s_mem.3 b/secure/lib/libcrypto/man/BIO_s_mem.3
index cc1131e7685c..fe7b4acd9009 100644
--- a/secure/lib/libcrypto/man/BIO_s_mem.3
+++ b/secure/lib/libcrypto/man/BIO_s_mem.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_s_mem 3"
-.TH BIO_s_mem 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_s_mem 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_s_null.3 b/secure/lib/libcrypto/man/BIO_s_null.3
index 0bc54c655ce1..ee4b3a13264d 100644
--- a/secure/lib/libcrypto/man/BIO_s_null.3
+++ b/secure/lib/libcrypto/man/BIO_s_null.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_s_null 3"
-.TH BIO_s_null 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_s_null 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_s_socket.3 b/secure/lib/libcrypto/man/BIO_s_socket.3
index c42526688873..4321e8124aa1 100644
--- a/secure/lib/libcrypto/man/BIO_s_socket.3
+++ b/secure/lib/libcrypto/man/BIO_s_socket.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_s_socket 3"
-.TH BIO_s_socket 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_s_socket 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_set_callback.3 b/secure/lib/libcrypto/man/BIO_set_callback.3
index 59a7d979fb5a..2ea32575d337 100644
--- a/secure/lib/libcrypto/man/BIO_set_callback.3
+++ b/secure/lib/libcrypto/man/BIO_set_callback.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_set_callback 3"
-.TH BIO_set_callback 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_set_callback 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BIO_should_retry.3 b/secure/lib/libcrypto/man/BIO_should_retry.3
index fc3aeadc8d05..7dc7ac6cc3aa 100644
--- a/secure/lib/libcrypto/man/BIO_should_retry.3
+++ b/secure/lib/libcrypto/man/BIO_should_retry.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BIO_should_retry 3"
-.TH BIO_should_retry 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BIO_should_retry 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_BLINDING_new.3 b/secure/lib/libcrypto/man/BN_BLINDING_new.3
index 4029d060ae74..84ef4e40a921 100644
--- a/secure/lib/libcrypto/man/BN_BLINDING_new.3
+++ b/secure/lib/libcrypto/man/BN_BLINDING_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_BLINDING_new 3"
-.TH BN_BLINDING_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_BLINDING_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_CTX_new.3 b/secure/lib/libcrypto/man/BN_CTX_new.3
index f3424a2a8e67..b56c161b4fa9 100644
--- a/secure/lib/libcrypto/man/BN_CTX_new.3
+++ b/secure/lib/libcrypto/man/BN_CTX_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_CTX_new 3"
-.TH BN_CTX_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_CTX_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_CTX_start.3 b/secure/lib/libcrypto/man/BN_CTX_start.3
index e61bec2beefd..4a92f6d3a5ea 100644
--- a/secure/lib/libcrypto/man/BN_CTX_start.3
+++ b/secure/lib/libcrypto/man/BN_CTX_start.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_CTX_start 3"
-.TH BN_CTX_start 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_CTX_start 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_add.3 b/secure/lib/libcrypto/man/BN_add.3
index adbfe1f51724..c674dc5a6ebb 100644
--- a/secure/lib/libcrypto/man/BN_add.3
+++ b/secure/lib/libcrypto/man/BN_add.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_add 3"
-.TH BN_add 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_add 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_add_word.3 b/secure/lib/libcrypto/man/BN_add_word.3
index 1180231411b2..ec19be41498f 100644
--- a/secure/lib/libcrypto/man/BN_add_word.3
+++ b/secure/lib/libcrypto/man/BN_add_word.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_add_word 3"
-.TH BN_add_word 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_add_word 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_bn2bin.3 b/secure/lib/libcrypto/man/BN_bn2bin.3
index 318afe60b28a..bc88eb8af4ab 100644
--- a/secure/lib/libcrypto/man/BN_bn2bin.3
+++ b/secure/lib/libcrypto/man/BN_bn2bin.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_bn2bin 3"
-.TH BN_bn2bin 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_bn2bin 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_cmp.3 b/secure/lib/libcrypto/man/BN_cmp.3
index 1fe36bb164ec..5cc7945cb85a 100644
--- a/secure/lib/libcrypto/man/BN_cmp.3
+++ b/secure/lib/libcrypto/man/BN_cmp.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_cmp 3"
-.TH BN_cmp 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_cmp 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_copy.3 b/secure/lib/libcrypto/man/BN_copy.3
index e90cb656f362..f371ea9a086b 100644
--- a/secure/lib/libcrypto/man/BN_copy.3
+++ b/secure/lib/libcrypto/man/BN_copy.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_copy 3"
-.TH BN_copy 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_copy 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_generate_prime.3 b/secure/lib/libcrypto/man/BN_generate_prime.3
index 7b30f6e2e9ce..238a729480d5 100644
--- a/secure/lib/libcrypto/man/BN_generate_prime.3
+++ b/secure/lib/libcrypto/man/BN_generate_prime.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_generate_prime 3"
-.TH BN_generate_prime 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_generate_prime 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_mod_inverse.3 b/secure/lib/libcrypto/man/BN_mod_inverse.3
index 360547ac349d..4f4d7acc90f0 100644
--- a/secure/lib/libcrypto/man/BN_mod_inverse.3
+++ b/secure/lib/libcrypto/man/BN_mod_inverse.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_mod_inverse 3"
-.TH BN_mod_inverse 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_mod_inverse 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_mod_mul_montgomery.3 b/secure/lib/libcrypto/man/BN_mod_mul_montgomery.3
index 89e295b3a90c..43d4269f4989 100644
--- a/secure/lib/libcrypto/man/BN_mod_mul_montgomery.3
+++ b/secure/lib/libcrypto/man/BN_mod_mul_montgomery.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_mod_mul_montgomery 3"
-.TH BN_mod_mul_montgomery 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_mod_mul_montgomery 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_mod_mul_reciprocal.3 b/secure/lib/libcrypto/man/BN_mod_mul_reciprocal.3
index a486c2bbc6b5..a584766e76f7 100644
--- a/secure/lib/libcrypto/man/BN_mod_mul_reciprocal.3
+++ b/secure/lib/libcrypto/man/BN_mod_mul_reciprocal.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_mod_mul_reciprocal 3"
-.TH BN_mod_mul_reciprocal 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_mod_mul_reciprocal 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_new.3 b/secure/lib/libcrypto/man/BN_new.3
index ccedaa8e6d91..a9f4c8185d07 100644
--- a/secure/lib/libcrypto/man/BN_new.3
+++ b/secure/lib/libcrypto/man/BN_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_new 3"
-.TH BN_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_num_bytes.3 b/secure/lib/libcrypto/man/BN_num_bytes.3
index fa1407e91c21..e134b243637c 100644
--- a/secure/lib/libcrypto/man/BN_num_bytes.3
+++ b/secure/lib/libcrypto/man/BN_num_bytes.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_num_bytes 3"
-.TH BN_num_bytes 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_num_bytes 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_rand.3 b/secure/lib/libcrypto/man/BN_rand.3
index 26837ae27c9f..7725cd79f0c1 100644
--- a/secure/lib/libcrypto/man/BN_rand.3
+++ b/secure/lib/libcrypto/man/BN_rand.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_rand 3"
-.TH BN_rand 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_rand 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_set_bit.3 b/secure/lib/libcrypto/man/BN_set_bit.3
index 75c6ce7bf0fc..f2a446c59f02 100644
--- a/secure/lib/libcrypto/man/BN_set_bit.3
+++ b/secure/lib/libcrypto/man/BN_set_bit.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_set_bit 3"
-.TH BN_set_bit 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_set_bit 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_swap.3 b/secure/lib/libcrypto/man/BN_swap.3
index fceba7fcc9da..568625059c40 100644
--- a/secure/lib/libcrypto/man/BN_swap.3
+++ b/secure/lib/libcrypto/man/BN_swap.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_swap 3"
-.TH BN_swap 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_swap 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/BN_zero.3 b/secure/lib/libcrypto/man/BN_zero.3
index a3ede143b0e9..3db136551abf 100644
--- a/secure/lib/libcrypto/man/BN_zero.3
+++ b/secure/lib/libcrypto/man/BN_zero.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "BN_zero 3"
-.TH BN_zero 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH BN_zero 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_add0_cert.3 b/secure/lib/libcrypto/man/CMS_add0_cert.3
index 0835fd851b26..283f3d729496 100644
--- a/secure/lib/libcrypto/man/CMS_add0_cert.3
+++ b/secure/lib/libcrypto/man/CMS_add0_cert.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_add0_cert 3"
-.TH CMS_add0_cert 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_add0_cert 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_add1_recipient_cert.3 b/secure/lib/libcrypto/man/CMS_add1_recipient_cert.3
index 23b9801ea163..d4b96009d755 100644
--- a/secure/lib/libcrypto/man/CMS_add1_recipient_cert.3
+++ b/secure/lib/libcrypto/man/CMS_add1_recipient_cert.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_add1_recipient_cert 3"
-.TH CMS_add1_recipient_cert 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_add1_recipient_cert 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_add1_signer.3 b/secure/lib/libcrypto/man/CMS_add1_signer.3
index 7183e28dba68..75a65a7624a5 100644
--- a/secure/lib/libcrypto/man/CMS_add1_signer.3
+++ b/secure/lib/libcrypto/man/CMS_add1_signer.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_add1_signer 3"
-.TH CMS_add1_signer 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_add1_signer 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_compress.3 b/secure/lib/libcrypto/man/CMS_compress.3
index 7ae678e30320..b5394799883a 100644
--- a/secure/lib/libcrypto/man/CMS_compress.3
+++ b/secure/lib/libcrypto/man/CMS_compress.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_compress 3"
-.TH CMS_compress 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_compress 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_decrypt.3 b/secure/lib/libcrypto/man/CMS_decrypt.3
index 205144bdd65c..ce0eacdffa9d 100644
--- a/secure/lib/libcrypto/man/CMS_decrypt.3
+++ b/secure/lib/libcrypto/man/CMS_decrypt.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_decrypt 3"
-.TH CMS_decrypt 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_decrypt 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_encrypt.3 b/secure/lib/libcrypto/man/CMS_encrypt.3
index 8fd3af8271f8..7e94d64f055e 100644
--- a/secure/lib/libcrypto/man/CMS_encrypt.3
+++ b/secure/lib/libcrypto/man/CMS_encrypt.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_encrypt 3"
-.TH CMS_encrypt 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_encrypt 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_final.3 b/secure/lib/libcrypto/man/CMS_final.3
index 340beadb002e..4493a86b1b9c 100644
--- a/secure/lib/libcrypto/man/CMS_final.3
+++ b/secure/lib/libcrypto/man/CMS_final.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_final 3"
-.TH CMS_final 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_final 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_get0_RecipientInfos.3 b/secure/lib/libcrypto/man/CMS_get0_RecipientInfos.3
index 931a88d202bd..4b4bc4ed1542 100644
--- a/secure/lib/libcrypto/man/CMS_get0_RecipientInfos.3
+++ b/secure/lib/libcrypto/man/CMS_get0_RecipientInfos.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_get0_RecipientInfos 3"
-.TH CMS_get0_RecipientInfos 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_get0_RecipientInfos 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_get0_SignerInfos.3 b/secure/lib/libcrypto/man/CMS_get0_SignerInfos.3
index 160057e33078..d724ae5b9856 100644
--- a/secure/lib/libcrypto/man/CMS_get0_SignerInfos.3
+++ b/secure/lib/libcrypto/man/CMS_get0_SignerInfos.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_get0_SignerInfos 3"
-.TH CMS_get0_SignerInfos 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_get0_SignerInfos 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_get0_type.3 b/secure/lib/libcrypto/man/CMS_get0_type.3
index dc32afc2c293..919d91889e13 100644
--- a/secure/lib/libcrypto/man/CMS_get0_type.3
+++ b/secure/lib/libcrypto/man/CMS_get0_type.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_get0_type 3"
-.TH CMS_get0_type 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_get0_type 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_get1_ReceiptRequest.3 b/secure/lib/libcrypto/man/CMS_get1_ReceiptRequest.3
index e6c778803220..f3dcf2702cb8 100644
--- a/secure/lib/libcrypto/man/CMS_get1_ReceiptRequest.3
+++ b/secure/lib/libcrypto/man/CMS_get1_ReceiptRequest.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_get1_ReceiptRequest 3"
-.TH CMS_get1_ReceiptRequest 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_get1_ReceiptRequest 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_sign.3 b/secure/lib/libcrypto/man/CMS_sign.3
index bb0be5e6c44c..daf147a753ab 100644
--- a/secure/lib/libcrypto/man/CMS_sign.3
+++ b/secure/lib/libcrypto/man/CMS_sign.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_sign 3"
-.TH CMS_sign 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_sign 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_sign_receipt.3 b/secure/lib/libcrypto/man/CMS_sign_receipt.3
index 6311b4a6bccb..25baa891cd31 100644
--- a/secure/lib/libcrypto/man/CMS_sign_receipt.3
+++ b/secure/lib/libcrypto/man/CMS_sign_receipt.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_sign_receipt 3"
-.TH CMS_sign_receipt 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_sign_receipt 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_uncompress.3 b/secure/lib/libcrypto/man/CMS_uncompress.3
index 289e13859958..dea41858c32f 100644
--- a/secure/lib/libcrypto/man/CMS_uncompress.3
+++ b/secure/lib/libcrypto/man/CMS_uncompress.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_uncompress 3"
-.TH CMS_uncompress 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_uncompress 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_verify.3 b/secure/lib/libcrypto/man/CMS_verify.3
index 52a45cdaf092..55803b6c2662 100644
--- a/secure/lib/libcrypto/man/CMS_verify.3
+++ b/secure/lib/libcrypto/man/CMS_verify.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_verify 3"
-.TH CMS_verify 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_verify 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CMS_verify_receipt.3 b/secure/lib/libcrypto/man/CMS_verify_receipt.3
index fd9b9886319c..fbcd2ee5d983 100644
--- a/secure/lib/libcrypto/man/CMS_verify_receipt.3
+++ b/secure/lib/libcrypto/man/CMS_verify_receipt.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS_verify_receipt 3"
-.TH CMS_verify_receipt 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS_verify_receipt 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CONF_modules_free.3 b/secure/lib/libcrypto/man/CONF_modules_free.3
index 7d1415baa5dd..18d3c8f756b7 100644
--- a/secure/lib/libcrypto/man/CONF_modules_free.3
+++ b/secure/lib/libcrypto/man/CONF_modules_free.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CONF_modules_free 3"
-.TH CONF_modules_free 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CONF_modules_free 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CONF_modules_load_file.3 b/secure/lib/libcrypto/man/CONF_modules_load_file.3
index c83ecbe1b2e8..e7af092c7c40 100644
--- a/secure/lib/libcrypto/man/CONF_modules_load_file.3
+++ b/secure/lib/libcrypto/man/CONF_modules_load_file.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CONF_modules_load_file 3"
-.TH CONF_modules_load_file 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CONF_modules_load_file 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/CRYPTO_set_ex_data.3 b/secure/lib/libcrypto/man/CRYPTO_set_ex_data.3
index 38c95e5eecf7..1b14da5ddd8d 100644
--- a/secure/lib/libcrypto/man/CRYPTO_set_ex_data.3
+++ b/secure/lib/libcrypto/man/CRYPTO_set_ex_data.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CRYPTO_set_ex_data 3"
-.TH CRYPTO_set_ex_data 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CRYPTO_set_ex_data 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DH_generate_key.3 b/secure/lib/libcrypto/man/DH_generate_key.3
index cf99604ce045..942533ea05ee 100644
--- a/secure/lib/libcrypto/man/DH_generate_key.3
+++ b/secure/lib/libcrypto/man/DH_generate_key.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DH_generate_key 3"
-.TH DH_generate_key 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DH_generate_key 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DH_generate_parameters.3 b/secure/lib/libcrypto/man/DH_generate_parameters.3
index a6e5964b29b6..ba364af40367 100644
--- a/secure/lib/libcrypto/man/DH_generate_parameters.3
+++ b/secure/lib/libcrypto/man/DH_generate_parameters.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DH_generate_parameters 3"
-.TH DH_generate_parameters 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DH_generate_parameters 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DH_get_ex_new_index.3 b/secure/lib/libcrypto/man/DH_get_ex_new_index.3
index 7f8afb7ec5c9..e01b66e2c14b 100644
--- a/secure/lib/libcrypto/man/DH_get_ex_new_index.3
+++ b/secure/lib/libcrypto/man/DH_get_ex_new_index.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DH_get_ex_new_index 3"
-.TH DH_get_ex_new_index 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DH_get_ex_new_index 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DH_new.3 b/secure/lib/libcrypto/man/DH_new.3
index 13f05d77e35a..e13904e80a1f 100644
--- a/secure/lib/libcrypto/man/DH_new.3
+++ b/secure/lib/libcrypto/man/DH_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DH_new 3"
-.TH DH_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DH_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DH_set_method.3 b/secure/lib/libcrypto/man/DH_set_method.3
index 1f7646a051b4..48525880cb1b 100644
--- a/secure/lib/libcrypto/man/DH_set_method.3
+++ b/secure/lib/libcrypto/man/DH_set_method.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DH_set_method 3"
-.TH DH_set_method 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DH_set_method 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DH_size.3 b/secure/lib/libcrypto/man/DH_size.3
index e47d1f2226df..9a1ef7667a76 100644
--- a/secure/lib/libcrypto/man/DH_size.3
+++ b/secure/lib/libcrypto/man/DH_size.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DH_size 3"
-.TH DH_size 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DH_size 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DSA_SIG_new.3 b/secure/lib/libcrypto/man/DSA_SIG_new.3
index 701cd77aca8d..74abff2a8011 100644
--- a/secure/lib/libcrypto/man/DSA_SIG_new.3
+++ b/secure/lib/libcrypto/man/DSA_SIG_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DSA_SIG_new 3"
-.TH DSA_SIG_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DSA_SIG_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DSA_do_sign.3 b/secure/lib/libcrypto/man/DSA_do_sign.3
index 9fac79790065..6bfeb9510e67 100644
--- a/secure/lib/libcrypto/man/DSA_do_sign.3
+++ b/secure/lib/libcrypto/man/DSA_do_sign.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DSA_do_sign 3"
-.TH DSA_do_sign 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DSA_do_sign 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DSA_dup_DH.3 b/secure/lib/libcrypto/man/DSA_dup_DH.3
index 142aa13f4963..b4b10d11bddf 100644
--- a/secure/lib/libcrypto/man/DSA_dup_DH.3
+++ b/secure/lib/libcrypto/man/DSA_dup_DH.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DSA_dup_DH 3"
-.TH DSA_dup_DH 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DSA_dup_DH 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DSA_generate_key.3 b/secure/lib/libcrypto/man/DSA_generate_key.3
index 6f12de9c2b9a..0b92e49a133b 100644
--- a/secure/lib/libcrypto/man/DSA_generate_key.3
+++ b/secure/lib/libcrypto/man/DSA_generate_key.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DSA_generate_key 3"
-.TH DSA_generate_key 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DSA_generate_key 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DSA_generate_parameters.3 b/secure/lib/libcrypto/man/DSA_generate_parameters.3
index 7ccc54b26564..99196a57f05f 100644
--- a/secure/lib/libcrypto/man/DSA_generate_parameters.3
+++ b/secure/lib/libcrypto/man/DSA_generate_parameters.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DSA_generate_parameters 3"
-.TH DSA_generate_parameters 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DSA_generate_parameters 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DSA_get_ex_new_index.3 b/secure/lib/libcrypto/man/DSA_get_ex_new_index.3
index f473de132eeb..78b4576d5c66 100644
--- a/secure/lib/libcrypto/man/DSA_get_ex_new_index.3
+++ b/secure/lib/libcrypto/man/DSA_get_ex_new_index.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DSA_get_ex_new_index 3"
-.TH DSA_get_ex_new_index 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DSA_get_ex_new_index 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DSA_new.3 b/secure/lib/libcrypto/man/DSA_new.3
index e3fe4086158b..7ab990277933 100644
--- a/secure/lib/libcrypto/man/DSA_new.3
+++ b/secure/lib/libcrypto/man/DSA_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DSA_new 3"
-.TH DSA_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DSA_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DSA_set_method.3 b/secure/lib/libcrypto/man/DSA_set_method.3
index ba984e03cbba..212a12619f3c 100644
--- a/secure/lib/libcrypto/man/DSA_set_method.3
+++ b/secure/lib/libcrypto/man/DSA_set_method.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DSA_set_method 3"
-.TH DSA_set_method 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DSA_set_method 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DSA_sign.3 b/secure/lib/libcrypto/man/DSA_sign.3
index 5a018ac7dafa..4b931edb197f 100644
--- a/secure/lib/libcrypto/man/DSA_sign.3
+++ b/secure/lib/libcrypto/man/DSA_sign.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DSA_sign 3"
-.TH DSA_sign 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DSA_sign 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/DSA_size.3 b/secure/lib/libcrypto/man/DSA_size.3
index bfc328e0c4af..ba562fc3855e 100644
--- a/secure/lib/libcrypto/man/DSA_size.3
+++ b/secure/lib/libcrypto/man/DSA_size.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DSA_size 3"
-.TH DSA_size 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DSA_size 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EC_GFp_simple_method.3 b/secure/lib/libcrypto/man/EC_GFp_simple_method.3
index 89a9b9d44c16..d340e16de0c6 100644
--- a/secure/lib/libcrypto/man/EC_GFp_simple_method.3
+++ b/secure/lib/libcrypto/man/EC_GFp_simple_method.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EC_GFp_simple_method 3"
-.TH EC_GFp_simple_method 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EC_GFp_simple_method 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EC_GROUP_copy.3 b/secure/lib/libcrypto/man/EC_GROUP_copy.3
index 19ce288c76b7..673ac1fcb38c 100644
--- a/secure/lib/libcrypto/man/EC_GROUP_copy.3
+++ b/secure/lib/libcrypto/man/EC_GROUP_copy.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EC_GROUP_copy 3"
-.TH EC_GROUP_copy 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EC_GROUP_copy 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EC_GROUP_new.3 b/secure/lib/libcrypto/man/EC_GROUP_new.3
index b21a561eedba..9b579f4b0b79 100644
--- a/secure/lib/libcrypto/man/EC_GROUP_new.3
+++ b/secure/lib/libcrypto/man/EC_GROUP_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EC_GROUP_new 3"
-.TH EC_GROUP_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EC_GROUP_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EC_KEY_new.3 b/secure/lib/libcrypto/man/EC_KEY_new.3
index 9481b9f671d1..2133fe6be1cc 100644
--- a/secure/lib/libcrypto/man/EC_KEY_new.3
+++ b/secure/lib/libcrypto/man/EC_KEY_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EC_KEY_new 3"
-.TH EC_KEY_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EC_KEY_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EC_POINT_add.3 b/secure/lib/libcrypto/man/EC_POINT_add.3
index 49475758fad4..20d23ced9f9d 100644
--- a/secure/lib/libcrypto/man/EC_POINT_add.3
+++ b/secure/lib/libcrypto/man/EC_POINT_add.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EC_POINT_add 3"
-.TH EC_POINT_add 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EC_POINT_add 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EC_POINT_new.3 b/secure/lib/libcrypto/man/EC_POINT_new.3
index 16a26e571b9c..4c48143143e4 100644
--- a/secure/lib/libcrypto/man/EC_POINT_new.3
+++ b/secure/lib/libcrypto/man/EC_POINT_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EC_POINT_new 3"
-.TH EC_POINT_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EC_POINT_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ERR_GET_LIB.3 b/secure/lib/libcrypto/man/ERR_GET_LIB.3
index e44b533411d3..324acd356f43 100644
--- a/secure/lib/libcrypto/man/ERR_GET_LIB.3
+++ b/secure/lib/libcrypto/man/ERR_GET_LIB.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ERR_GET_LIB 3"
-.TH ERR_GET_LIB 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ERR_GET_LIB 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ERR_clear_error.3 b/secure/lib/libcrypto/man/ERR_clear_error.3
index e2e9b3c02cf1..d438690737b4 100644
--- a/secure/lib/libcrypto/man/ERR_clear_error.3
+++ b/secure/lib/libcrypto/man/ERR_clear_error.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ERR_clear_error 3"
-.TH ERR_clear_error 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ERR_clear_error 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ERR_error_string.3 b/secure/lib/libcrypto/man/ERR_error_string.3
index faa1815835e3..ceae6e9c5094 100644
--- a/secure/lib/libcrypto/man/ERR_error_string.3
+++ b/secure/lib/libcrypto/man/ERR_error_string.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ERR_error_string 3"
-.TH ERR_error_string 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ERR_error_string 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ERR_get_error.3 b/secure/lib/libcrypto/man/ERR_get_error.3
index 5f50af215535..e5e89d2670ef 100644
--- a/secure/lib/libcrypto/man/ERR_get_error.3
+++ b/secure/lib/libcrypto/man/ERR_get_error.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ERR_get_error 3"
-.TH ERR_get_error 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ERR_get_error 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ERR_load_crypto_strings.3 b/secure/lib/libcrypto/man/ERR_load_crypto_strings.3
index 542782fc674e..ab55cbe5400e 100644
--- a/secure/lib/libcrypto/man/ERR_load_crypto_strings.3
+++ b/secure/lib/libcrypto/man/ERR_load_crypto_strings.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ERR_load_crypto_strings 3"
-.TH ERR_load_crypto_strings 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ERR_load_crypto_strings 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ERR_load_strings.3 b/secure/lib/libcrypto/man/ERR_load_strings.3
index 2c2268774ddf..4fb6d8680ce0 100644
--- a/secure/lib/libcrypto/man/ERR_load_strings.3
+++ b/secure/lib/libcrypto/man/ERR_load_strings.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ERR_load_strings 3"
-.TH ERR_load_strings 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ERR_load_strings 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ERR_print_errors.3 b/secure/lib/libcrypto/man/ERR_print_errors.3
index 7048d50f1081..ce7846e88e3e 100644
--- a/secure/lib/libcrypto/man/ERR_print_errors.3
+++ b/secure/lib/libcrypto/man/ERR_print_errors.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ERR_print_errors 3"
-.TH ERR_print_errors 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ERR_print_errors 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ERR_put_error.3 b/secure/lib/libcrypto/man/ERR_put_error.3
index 4020eecdc643..f767258f4368 100644
--- a/secure/lib/libcrypto/man/ERR_put_error.3
+++ b/secure/lib/libcrypto/man/ERR_put_error.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ERR_put_error 3"
-.TH ERR_put_error 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ERR_put_error 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ERR_remove_state.3 b/secure/lib/libcrypto/man/ERR_remove_state.3
index 554ebc49f451..b276bc70ff91 100644
--- a/secure/lib/libcrypto/man/ERR_remove_state.3
+++ b/secure/lib/libcrypto/man/ERR_remove_state.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ERR_remove_state 3"
-.TH ERR_remove_state 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ERR_remove_state 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ERR_set_mark.3 b/secure/lib/libcrypto/man/ERR_set_mark.3
index 1be092262d8d..7b33df8f606a 100644
--- a/secure/lib/libcrypto/man/ERR_set_mark.3
+++ b/secure/lib/libcrypto/man/ERR_set_mark.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ERR_set_mark 3"
-.TH ERR_set_mark 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ERR_set_mark 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_BytesToKey.3 b/secure/lib/libcrypto/man/EVP_BytesToKey.3
index e092a1880b5c..24abfd790e75 100644
--- a/secure/lib/libcrypto/man/EVP_BytesToKey.3
+++ b/secure/lib/libcrypto/man/EVP_BytesToKey.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_BytesToKey 3"
-.TH EVP_BytesToKey 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_BytesToKey 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_DigestInit.3 b/secure/lib/libcrypto/man/EVP_DigestInit.3
index 4096ca280634..964febe36d6c 100644
--- a/secure/lib/libcrypto/man/EVP_DigestInit.3
+++ b/secure/lib/libcrypto/man/EVP_DigestInit.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_DigestInit 3"
-.TH EVP_DigestInit 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_DigestInit 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_DigestSignInit.3 b/secure/lib/libcrypto/man/EVP_DigestSignInit.3
index c3b4c3ba9b2e..526ec8092117 100644
--- a/secure/lib/libcrypto/man/EVP_DigestSignInit.3
+++ b/secure/lib/libcrypto/man/EVP_DigestSignInit.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_DigestSignInit 3"
-.TH EVP_DigestSignInit 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_DigestSignInit 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_DigestVerifyInit.3 b/secure/lib/libcrypto/man/EVP_DigestVerifyInit.3
index dc14e4f75126..e5057c29875c 100644
--- a/secure/lib/libcrypto/man/EVP_DigestVerifyInit.3
+++ b/secure/lib/libcrypto/man/EVP_DigestVerifyInit.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_DigestVerifyInit 3"
-.TH EVP_DigestVerifyInit 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_DigestVerifyInit 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_EncryptInit.3 b/secure/lib/libcrypto/man/EVP_EncryptInit.3
index 5b6e418213f4..72750a8543f1 100644
--- a/secure/lib/libcrypto/man/EVP_EncryptInit.3
+++ b/secure/lib/libcrypto/man/EVP_EncryptInit.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_EncryptInit 3"
-.TH EVP_EncryptInit 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_EncryptInit 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_OpenInit.3 b/secure/lib/libcrypto/man/EVP_OpenInit.3
index a9efbc2105d0..901bc2381f84 100644
--- a/secure/lib/libcrypto/man/EVP_OpenInit.3
+++ b/secure/lib/libcrypto/man/EVP_OpenInit.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_OpenInit 3"
-.TH EVP_OpenInit 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_OpenInit 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_CTX_ctrl.3 b/secure/lib/libcrypto/man/EVP_PKEY_CTX_ctrl.3
index 91e0a111bd07..c62d4e9c7138 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_CTX_ctrl.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_CTX_ctrl.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_PKEY_CTX_ctrl 3"
-.TH EVP_PKEY_CTX_ctrl 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_PKEY_CTX_ctrl 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_CTX_new.3 b/secure/lib/libcrypto/man/EVP_PKEY_CTX_new.3
index 6a6bedcf4ea2..ede32e48dcd9 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_CTX_new.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_CTX_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_PKEY_CTX_new 3"
-.TH EVP_PKEY_CTX_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_PKEY_CTX_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_cmp.3 b/secure/lib/libcrypto/man/EVP_PKEY_cmp.3
index e27f023b77d6..83284c625be8 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_cmp.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_cmp.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_PKEY_cmp 3"
-.TH EVP_PKEY_cmp 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_PKEY_cmp 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_decrypt.3 b/secure/lib/libcrypto/man/EVP_PKEY_decrypt.3
index 7638dd3f29c0..317cbd39bd68 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_decrypt.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_decrypt.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_PKEY_decrypt 3"
-.TH EVP_PKEY_decrypt 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_PKEY_decrypt 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_derive.3 b/secure/lib/libcrypto/man/EVP_PKEY_derive.3
index 73819794f202..cf6a3d2233dc 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_derive.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_derive.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_PKEY_derive 3"
-.TH EVP_PKEY_derive 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_PKEY_derive 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_encrypt.3 b/secure/lib/libcrypto/man/EVP_PKEY_encrypt.3
index 425b73fc3d7c..968c657a4a90 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_encrypt.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_encrypt.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_PKEY_encrypt 3"
-.TH EVP_PKEY_encrypt 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_PKEY_encrypt 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_get_default_digest.3 b/secure/lib/libcrypto/man/EVP_PKEY_get_default_digest.3
index 8e33b95ba454..baadde23b017 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_get_default_digest.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_get_default_digest.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_PKEY_get_default_digest 3"
-.TH EVP_PKEY_get_default_digest 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_PKEY_get_default_digest 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_keygen.3 b/secure/lib/libcrypto/man/EVP_PKEY_keygen.3
index 30648cd127e2..40cadb1da222 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_keygen.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_keygen.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_PKEY_keygen 3"
-.TH EVP_PKEY_keygen 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_PKEY_keygen 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_new.3 b/secure/lib/libcrypto/man/EVP_PKEY_new.3
index 60d80d33b77b..a215ffbe3dc2 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_new.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_PKEY_new 3"
-.TH EVP_PKEY_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_PKEY_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_print_private.3 b/secure/lib/libcrypto/man/EVP_PKEY_print_private.3
index 3410aad09f03..45d7a8f12187 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_print_private.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_print_private.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_PKEY_print_private 3"
-.TH EVP_PKEY_print_private 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_PKEY_print_private 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_set1_RSA.3 b/secure/lib/libcrypto/man/EVP_PKEY_set1_RSA.3
index 8d65be999a2e..66749bd569aa 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_set1_RSA.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_set1_RSA.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_PKEY_set1_RSA 3"
-.TH EVP_PKEY_set1_RSA 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_PKEY_set1_RSA 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_sign.3 b/secure/lib/libcrypto/man/EVP_PKEY_sign.3
index d165f826b34d..ecc7326a6f21 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_sign.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_sign.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_PKEY_sign 3"
-.TH EVP_PKEY_sign 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_PKEY_sign 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_verify.3 b/secure/lib/libcrypto/man/EVP_PKEY_verify.3
index 0218f2ba2723..9cef011226b7 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_verify.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_verify.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_PKEY_verify 3"
-.TH EVP_PKEY_verify 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_PKEY_verify 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_verify_recover.3 b/secure/lib/libcrypto/man/EVP_PKEY_verify_recover.3
index 982c4a84b736..f28916f3dbdb 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_verify_recover.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_verify_recover.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_PKEY_verify_recover 3"
-.TH EVP_PKEY_verify_recover 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_PKEY_verify_recover 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_SealInit.3 b/secure/lib/libcrypto/man/EVP_SealInit.3
index b6d3b0410623..0b195a4c25b6 100644
--- a/secure/lib/libcrypto/man/EVP_SealInit.3
+++ b/secure/lib/libcrypto/man/EVP_SealInit.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_SealInit 3"
-.TH EVP_SealInit 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_SealInit 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_SignInit.3 b/secure/lib/libcrypto/man/EVP_SignInit.3
index 5199db549840..8d0c569d74fd 100644
--- a/secure/lib/libcrypto/man/EVP_SignInit.3
+++ b/secure/lib/libcrypto/man/EVP_SignInit.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_SignInit 3"
-.TH EVP_SignInit 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_SignInit 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/EVP_VerifyInit.3 b/secure/lib/libcrypto/man/EVP_VerifyInit.3
index 06f8bf08257c..2076e1114fdb 100644
--- a/secure/lib/libcrypto/man/EVP_VerifyInit.3
+++ b/secure/lib/libcrypto/man/EVP_VerifyInit.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EVP_VerifyInit 3"
-.TH EVP_VerifyInit 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EVP_VerifyInit 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/OBJ_nid2obj.3 b/secure/lib/libcrypto/man/OBJ_nid2obj.3
index 878b6059a384..b8803cf06a43 100644
--- a/secure/lib/libcrypto/man/OBJ_nid2obj.3
+++ b/secure/lib/libcrypto/man/OBJ_nid2obj.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "OBJ_nid2obj 3"
-.TH OBJ_nid2obj 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH OBJ_nid2obj 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/OPENSSL_Applink.3 b/secure/lib/libcrypto/man/OPENSSL_Applink.3
index 4e219364a76e..156c01a990d3 100644
--- a/secure/lib/libcrypto/man/OPENSSL_Applink.3
+++ b/secure/lib/libcrypto/man/OPENSSL_Applink.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "OPENSSL_Applink 3"
-.TH OPENSSL_Applink 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH OPENSSL_Applink 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/OPENSSL_VERSION_NUMBER.3 b/secure/lib/libcrypto/man/OPENSSL_VERSION_NUMBER.3
index b6210d3e4c35..15d8559ae3de 100644
--- a/secure/lib/libcrypto/man/OPENSSL_VERSION_NUMBER.3
+++ b/secure/lib/libcrypto/man/OPENSSL_VERSION_NUMBER.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "OPENSSL_VERSION_NUMBER 3"
-.TH OPENSSL_VERSION_NUMBER 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH OPENSSL_VERSION_NUMBER 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/OPENSSL_config.3 b/secure/lib/libcrypto/man/OPENSSL_config.3
index dcc2ad28c467..3dda3057ef6e 100644
--- a/secure/lib/libcrypto/man/OPENSSL_config.3
+++ b/secure/lib/libcrypto/man/OPENSSL_config.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "OPENSSL_config 3"
-.TH OPENSSL_config 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH OPENSSL_config 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/OPENSSL_ia32cap.3 b/secure/lib/libcrypto/man/OPENSSL_ia32cap.3
index 3ac977a19ec7..d2ef459d7ca8 100644
--- a/secure/lib/libcrypto/man/OPENSSL_ia32cap.3
+++ b/secure/lib/libcrypto/man/OPENSSL_ia32cap.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "OPENSSL_ia32cap 3"
-.TH OPENSSL_ia32cap 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH OPENSSL_ia32cap 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/OPENSSL_instrument_bus.3 b/secure/lib/libcrypto/man/OPENSSL_instrument_bus.3
index af916bea49a6..9bf6627e64ba 100644
--- a/secure/lib/libcrypto/man/OPENSSL_instrument_bus.3
+++ b/secure/lib/libcrypto/man/OPENSSL_instrument_bus.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "OPENSSL_instrument_bus 3"
-.TH OPENSSL_instrument_bus 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH OPENSSL_instrument_bus 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/OPENSSL_load_builtin_modules.3 b/secure/lib/libcrypto/man/OPENSSL_load_builtin_modules.3
index 812480db256e..9f288d856f17 100644
--- a/secure/lib/libcrypto/man/OPENSSL_load_builtin_modules.3
+++ b/secure/lib/libcrypto/man/OPENSSL_load_builtin_modules.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "OPENSSL_load_builtin_modules 3"
-.TH OPENSSL_load_builtin_modules 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH OPENSSL_load_builtin_modules 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/OpenSSL_add_all_algorithms.3 b/secure/lib/libcrypto/man/OpenSSL_add_all_algorithms.3
index 7b1b802943df..b31b05325a5c 100644
--- a/secure/lib/libcrypto/man/OpenSSL_add_all_algorithms.3
+++ b/secure/lib/libcrypto/man/OpenSSL_add_all_algorithms.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "OpenSSL_add_all_algorithms 3"
-.TH OpenSSL_add_all_algorithms 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH OpenSSL_add_all_algorithms 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/PEM_write_bio_CMS_stream.3 b/secure/lib/libcrypto/man/PEM_write_bio_CMS_stream.3
index 7d2079998d3b..8b963364e0ef 100644
--- a/secure/lib/libcrypto/man/PEM_write_bio_CMS_stream.3
+++ b/secure/lib/libcrypto/man/PEM_write_bio_CMS_stream.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PEM_write_bio_CMS_stream 3"
-.TH PEM_write_bio_CMS_stream 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PEM_write_bio_CMS_stream 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/PEM_write_bio_PKCS7_stream.3 b/secure/lib/libcrypto/man/PEM_write_bio_PKCS7_stream.3
index 14d9d1bdce3b..cf498f4dbd5d 100644
--- a/secure/lib/libcrypto/man/PEM_write_bio_PKCS7_stream.3
+++ b/secure/lib/libcrypto/man/PEM_write_bio_PKCS7_stream.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PEM_write_bio_PKCS7_stream 3"
-.TH PEM_write_bio_PKCS7_stream 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PEM_write_bio_PKCS7_stream 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/PKCS12_create.3 b/secure/lib/libcrypto/man/PKCS12_create.3
index 46a12b8ec5b5..b51d555adcab 100644
--- a/secure/lib/libcrypto/man/PKCS12_create.3
+++ b/secure/lib/libcrypto/man/PKCS12_create.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PKCS12_create 3"
-.TH PKCS12_create 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PKCS12_create 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/PKCS12_parse.3 b/secure/lib/libcrypto/man/PKCS12_parse.3
index 3be106cebb1e..e6e31eb56487 100644
--- a/secure/lib/libcrypto/man/PKCS12_parse.3
+++ b/secure/lib/libcrypto/man/PKCS12_parse.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PKCS12_parse 3"
-.TH PKCS12_parse 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PKCS12_parse 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/PKCS7_decrypt.3 b/secure/lib/libcrypto/man/PKCS7_decrypt.3
index 5321f9f9e467..9a177b32e2bd 100644
--- a/secure/lib/libcrypto/man/PKCS7_decrypt.3
+++ b/secure/lib/libcrypto/man/PKCS7_decrypt.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PKCS7_decrypt 3"
-.TH PKCS7_decrypt 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PKCS7_decrypt 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/PKCS7_encrypt.3 b/secure/lib/libcrypto/man/PKCS7_encrypt.3
index e6c8552bb8b8..2a74fc73d454 100644
--- a/secure/lib/libcrypto/man/PKCS7_encrypt.3
+++ b/secure/lib/libcrypto/man/PKCS7_encrypt.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PKCS7_encrypt 3"
-.TH PKCS7_encrypt 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PKCS7_encrypt 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/PKCS7_sign.3 b/secure/lib/libcrypto/man/PKCS7_sign.3
index 01de0aae96de..5939da522e20 100644
--- a/secure/lib/libcrypto/man/PKCS7_sign.3
+++ b/secure/lib/libcrypto/man/PKCS7_sign.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PKCS7_sign 3"
-.TH PKCS7_sign 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PKCS7_sign 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/PKCS7_sign_add_signer.3 b/secure/lib/libcrypto/man/PKCS7_sign_add_signer.3
index 0149972fe1fd..aaa8e46cd659 100644
--- a/secure/lib/libcrypto/man/PKCS7_sign_add_signer.3
+++ b/secure/lib/libcrypto/man/PKCS7_sign_add_signer.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PKCS7_sign_add_signer 3"
-.TH PKCS7_sign_add_signer 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PKCS7_sign_add_signer 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/PKCS7_verify.3 b/secure/lib/libcrypto/man/PKCS7_verify.3
index 359e5a767206..f90834ee6fb0 100644
--- a/secure/lib/libcrypto/man/PKCS7_verify.3
+++ b/secure/lib/libcrypto/man/PKCS7_verify.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PKCS7_verify 3"
-.TH PKCS7_verify 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PKCS7_verify 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RAND_add.3 b/secure/lib/libcrypto/man/RAND_add.3
index 4dbb95e90cce..ecd87cf38c45 100644
--- a/secure/lib/libcrypto/man/RAND_add.3
+++ b/secure/lib/libcrypto/man/RAND_add.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RAND_add 3"
-.TH RAND_add 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RAND_add 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RAND_bytes.3 b/secure/lib/libcrypto/man/RAND_bytes.3
index 77b0179b9d2f..7d60d8749e0f 100644
--- a/secure/lib/libcrypto/man/RAND_bytes.3
+++ b/secure/lib/libcrypto/man/RAND_bytes.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RAND_bytes 3"
-.TH RAND_bytes 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RAND_bytes 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RAND_cleanup.3 b/secure/lib/libcrypto/man/RAND_cleanup.3
index 75444c09141a..fa98f1db4196 100644
--- a/secure/lib/libcrypto/man/RAND_cleanup.3
+++ b/secure/lib/libcrypto/man/RAND_cleanup.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RAND_cleanup 3"
-.TH RAND_cleanup 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RAND_cleanup 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RAND_egd.3 b/secure/lib/libcrypto/man/RAND_egd.3
index 482ff2cbf419..2d354cdf76cf 100644
--- a/secure/lib/libcrypto/man/RAND_egd.3
+++ b/secure/lib/libcrypto/man/RAND_egd.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RAND_egd 3"
-.TH RAND_egd 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RAND_egd 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RAND_load_file.3 b/secure/lib/libcrypto/man/RAND_load_file.3
index 0d7851bf62c7..ddf8f741fd96 100644
--- a/secure/lib/libcrypto/man/RAND_load_file.3
+++ b/secure/lib/libcrypto/man/RAND_load_file.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RAND_load_file 3"
-.TH RAND_load_file 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RAND_load_file 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RAND_set_rand_method.3 b/secure/lib/libcrypto/man/RAND_set_rand_method.3
index ba5c14953693..3cac460c525c 100644
--- a/secure/lib/libcrypto/man/RAND_set_rand_method.3
+++ b/secure/lib/libcrypto/man/RAND_set_rand_method.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RAND_set_rand_method 3"
-.TH RAND_set_rand_method 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RAND_set_rand_method 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RSA_blinding_on.3 b/secure/lib/libcrypto/man/RSA_blinding_on.3
index 68b0be5bedf9..9215584caee4 100644
--- a/secure/lib/libcrypto/man/RSA_blinding_on.3
+++ b/secure/lib/libcrypto/man/RSA_blinding_on.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSA_blinding_on 3"
-.TH RSA_blinding_on 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSA_blinding_on 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RSA_check_key.3 b/secure/lib/libcrypto/man/RSA_check_key.3
index 27df720af877..1b7d1c5bbe0c 100644
--- a/secure/lib/libcrypto/man/RSA_check_key.3
+++ b/secure/lib/libcrypto/man/RSA_check_key.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSA_check_key 3"
-.TH RSA_check_key 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSA_check_key 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RSA_generate_key.3 b/secure/lib/libcrypto/man/RSA_generate_key.3
index 5ee29d8d57dc..0c00558b513d 100644
--- a/secure/lib/libcrypto/man/RSA_generate_key.3
+++ b/secure/lib/libcrypto/man/RSA_generate_key.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSA_generate_key 3"
-.TH RSA_generate_key 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSA_generate_key 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RSA_get_ex_new_index.3 b/secure/lib/libcrypto/man/RSA_get_ex_new_index.3
index a73e50acff22..d6e364cffb16 100644
--- a/secure/lib/libcrypto/man/RSA_get_ex_new_index.3
+++ b/secure/lib/libcrypto/man/RSA_get_ex_new_index.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSA_get_ex_new_index 3"
-.TH RSA_get_ex_new_index 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSA_get_ex_new_index 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RSA_new.3 b/secure/lib/libcrypto/man/RSA_new.3
index 39af29ec90c0..d280491792a0 100644
--- a/secure/lib/libcrypto/man/RSA_new.3
+++ b/secure/lib/libcrypto/man/RSA_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSA_new 3"
-.TH RSA_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSA_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RSA_padding_add_PKCS1_type_1.3 b/secure/lib/libcrypto/man/RSA_padding_add_PKCS1_type_1.3
index 60ded7ed2c69..5eee16f9cad5 100644
--- a/secure/lib/libcrypto/man/RSA_padding_add_PKCS1_type_1.3
+++ b/secure/lib/libcrypto/man/RSA_padding_add_PKCS1_type_1.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSA_padding_add_PKCS1_type_1 3"
-.TH RSA_padding_add_PKCS1_type_1 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSA_padding_add_PKCS1_type_1 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RSA_print.3 b/secure/lib/libcrypto/man/RSA_print.3
index a48c6d6b28c0..0bb31e5812af 100644
--- a/secure/lib/libcrypto/man/RSA_print.3
+++ b/secure/lib/libcrypto/man/RSA_print.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSA_print 3"
-.TH RSA_print 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSA_print 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RSA_private_encrypt.3 b/secure/lib/libcrypto/man/RSA_private_encrypt.3
index cc98abde58ad..64502ad24a81 100644
--- a/secure/lib/libcrypto/man/RSA_private_encrypt.3
+++ b/secure/lib/libcrypto/man/RSA_private_encrypt.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSA_private_encrypt 3"
-.TH RSA_private_encrypt 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSA_private_encrypt 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RSA_public_encrypt.3 b/secure/lib/libcrypto/man/RSA_public_encrypt.3
index 54b997db9ca4..f1e2e8f682e0 100644
--- a/secure/lib/libcrypto/man/RSA_public_encrypt.3
+++ b/secure/lib/libcrypto/man/RSA_public_encrypt.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSA_public_encrypt 3"
-.TH RSA_public_encrypt 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSA_public_encrypt 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RSA_set_method.3 b/secure/lib/libcrypto/man/RSA_set_method.3
index a6aa98f01a51..7a3a26ab82ec 100644
--- a/secure/lib/libcrypto/man/RSA_set_method.3
+++ b/secure/lib/libcrypto/man/RSA_set_method.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSA_set_method 3"
-.TH RSA_set_method 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSA_set_method 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RSA_sign.3 b/secure/lib/libcrypto/man/RSA_sign.3
index 2f57c5a94898..a5d4e1fa719c 100644
--- a/secure/lib/libcrypto/man/RSA_sign.3
+++ b/secure/lib/libcrypto/man/RSA_sign.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSA_sign 3"
-.TH RSA_sign 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSA_sign 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RSA_sign_ASN1_OCTET_STRING.3 b/secure/lib/libcrypto/man/RSA_sign_ASN1_OCTET_STRING.3
index 32d579c44466..8d3909e8f4eb 100644
--- a/secure/lib/libcrypto/man/RSA_sign_ASN1_OCTET_STRING.3
+++ b/secure/lib/libcrypto/man/RSA_sign_ASN1_OCTET_STRING.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSA_sign_ASN1_OCTET_STRING 3"
-.TH RSA_sign_ASN1_OCTET_STRING 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSA_sign_ASN1_OCTET_STRING 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/RSA_size.3 b/secure/lib/libcrypto/man/RSA_size.3
index 6fb4b1c76be0..7bd820a48bb4 100644
--- a/secure/lib/libcrypto/man/RSA_size.3
+++ b/secure/lib/libcrypto/man/RSA_size.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSA_size 3"
-.TH RSA_size 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSA_size 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/SMIME_read_CMS.3 b/secure/lib/libcrypto/man/SMIME_read_CMS.3
index 0f2e94e61cfb..8e61ff0cc1d2 100644
--- a/secure/lib/libcrypto/man/SMIME_read_CMS.3
+++ b/secure/lib/libcrypto/man/SMIME_read_CMS.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SMIME_read_CMS 3"
-.TH SMIME_read_CMS 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SMIME_read_CMS 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/SMIME_read_PKCS7.3 b/secure/lib/libcrypto/man/SMIME_read_PKCS7.3
index 341a77c5f540..df097458df54 100644
--- a/secure/lib/libcrypto/man/SMIME_read_PKCS7.3
+++ b/secure/lib/libcrypto/man/SMIME_read_PKCS7.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SMIME_read_PKCS7 3"
-.TH SMIME_read_PKCS7 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SMIME_read_PKCS7 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/SMIME_write_CMS.3 b/secure/lib/libcrypto/man/SMIME_write_CMS.3
index d1288aff6c72..ecd5d0aed945 100644
--- a/secure/lib/libcrypto/man/SMIME_write_CMS.3
+++ b/secure/lib/libcrypto/man/SMIME_write_CMS.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SMIME_write_CMS 3"
-.TH SMIME_write_CMS 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SMIME_write_CMS 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/SMIME_write_PKCS7.3 b/secure/lib/libcrypto/man/SMIME_write_PKCS7.3
index 35ce5ceb04ee..65be1eebc9b5 100644
--- a/secure/lib/libcrypto/man/SMIME_write_PKCS7.3
+++ b/secure/lib/libcrypto/man/SMIME_write_PKCS7.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SMIME_write_PKCS7 3"
-.TH SMIME_write_PKCS7 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SMIME_write_PKCS7 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/X509_NAME_ENTRY_get_object.3 b/secure/lib/libcrypto/man/X509_NAME_ENTRY_get_object.3
index 1145471bea1b..bc0c93aa7ae8 100644
--- a/secure/lib/libcrypto/man/X509_NAME_ENTRY_get_object.3
+++ b/secure/lib/libcrypto/man/X509_NAME_ENTRY_get_object.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509_NAME_ENTRY_get_object 3"
-.TH X509_NAME_ENTRY_get_object 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509_NAME_ENTRY_get_object 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/X509_NAME_add_entry_by_txt.3 b/secure/lib/libcrypto/man/X509_NAME_add_entry_by_txt.3
index 6faa83d7185b..4d0fd70af1fa 100644
--- a/secure/lib/libcrypto/man/X509_NAME_add_entry_by_txt.3
+++ b/secure/lib/libcrypto/man/X509_NAME_add_entry_by_txt.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509_NAME_add_entry_by_txt 3"
-.TH X509_NAME_add_entry_by_txt 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509_NAME_add_entry_by_txt 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/X509_NAME_get_index_by_NID.3 b/secure/lib/libcrypto/man/X509_NAME_get_index_by_NID.3
index 8899c51d6f47..1bd371d5664a 100644
--- a/secure/lib/libcrypto/man/X509_NAME_get_index_by_NID.3
+++ b/secure/lib/libcrypto/man/X509_NAME_get_index_by_NID.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509_NAME_get_index_by_NID 3"
-.TH X509_NAME_get_index_by_NID 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509_NAME_get_index_by_NID 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/X509_NAME_print_ex.3 b/secure/lib/libcrypto/man/X509_NAME_print_ex.3
index 12a6a9ad2ce4..ab24f724f610 100644
--- a/secure/lib/libcrypto/man/X509_NAME_print_ex.3
+++ b/secure/lib/libcrypto/man/X509_NAME_print_ex.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509_NAME_print_ex 3"
-.TH X509_NAME_print_ex 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509_NAME_print_ex 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/X509_STORE_CTX_get_error.3 b/secure/lib/libcrypto/man/X509_STORE_CTX_get_error.3
index 5f550bcd9b7d..680446f8b34a 100644
--- a/secure/lib/libcrypto/man/X509_STORE_CTX_get_error.3
+++ b/secure/lib/libcrypto/man/X509_STORE_CTX_get_error.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509_STORE_CTX_get_error 3"
-.TH X509_STORE_CTX_get_error 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509_STORE_CTX_get_error 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/X509_STORE_CTX_get_ex_new_index.3 b/secure/lib/libcrypto/man/X509_STORE_CTX_get_ex_new_index.3
index 2d2b3477c7e8..e65edff0af1a 100644
--- a/secure/lib/libcrypto/man/X509_STORE_CTX_get_ex_new_index.3
+++ b/secure/lib/libcrypto/man/X509_STORE_CTX_get_ex_new_index.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509_STORE_CTX_get_ex_new_index 3"
-.TH X509_STORE_CTX_get_ex_new_index 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509_STORE_CTX_get_ex_new_index 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/X509_STORE_CTX_new.3 b/secure/lib/libcrypto/man/X509_STORE_CTX_new.3
index 47e97c3b574b..b9e9433b5738 100644
--- a/secure/lib/libcrypto/man/X509_STORE_CTX_new.3
+++ b/secure/lib/libcrypto/man/X509_STORE_CTX_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509_STORE_CTX_new 3"
-.TH X509_STORE_CTX_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509_STORE_CTX_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/X509_STORE_CTX_set_verify_cb.3 b/secure/lib/libcrypto/man/X509_STORE_CTX_set_verify_cb.3
index 63e88462ca90..143b5da1278c 100644
--- a/secure/lib/libcrypto/man/X509_STORE_CTX_set_verify_cb.3
+++ b/secure/lib/libcrypto/man/X509_STORE_CTX_set_verify_cb.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509_STORE_CTX_set_verify_cb 3"
-.TH X509_STORE_CTX_set_verify_cb 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509_STORE_CTX_set_verify_cb 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/X509_STORE_set_verify_cb_func.3 b/secure/lib/libcrypto/man/X509_STORE_set_verify_cb_func.3
index 5ac5a469f124..265432cb748d 100644
--- a/secure/lib/libcrypto/man/X509_STORE_set_verify_cb_func.3
+++ b/secure/lib/libcrypto/man/X509_STORE_set_verify_cb_func.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509_STORE_set_verify_cb_func 3"
-.TH X509_STORE_set_verify_cb_func 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509_STORE_set_verify_cb_func 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/X509_VERIFY_PARAM_set_flags.3 b/secure/lib/libcrypto/man/X509_VERIFY_PARAM_set_flags.3
index 323e662d9d12..67a3adb2b632 100644
--- a/secure/lib/libcrypto/man/X509_VERIFY_PARAM_set_flags.3
+++ b/secure/lib/libcrypto/man/X509_VERIFY_PARAM_set_flags.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509_VERIFY_PARAM_set_flags 3"
-.TH X509_VERIFY_PARAM_set_flags 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509_VERIFY_PARAM_set_flags 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/X509_check_host.3 b/secure/lib/libcrypto/man/X509_check_host.3
index 87680786fb64..6214c0a94418 100644
--- a/secure/lib/libcrypto/man/X509_check_host.3
+++ b/secure/lib/libcrypto/man/X509_check_host.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509_check_host 3"
-.TH X509_check_host 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509_check_host 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/X509_new.3 b/secure/lib/libcrypto/man/X509_new.3
index 631398d50e6a..98b0a3d16a6b 100644
--- a/secure/lib/libcrypto/man/X509_new.3
+++ b/secure/lib/libcrypto/man/X509_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509_new 3"
-.TH X509_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/X509_verify_cert.3 b/secure/lib/libcrypto/man/X509_verify_cert.3
index f74bf50c21df..cf57e76b03ff 100644
--- a/secure/lib/libcrypto/man/X509_verify_cert.3
+++ b/secure/lib/libcrypto/man/X509_verify_cert.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509_verify_cert 3"
-.TH X509_verify_cert 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509_verify_cert 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/bio.3 b/secure/lib/libcrypto/man/bio.3
index 86d132ca9fd6..9c78a7cc1614 100644
--- a/secure/lib/libcrypto/man/bio.3
+++ b/secure/lib/libcrypto/man/bio.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "bio 3"
-.TH bio 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH bio 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/blowfish.3 b/secure/lib/libcrypto/man/blowfish.3
index 588c21fe7160..27ad78e32fc4 100644
--- a/secure/lib/libcrypto/man/blowfish.3
+++ b/secure/lib/libcrypto/man/blowfish.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "blowfish 3"
-.TH blowfish 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH blowfish 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/bn.3 b/secure/lib/libcrypto/man/bn.3
index 23948eab1011..14b6923e83eb 100644
--- a/secure/lib/libcrypto/man/bn.3
+++ b/secure/lib/libcrypto/man/bn.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "bn 3"
-.TH bn 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH bn 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/bn_internal.3 b/secure/lib/libcrypto/man/bn_internal.3
index 4b7108a046ac..49f2ac1376d6 100644
--- a/secure/lib/libcrypto/man/bn_internal.3
+++ b/secure/lib/libcrypto/man/bn_internal.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "bn_internal 3"
-.TH bn_internal 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH bn_internal 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/buffer.3 b/secure/lib/libcrypto/man/buffer.3
index b47075a75737..806ed8b625cd 100644
--- a/secure/lib/libcrypto/man/buffer.3
+++ b/secure/lib/libcrypto/man/buffer.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "buffer 3"
-.TH buffer 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH buffer 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/crypto.3 b/secure/lib/libcrypto/man/crypto.3
index 7c529546108b..4854cadd346c 100644
--- a/secure/lib/libcrypto/man/crypto.3
+++ b/secure/lib/libcrypto/man/crypto.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "crypto 3"
-.TH crypto 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH crypto 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/d2i_ASN1_OBJECT.3 b/secure/lib/libcrypto/man/d2i_ASN1_OBJECT.3
index dc415b6f9281..9ec56417b1ec 100644
--- a/secure/lib/libcrypto/man/d2i_ASN1_OBJECT.3
+++ b/secure/lib/libcrypto/man/d2i_ASN1_OBJECT.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_ASN1_OBJECT 3"
-.TH d2i_ASN1_OBJECT 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_ASN1_OBJECT 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/d2i_CMS_ContentInfo.3 b/secure/lib/libcrypto/man/d2i_CMS_ContentInfo.3
index c89e582727ab..64bf083cf57e 100644
--- a/secure/lib/libcrypto/man/d2i_CMS_ContentInfo.3
+++ b/secure/lib/libcrypto/man/d2i_CMS_ContentInfo.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_CMS_ContentInfo 3"
-.TH d2i_CMS_ContentInfo 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_CMS_ContentInfo 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/d2i_DHparams.3 b/secure/lib/libcrypto/man/d2i_DHparams.3
index 93ac08e3f031..e76374189b39 100644
--- a/secure/lib/libcrypto/man/d2i_DHparams.3
+++ b/secure/lib/libcrypto/man/d2i_DHparams.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_DHparams 3"
-.TH d2i_DHparams 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_DHparams 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/d2i_DSAPublicKey.3 b/secure/lib/libcrypto/man/d2i_DSAPublicKey.3
index 86c2f354295f..e121977727fa 100644
--- a/secure/lib/libcrypto/man/d2i_DSAPublicKey.3
+++ b/secure/lib/libcrypto/man/d2i_DSAPublicKey.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_DSAPublicKey 3"
-.TH d2i_DSAPublicKey 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_DSAPublicKey 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/d2i_ECPKParameters.3 b/secure/lib/libcrypto/man/d2i_ECPKParameters.3
index 5108a824869e..d1e63d76737a 100644
--- a/secure/lib/libcrypto/man/d2i_ECPKParameters.3
+++ b/secure/lib/libcrypto/man/d2i_ECPKParameters.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_ECPKParameters 3"
-.TH d2i_ECPKParameters 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_ECPKParameters 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/d2i_ECPrivateKey.3 b/secure/lib/libcrypto/man/d2i_ECPrivateKey.3
index a4deedc75882..337c08e85c1b 100644
--- a/secure/lib/libcrypto/man/d2i_ECPrivateKey.3
+++ b/secure/lib/libcrypto/man/d2i_ECPrivateKey.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_ECPrivateKey 3"
-.TH d2i_ECPrivateKey 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_ECPrivateKey 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/d2i_PKCS8PrivateKey.3 b/secure/lib/libcrypto/man/d2i_PKCS8PrivateKey.3
index d72ddc0f7260..9a02a914f7ff 100644
--- a/secure/lib/libcrypto/man/d2i_PKCS8PrivateKey.3
+++ b/secure/lib/libcrypto/man/d2i_PKCS8PrivateKey.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_PKCS8PrivateKey 3"
-.TH d2i_PKCS8PrivateKey 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_PKCS8PrivateKey 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/d2i_RSAPublicKey.3 b/secure/lib/libcrypto/man/d2i_RSAPublicKey.3
index 71c85b8f3247..323c4900c65e 100644
--- a/secure/lib/libcrypto/man/d2i_RSAPublicKey.3
+++ b/secure/lib/libcrypto/man/d2i_RSAPublicKey.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_RSAPublicKey 3"
-.TH d2i_RSAPublicKey 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_RSAPublicKey 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/d2i_X509.3 b/secure/lib/libcrypto/man/d2i_X509.3
index 5ad3dd2a6c4f..7d5fb607defa 100644
--- a/secure/lib/libcrypto/man/d2i_X509.3
+++ b/secure/lib/libcrypto/man/d2i_X509.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_X509 3"
-.TH d2i_X509 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_X509 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/d2i_X509_ALGOR.3 b/secure/lib/libcrypto/man/d2i_X509_ALGOR.3
index 5050f66c0b81..92b231367fd4 100644
--- a/secure/lib/libcrypto/man/d2i_X509_ALGOR.3
+++ b/secure/lib/libcrypto/man/d2i_X509_ALGOR.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_X509_ALGOR 3"
-.TH d2i_X509_ALGOR 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_X509_ALGOR 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/d2i_X509_CRL.3 b/secure/lib/libcrypto/man/d2i_X509_CRL.3
index ec59a39603de..db2d71d1f892 100644
--- a/secure/lib/libcrypto/man/d2i_X509_CRL.3
+++ b/secure/lib/libcrypto/man/d2i_X509_CRL.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_X509_CRL 3"
-.TH d2i_X509_CRL 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_X509_CRL 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/d2i_X509_NAME.3 b/secure/lib/libcrypto/man/d2i_X509_NAME.3
index cd795122445e..453a132a7541 100644
--- a/secure/lib/libcrypto/man/d2i_X509_NAME.3
+++ b/secure/lib/libcrypto/man/d2i_X509_NAME.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_X509_NAME 3"
-.TH d2i_X509_NAME 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_X509_NAME 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/d2i_X509_REQ.3 b/secure/lib/libcrypto/man/d2i_X509_REQ.3
index b8d20a3bd706..72fc91608c48 100644
--- a/secure/lib/libcrypto/man/d2i_X509_REQ.3
+++ b/secure/lib/libcrypto/man/d2i_X509_REQ.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_X509_REQ 3"
-.TH d2i_X509_REQ 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_X509_REQ 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/d2i_X509_SIG.3 b/secure/lib/libcrypto/man/d2i_X509_SIG.3
index 5dbb776dfab8..22ba9cd9126b 100644
--- a/secure/lib/libcrypto/man/d2i_X509_SIG.3
+++ b/secure/lib/libcrypto/man/d2i_X509_SIG.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_X509_SIG 3"
-.TH d2i_X509_SIG 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_X509_SIG 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/des.3 b/secure/lib/libcrypto/man/des.3
index a177c27be66f..5274049a6a59 100644
--- a/secure/lib/libcrypto/man/des.3
+++ b/secure/lib/libcrypto/man/des.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "des 3"
-.TH des 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH des 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/dh.3 b/secure/lib/libcrypto/man/dh.3
index cab08e2e4b61..e6cba172a2d7 100644
--- a/secure/lib/libcrypto/man/dh.3
+++ b/secure/lib/libcrypto/man/dh.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "dh 3"
-.TH dh 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH dh 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/dsa.3 b/secure/lib/libcrypto/man/dsa.3
index d45505aecaa8..4533582aa55e 100644
--- a/secure/lib/libcrypto/man/dsa.3
+++ b/secure/lib/libcrypto/man/dsa.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "dsa 3"
-.TH dsa 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH dsa 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ec.3 b/secure/lib/libcrypto/man/ec.3
index 6346a1573583..a5e483787880 100644
--- a/secure/lib/libcrypto/man/ec.3
+++ b/secure/lib/libcrypto/man/ec.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ec 3"
-.TH ec 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ec 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ecdsa.3 b/secure/lib/libcrypto/man/ecdsa.3
index 60bd3d2b683b..43175249f2bd 100644
--- a/secure/lib/libcrypto/man/ecdsa.3
+++ b/secure/lib/libcrypto/man/ecdsa.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ecdsa 3"
-.TH ecdsa 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ecdsa 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/engine.3 b/secure/lib/libcrypto/man/engine.3
index b6cb04a45909..c3059bbc53fb 100644
--- a/secure/lib/libcrypto/man/engine.3
+++ b/secure/lib/libcrypto/man/engine.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "engine 3"
-.TH engine 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH engine 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/err.3 b/secure/lib/libcrypto/man/err.3
index 09f3f3a97208..f05c2d1888f0 100644
--- a/secure/lib/libcrypto/man/err.3
+++ b/secure/lib/libcrypto/man/err.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "err 3"
-.TH err 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH err 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/evp.3 b/secure/lib/libcrypto/man/evp.3
index 37d7d2dabb84..68f84df70dd9 100644
--- a/secure/lib/libcrypto/man/evp.3
+++ b/secure/lib/libcrypto/man/evp.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "evp 3"
-.TH evp 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH evp 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/hmac.3 b/secure/lib/libcrypto/man/hmac.3
index c5654455a74e..80e7f34da294 100644
--- a/secure/lib/libcrypto/man/hmac.3
+++ b/secure/lib/libcrypto/man/hmac.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "hmac 3"
-.TH hmac 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH hmac 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/i2d_CMS_bio_stream.3 b/secure/lib/libcrypto/man/i2d_CMS_bio_stream.3
index 24375b1005b4..ade4ef0a748f 100644
--- a/secure/lib/libcrypto/man/i2d_CMS_bio_stream.3
+++ b/secure/lib/libcrypto/man/i2d_CMS_bio_stream.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "i2d_CMS_bio_stream 3"
-.TH i2d_CMS_bio_stream 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH i2d_CMS_bio_stream 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/i2d_PKCS7_bio_stream.3 b/secure/lib/libcrypto/man/i2d_PKCS7_bio_stream.3
index 6c436ce311e6..7864aef98b9f 100644
--- a/secure/lib/libcrypto/man/i2d_PKCS7_bio_stream.3
+++ b/secure/lib/libcrypto/man/i2d_PKCS7_bio_stream.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "i2d_PKCS7_bio_stream 3"
-.TH i2d_PKCS7_bio_stream 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH i2d_PKCS7_bio_stream 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/lh_stats.3 b/secure/lib/libcrypto/man/lh_stats.3
index 25a53b104062..0daa911ca364 100644
--- a/secure/lib/libcrypto/man/lh_stats.3
+++ b/secure/lib/libcrypto/man/lh_stats.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "lh_stats 3"
-.TH lh_stats 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH lh_stats 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/lhash.3 b/secure/lib/libcrypto/man/lhash.3
index d976c7f5414c..c1eed4a3a1de 100644
--- a/secure/lib/libcrypto/man/lhash.3
+++ b/secure/lib/libcrypto/man/lhash.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "lhash 3"
-.TH lhash 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH lhash 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/md5.3 b/secure/lib/libcrypto/man/md5.3
index 3cbe1ca02961..1ca7aa1ecc33 100644
--- a/secure/lib/libcrypto/man/md5.3
+++ b/secure/lib/libcrypto/man/md5.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "md5 3"
-.TH md5 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH md5 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/mdc2.3 b/secure/lib/libcrypto/man/mdc2.3
index 8331daeb3662..01437dbb1c00 100644
--- a/secure/lib/libcrypto/man/mdc2.3
+++ b/secure/lib/libcrypto/man/mdc2.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "mdc2 3"
-.TH mdc2 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH mdc2 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/pem.3 b/secure/lib/libcrypto/man/pem.3
index 4acb1e9f7708..85af9d78d555 100644
--- a/secure/lib/libcrypto/man/pem.3
+++ b/secure/lib/libcrypto/man/pem.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "pem 3"
-.TH pem 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH pem 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/rand.3 b/secure/lib/libcrypto/man/rand.3
index 5af5acd386eb..a5f269246597 100644
--- a/secure/lib/libcrypto/man/rand.3
+++ b/secure/lib/libcrypto/man/rand.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "rand 3"
-.TH rand 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH rand 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/rc4.3 b/secure/lib/libcrypto/man/rc4.3
index 10927467254f..122c4c2c0144 100644
--- a/secure/lib/libcrypto/man/rc4.3
+++ b/secure/lib/libcrypto/man/rc4.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "rc4 3"
-.TH rc4 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH rc4 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ripemd.3 b/secure/lib/libcrypto/man/ripemd.3
index 979b866ee300..63f98c83468d 100644
--- a/secure/lib/libcrypto/man/ripemd.3
+++ b/secure/lib/libcrypto/man/ripemd.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ripemd 3"
-.TH ripemd 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ripemd 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/rsa.3 b/secure/lib/libcrypto/man/rsa.3
index c79febb36c57..e8c986ac94f5 100644
--- a/secure/lib/libcrypto/man/rsa.3
+++ b/secure/lib/libcrypto/man/rsa.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "rsa 3"
-.TH rsa 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH rsa 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/sha.3 b/secure/lib/libcrypto/man/sha.3
index a375649bd1e3..5ae70f36a25c 100644
--- a/secure/lib/libcrypto/man/sha.3
+++ b/secure/lib/libcrypto/man/sha.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "sha 3"
-.TH sha 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH sha 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/threads.3 b/secure/lib/libcrypto/man/threads.3
index 041c0ae6ae47..4b50d0ee5b66 100644
--- a/secure/lib/libcrypto/man/threads.3
+++ b/secure/lib/libcrypto/man/threads.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "threads 3"
-.TH threads 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH threads 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ui.3 b/secure/lib/libcrypto/man/ui.3
index 93fcba655999..54950ab03dd4 100644
--- a/secure/lib/libcrypto/man/ui.3
+++ b/secure/lib/libcrypto/man/ui.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ui 3"
-.TH ui 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ui 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/ui_compat.3 b/secure/lib/libcrypto/man/ui_compat.3
index 322d2144db99..99a8bb9131d1 100644
--- a/secure/lib/libcrypto/man/ui_compat.3
+++ b/secure/lib/libcrypto/man/ui_compat.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ui_compat 3"
-.TH ui_compat 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ui_compat 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libcrypto/man/x509.3 b/secure/lib/libcrypto/man/x509.3
index 0e9faab26e8d..6be1e144b112 100644
--- a/secure/lib/libcrypto/man/x509.3
+++ b/secure/lib/libcrypto/man/x509.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "x509 3"
-.TH x509 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH x509 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/Makefile.man b/secure/lib/libssl/Makefile.man
index fdeb315f3c15..34e23870937a 100644
--- a/secure/lib/libssl/Makefile.man
+++ b/secure/lib/libssl/Makefile.man
@@ -46,6 +46,7 @@ MAN+= SSL_CTX_set_session_cache_mode.3
MAN+= SSL_CTX_set_session_id_context.3
MAN+= SSL_CTX_set_ssl_version.3
MAN+= SSL_CTX_set_timeout.3
+MAN+= SSL_CTX_set_tlsext_status_cb.3
MAN+= SSL_CTX_set_tlsext_ticket_key_cb.3
MAN+= SSL_CTX_set_tmp_dh_callback.3
MAN+= SSL_CTX_set_tmp_rsa_callback.3
@@ -215,6 +216,10 @@ MLINKS+= SSL_CTX_set_session_id_context.3 SSL_set_session_id_context.3
MLINKS+= SSL_CTX_set_ssl_version.3 SSL_set_ssl_method.3
MLINKS+= SSL_CTX_set_ssl_version.3 SSL_get_ssl_method.3
MLINKS+= SSL_CTX_set_timeout.3 SSL_CTX_get_timeout.3
+MLINKS+= SSL_CTX_set_tlsext_status_cb.3 SSL_CTX_set_tlsext_status_arg.3
+MLINKS+= SSL_CTX_set_tlsext_status_cb.3 SSL_set_tlsext_status_type.3
+MLINKS+= SSL_CTX_set_tlsext_status_cb.3 SSL_get_tlsext_status_ocsp_resp.3
+MLINKS+= SSL_CTX_set_tlsext_status_cb.3 SSL_set_tlsext_status_ocsp_resp.3
MLINKS+= SSL_CTX_set_tmp_dh_callback.3 SSL_CTX_set_tmp_dh.3
MLINKS+= SSL_CTX_set_tmp_dh_callback.3 SSL_set_tmp_dh_callback.3
MLINKS+= SSL_CTX_set_tmp_dh_callback.3 SSL_set_tmp_dh.3
diff --git a/secure/lib/libssl/man/SSL_CIPHER_get_name.3 b/secure/lib/libssl/man/SSL_CIPHER_get_name.3
index 7b944469bb55..fa4c52a953f8 100644
--- a/secure/lib/libssl/man/SSL_CIPHER_get_name.3
+++ b/secure/lib/libssl/man/SSL_CIPHER_get_name.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CIPHER_get_name 3"
-.TH SSL_CIPHER_get_name 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CIPHER_get_name 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_COMP_add_compression_method.3 b/secure/lib/libssl/man/SSL_COMP_add_compression_method.3
index d327d528fbd5..93121584ebd8 100644
--- a/secure/lib/libssl/man/SSL_COMP_add_compression_method.3
+++ b/secure/lib/libssl/man/SSL_COMP_add_compression_method.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_COMP_add_compression_method 3"
-.TH SSL_COMP_add_compression_method 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_COMP_add_compression_method 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CONF_CTX_new.3 b/secure/lib/libssl/man/SSL_CONF_CTX_new.3
index 6104db510e5a..47ef5cad24c7 100644
--- a/secure/lib/libssl/man/SSL_CONF_CTX_new.3
+++ b/secure/lib/libssl/man/SSL_CONF_CTX_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CONF_CTX_new 3"
-.TH SSL_CONF_CTX_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CONF_CTX_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CONF_CTX_set1_prefix.3 b/secure/lib/libssl/man/SSL_CONF_CTX_set1_prefix.3
index 905e7ac4361e..3f4d6fef9085 100644
--- a/secure/lib/libssl/man/SSL_CONF_CTX_set1_prefix.3
+++ b/secure/lib/libssl/man/SSL_CONF_CTX_set1_prefix.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CONF_CTX_set1_prefix 3"
-.TH SSL_CONF_CTX_set1_prefix 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CONF_CTX_set1_prefix 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CONF_CTX_set_flags.3 b/secure/lib/libssl/man/SSL_CONF_CTX_set_flags.3
index c75e2f5f0753..1d672673952e 100644
--- a/secure/lib/libssl/man/SSL_CONF_CTX_set_flags.3
+++ b/secure/lib/libssl/man/SSL_CONF_CTX_set_flags.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CONF_CTX_set_flags 3"
-.TH SSL_CONF_CTX_set_flags 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CONF_CTX_set_flags 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CONF_CTX_set_ssl_ctx.3 b/secure/lib/libssl/man/SSL_CONF_CTX_set_ssl_ctx.3
index eebb6d45df0b..9995aa66c4b0 100644
--- a/secure/lib/libssl/man/SSL_CONF_CTX_set_ssl_ctx.3
+++ b/secure/lib/libssl/man/SSL_CONF_CTX_set_ssl_ctx.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CONF_CTX_set_ssl_ctx 3"
-.TH SSL_CONF_CTX_set_ssl_ctx 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CONF_CTX_set_ssl_ctx 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CONF_cmd.3 b/secure/lib/libssl/man/SSL_CONF_cmd.3
index 4b7135bb8f06..26a44ca2f0e7 100644
--- a/secure/lib/libssl/man/SSL_CONF_cmd.3
+++ b/secure/lib/libssl/man/SSL_CONF_cmd.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CONF_cmd 3"
-.TH SSL_CONF_cmd 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CONF_cmd 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CONF_cmd_argv.3 b/secure/lib/libssl/man/SSL_CONF_cmd_argv.3
index ec90cab43b69..67ee8cade308 100644
--- a/secure/lib/libssl/man/SSL_CONF_cmd_argv.3
+++ b/secure/lib/libssl/man/SSL_CONF_cmd_argv.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CONF_cmd_argv 3"
-.TH SSL_CONF_cmd_argv 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CONF_cmd_argv 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_add1_chain_cert.3 b/secure/lib/libssl/man/SSL_CTX_add1_chain_cert.3
index 2b0b1554f93d..b0cabc398705 100644
--- a/secure/lib/libssl/man/SSL_CTX_add1_chain_cert.3
+++ b/secure/lib/libssl/man/SSL_CTX_add1_chain_cert.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_add1_chain_cert 3"
-.TH SSL_CTX_add1_chain_cert 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_add1_chain_cert 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_add_extra_chain_cert.3 b/secure/lib/libssl/man/SSL_CTX_add_extra_chain_cert.3
index e354223067a2..fc63eb07867a 100644
--- a/secure/lib/libssl/man/SSL_CTX_add_extra_chain_cert.3
+++ b/secure/lib/libssl/man/SSL_CTX_add_extra_chain_cert.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_add_extra_chain_cert 3"
-.TH SSL_CTX_add_extra_chain_cert 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_add_extra_chain_cert 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_add_session.3 b/secure/lib/libssl/man/SSL_CTX_add_session.3
index 0c4efd29fcd1..0a4afbd9c791 100644
--- a/secure/lib/libssl/man/SSL_CTX_add_session.3
+++ b/secure/lib/libssl/man/SSL_CTX_add_session.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_add_session 3"
-.TH SSL_CTX_add_session 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_add_session 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_ctrl.3 b/secure/lib/libssl/man/SSL_CTX_ctrl.3
index 68bd173fde4c..1bd807858edf 100644
--- a/secure/lib/libssl/man/SSL_CTX_ctrl.3
+++ b/secure/lib/libssl/man/SSL_CTX_ctrl.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_ctrl 3"
-.TH SSL_CTX_ctrl 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_ctrl 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_flush_sessions.3 b/secure/lib/libssl/man/SSL_CTX_flush_sessions.3
index 8fd1e30bca0a..4e8ce56c0883 100644
--- a/secure/lib/libssl/man/SSL_CTX_flush_sessions.3
+++ b/secure/lib/libssl/man/SSL_CTX_flush_sessions.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_flush_sessions 3"
-.TH SSL_CTX_flush_sessions 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_flush_sessions 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_free.3 b/secure/lib/libssl/man/SSL_CTX_free.3
index 1a9bd9cf9f73..60e260842e71 100644
--- a/secure/lib/libssl/man/SSL_CTX_free.3
+++ b/secure/lib/libssl/man/SSL_CTX_free.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_free 3"
-.TH SSL_CTX_free 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_free 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_get0_param.3 b/secure/lib/libssl/man/SSL_CTX_get0_param.3
index a05af054f8a0..c7b2a3227d27 100644
--- a/secure/lib/libssl/man/SSL_CTX_get0_param.3
+++ b/secure/lib/libssl/man/SSL_CTX_get0_param.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_get0_param 3"
-.TH SSL_CTX_get0_param 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_get0_param 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_get_ex_new_index.3 b/secure/lib/libssl/man/SSL_CTX_get_ex_new_index.3
index 6e5194cefc66..b4d4f90927e9 100644
--- a/secure/lib/libssl/man/SSL_CTX_get_ex_new_index.3
+++ b/secure/lib/libssl/man/SSL_CTX_get_ex_new_index.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_get_ex_new_index 3"
-.TH SSL_CTX_get_ex_new_index 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_get_ex_new_index 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_get_verify_mode.3 b/secure/lib/libssl/man/SSL_CTX_get_verify_mode.3
index aa9095eb7c23..7bb5439a3192 100644
--- a/secure/lib/libssl/man/SSL_CTX_get_verify_mode.3
+++ b/secure/lib/libssl/man/SSL_CTX_get_verify_mode.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_get_verify_mode 3"
-.TH SSL_CTX_get_verify_mode 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_get_verify_mode 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_load_verify_locations.3 b/secure/lib/libssl/man/SSL_CTX_load_verify_locations.3
index d2d37a880dd4..c5d794b49d4e 100644
--- a/secure/lib/libssl/man/SSL_CTX_load_verify_locations.3
+++ b/secure/lib/libssl/man/SSL_CTX_load_verify_locations.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_load_verify_locations 3"
-.TH SSL_CTX_load_verify_locations 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_load_verify_locations 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_new.3 b/secure/lib/libssl/man/SSL_CTX_new.3
index 60cb996daa91..3127c4ce9bf8 100644
--- a/secure/lib/libssl/man/SSL_CTX_new.3
+++ b/secure/lib/libssl/man/SSL_CTX_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_new 3"
-.TH SSL_CTX_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_sess_number.3 b/secure/lib/libssl/man/SSL_CTX_sess_number.3
index 1515053d3794..662bcc704898 100644
--- a/secure/lib/libssl/man/SSL_CTX_sess_number.3
+++ b/secure/lib/libssl/man/SSL_CTX_sess_number.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_sess_number 3"
-.TH SSL_CTX_sess_number 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_sess_number 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_sess_set_cache_size.3 b/secure/lib/libssl/man/SSL_CTX_sess_set_cache_size.3
index 0506967e82f8..9bdd6f25a3f2 100644
--- a/secure/lib/libssl/man/SSL_CTX_sess_set_cache_size.3
+++ b/secure/lib/libssl/man/SSL_CTX_sess_set_cache_size.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_sess_set_cache_size 3"
-.TH SSL_CTX_sess_set_cache_size 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_sess_set_cache_size 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_sess_set_get_cb.3 b/secure/lib/libssl/man/SSL_CTX_sess_set_get_cb.3
index d3515c4b7208..28c0d0b93428 100644
--- a/secure/lib/libssl/man/SSL_CTX_sess_set_get_cb.3
+++ b/secure/lib/libssl/man/SSL_CTX_sess_set_get_cb.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_sess_set_get_cb 3"
-.TH SSL_CTX_sess_set_get_cb 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_sess_set_get_cb 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_sessions.3 b/secure/lib/libssl/man/SSL_CTX_sessions.3
index bfe8b44baa33..b1947bc4ce0f 100644
--- a/secure/lib/libssl/man/SSL_CTX_sessions.3
+++ b/secure/lib/libssl/man/SSL_CTX_sessions.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_sessions 3"
-.TH SSL_CTX_sessions 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_sessions 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set1_curves.3 b/secure/lib/libssl/man/SSL_CTX_set1_curves.3
index 946a2d77abfd..e5509a72f8c4 100644
--- a/secure/lib/libssl/man/SSL_CTX_set1_curves.3
+++ b/secure/lib/libssl/man/SSL_CTX_set1_curves.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set1_curves 3"
-.TH SSL_CTX_set1_curves 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set1_curves 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set1_verify_cert_store.3 b/secure/lib/libssl/man/SSL_CTX_set1_verify_cert_store.3
index f22269afefc1..7ff815340f22 100644
--- a/secure/lib/libssl/man/SSL_CTX_set1_verify_cert_store.3
+++ b/secure/lib/libssl/man/SSL_CTX_set1_verify_cert_store.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set1_verify_cert_store 3"
-.TH SSL_CTX_set1_verify_cert_store 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set1_verify_cert_store 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@@ -154,10 +154,10 @@ verification or chain store
\& int SSL_CTX_set0_chain_cert_store(SSL_CTX *ctx, X509_STORE *st);
\& int SSL_CTX_set1_chain_cert_store(SSL_CTX *ctx, X509_STORE *st);
\&
-\& int SSL_set0_verify_cert_store(SSL_CTX *ctx, X509_STORE *st);
-\& int SSL_set1_verify_cert_store(SSL_CTX *ctx, X509_STORE *st);
-\& int SSL_set0_chain_cert_store(SSL_CTX *ctx, X509_STORE *st);
-\& int SSL_set1_chain_cert_store(SSL_CTX *ctx, X509_STORE *st);
+\& int SSL_set0_verify_cert_store(SSL *ctx, X509_STORE *st);
+\& int SSL_set1_verify_cert_store(SSL *ctx, X509_STORE *st);
+\& int SSL_set0_chain_cert_store(SSL *ctx, X509_STORE *st);
+\& int SSL_set1_chain_cert_store(SSL *ctx, X509_STORE *st);
.Ve
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
diff --git a/secure/lib/libssl/man/SSL_CTX_set_cert_cb.3 b/secure/lib/libssl/man/SSL_CTX_set_cert_cb.3
index ed00c3693a21..f9412dcee441 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_cert_cb.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_cert_cb.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_cert_cb 3"
-.TH SSL_CTX_set_cert_cb 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_cert_cb 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_cert_store.3 b/secure/lib/libssl/man/SSL_CTX_set_cert_store.3
index 445fa7e2f874..d617d38d433d 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_cert_store.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_cert_store.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_cert_store 3"
-.TH SSL_CTX_set_cert_store 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_cert_store 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_cert_verify_callback.3 b/secure/lib/libssl/man/SSL_CTX_set_cert_verify_callback.3
index 0599310ec028..784bfaf9d118 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_cert_verify_callback.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_cert_verify_callback.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_cert_verify_callback 3"
-.TH SSL_CTX_set_cert_verify_callback 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_cert_verify_callback 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_cipher_list.3 b/secure/lib/libssl/man/SSL_CTX_set_cipher_list.3
index 3a711f51ea83..7ce22d6eac9d 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_cipher_list.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_cipher_list.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_cipher_list 3"
-.TH SSL_CTX_set_cipher_list 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_cipher_list 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_client_CA_list.3 b/secure/lib/libssl/man/SSL_CTX_set_client_CA_list.3
index 8224a07a0b7f..f29270c279fe 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_client_CA_list.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_client_CA_list.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_client_CA_list 3"
-.TH SSL_CTX_set_client_CA_list 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_client_CA_list 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_client_cert_cb.3 b/secure/lib/libssl/man/SSL_CTX_set_client_cert_cb.3
index 551b489fe3dc..1cabee50395c 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_client_cert_cb.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_client_cert_cb.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_client_cert_cb 3"
-.TH SSL_CTX_set_client_cert_cb 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_client_cert_cb 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_custom_cli_ext.3 b/secure/lib/libssl/man/SSL_CTX_set_custom_cli_ext.3
index 8ca38bf459f1..300093ab0f06 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_custom_cli_ext.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_custom_cli_ext.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_custom_cli_ext 3"
-.TH SSL_CTX_set_custom_cli_ext 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_custom_cli_ext 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_default_passwd_cb.3 b/secure/lib/libssl/man/SSL_CTX_set_default_passwd_cb.3
index 68c1b432c436..811db17dc1d2 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_default_passwd_cb.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_default_passwd_cb.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_default_passwd_cb 3"
-.TH SSL_CTX_set_default_passwd_cb 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_default_passwd_cb 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_generate_session_id.3 b/secure/lib/libssl/man/SSL_CTX_set_generate_session_id.3
index 543072ec7af7..4c59a54a74c1 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_generate_session_id.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_generate_session_id.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_generate_session_id 3"
-.TH SSL_CTX_set_generate_session_id 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_generate_session_id 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_info_callback.3 b/secure/lib/libssl/man/SSL_CTX_set_info_callback.3
index 28307039015a..d2a92a6ba318 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_info_callback.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_info_callback.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_info_callback 3"
-.TH SSL_CTX_set_info_callback 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_info_callback 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_max_cert_list.3 b/secure/lib/libssl/man/SSL_CTX_set_max_cert_list.3
index 31bf93d574a5..fffaed4b252d 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_max_cert_list.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_max_cert_list.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_max_cert_list 3"
-.TH SSL_CTX_set_max_cert_list 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_max_cert_list 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_mode.3 b/secure/lib/libssl/man/SSL_CTX_set_mode.3
index bb63268e0f46..151ac0780a13 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_mode.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_mode.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_mode 3"
-.TH SSL_CTX_set_mode 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_mode 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_msg_callback.3 b/secure/lib/libssl/man/SSL_CTX_set_msg_callback.3
index ac58fe57ab1a..21f45ac1631d 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_msg_callback.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_msg_callback.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_msg_callback 3"
-.TH SSL_CTX_set_msg_callback 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_msg_callback 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_options.3 b/secure/lib/libssl/man/SSL_CTX_set_options.3
index 138cdc54176a..93256e0d9646 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_options.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_options.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_options 3"
-.TH SSL_CTX_set_options 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_options 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_psk_client_callback.3 b/secure/lib/libssl/man/SSL_CTX_set_psk_client_callback.3
index b4708b80f29d..a92e797dc44f 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_psk_client_callback.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_psk_client_callback.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_psk_client_callback 3"
-.TH SSL_CTX_set_psk_client_callback 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_psk_client_callback 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_quiet_shutdown.3 b/secure/lib/libssl/man/SSL_CTX_set_quiet_shutdown.3
index 8c9d08f33dc0..6f54754e54fa 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_quiet_shutdown.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_quiet_shutdown.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_quiet_shutdown 3"
-.TH SSL_CTX_set_quiet_shutdown 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_quiet_shutdown 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_read_ahead.3 b/secure/lib/libssl/man/SSL_CTX_set_read_ahead.3
index da19c435034c..e73e0caa91fc 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_read_ahead.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_read_ahead.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_read_ahead 3"
-.TH SSL_CTX_set_read_ahead 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_read_ahead 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_session_cache_mode.3 b/secure/lib/libssl/man/SSL_CTX_set_session_cache_mode.3
index 1881c7ed9438..dfcccbb859b4 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_session_cache_mode.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_session_cache_mode.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_session_cache_mode 3"
-.TH SSL_CTX_set_session_cache_mode 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_session_cache_mode 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_session_id_context.3 b/secure/lib/libssl/man/SSL_CTX_set_session_id_context.3
index d93a804999e0..5c17448508ae 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_session_id_context.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_session_id_context.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_session_id_context 3"
-.TH SSL_CTX_set_session_id_context 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_session_id_context 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_ssl_version.3 b/secure/lib/libssl/man/SSL_CTX_set_ssl_version.3
index 9339a29f67b1..452ebf7de636 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_ssl_version.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_ssl_version.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_ssl_version 3"
-.TH SSL_CTX_set_ssl_version 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_ssl_version 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_timeout.3 b/secure/lib/libssl/man/SSL_CTX_set_timeout.3
index 121cc0496bad..70530e7c74b7 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_timeout.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_timeout.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_timeout 3"
-.TH SSL_CTX_set_timeout 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_timeout 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_tlsext_status_cb.3 b/secure/lib/libssl/man/SSL_CTX_set_tlsext_status_cb.3
new file mode 100644
index 000000000000..11f995efab50
--- /dev/null
+++ b/secure/lib/libssl/man/SSL_CTX_set_tlsext_status_cb.3
@@ -0,0 +1,207 @@
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. \*(C+ will
+.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+. ds C`
+. ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+. if \nF \{
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. if !\nF==2 \{
+. nr % 0
+. nr F 2
+. \}
+. \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear. Run. Save yourself. No user-serviceable parts.
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds /
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "SSL_CTX_set_tlsext_status_cb 3"
+.TH SSL_CTX_set_tlsext_status_cb 3 "2016-01-28" "1.0.2f" "OpenSSL"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+SSL_CTX_set_tlsext_status_cb, SSL_CTX_set_tlsext_status_arg,
+SSL_set_tlsext_status_type, SSL_get_tlsext_status_ocsp_resp,
+SSL_set_tlsext_status_ocsp_resp \- OCSP Certificate Status Request functions
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+.Vb 1
+\& #include <openssl/tls1.h>
+\&
+\& long SSL_CTX_set_tlsext_status_cb(SSL_CTX *ctx,
+\& int (*callback)(SSL *, void *));
+\& long SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg);
+\&
+\& long SSL_set_tlsext_status_type(SSL *s, int type);
+\&
+\& long SSL_get_tlsext_status_ocsp_resp(ssl, unsigned char **resp);
+\& long SSL_set_tlsext_status_ocsp_resp(ssl, unsigned char *resp, int len);
+.Ve
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+A client application may request that a server send back an \s-1OCSP\s0 status response
+(also known as \s-1OCSP\s0 stapling). To do so the client should call the
+\&\fISSL_set_tlsext_status_type()\fR function prior to the start of the handshake.
+Currently the only supported type is \fBTLSEXT_STATUSTYPE_ocsp\fR. This value
+should be passed in the \fBtype\fR argument. The client should additionally provide
+a callback function to decide what to do with the returned \s-1OCSP\s0 response by
+calling \fISSL_CTX_set_tlsext_status_cb()\fR. The callback function should determine
+whether the returned \s-1OCSP\s0 response is acceptable or not. The callback will be
+passed as an argument the value previously set via a call to
+\&\fISSL_CTX_set_tlsext_status_arg()\fR. Note that the callback will not be called in
+the event of a handshake where session resumption occurs (because there are no
+Certificates exchanged in such a handshake).
+.PP
+The response returned by the server can be obtained via a call to
+\&\fISSL_get_tlsext_status_ocsp_resp()\fR. The value \fB*resp\fR will be updated to point
+to the \s-1OCSP\s0 response data and the return value will be the length of that data.
+Typically a callback would obtain an \s-1OCSP_RESPONSE\s0 object from this data via a
+call to the \fId2i_OCSP_RESPONSE()\fR function. If the server has not provided any
+response data then \fB*resp\fR will be \s-1NULL\s0 and the return value from
+\&\fISSL_get_tlsext_status_ocsp_resp()\fR will be \-1.
+.PP
+A server application must also call the \fISSL_CTX_set_tlsext_status_cb()\fR function
+if it wants to be able to provide clients with \s-1OCSP\s0 Certificate Status
+responses. Typically the server callback would obtain the server certificate
+that is being sent back to the client via a call to \fISSL_get_certificate()\fR;
+obtain the \s-1OCSP\s0 response to be sent back; and then set that response data by
+calling \fISSL_set_tlsext_status_ocsp_resp()\fR. A pointer to the response data should
+be provided in the \fBresp\fR argument, and the length of that data should be in
+the \fBlen\fR argument.
+.SH "RETURN VALUES"
+.IX Header "RETURN VALUES"
+The callback when used on the client side should return a negative value on
+error; 0 if the response is not acceptable (in which case the handshake will
+fail) or a positive value if it is acceptable.
+.PP
+The callback when used on the server side should return with either
+\&\s-1SSL_TLSEXT_ERR_OK \s0(meaning that the \s-1OCSP\s0 response that has been set should be
+returned), \s-1SSL_TLSEXT_ERR_NOACK \s0(meaning that an \s-1OCSP\s0 response should not be
+returned) or \s-1SSL_TLSEXT_ERR_ALERT_FATAL \s0(meaning that a fatal error has
+occurred).
+.PP
+\&\fISSL_CTX_set_tlsext_status_cb()\fR, \fISSL_CTX_set_tlsext_status_arg()\fR,
+\&\fISSL_set_tlsext_status_type()\fR and \fISSL_set_tlsext_status_ocsp_resp()\fR return 0 on
+error or 1 on success.
+.PP
+\&\fISSL_get_tlsext_status_ocsp_resp()\fR returns the length of the \s-1OCSP\s0 response data
+or \-1 if there is no \s-1OCSP\s0 response data.
diff --git a/secure/lib/libssl/man/SSL_CTX_set_tlsext_ticket_key_cb.3 b/secure/lib/libssl/man/SSL_CTX_set_tlsext_ticket_key_cb.3
index 3d730efc0527..63e0baaf3f25 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_tlsext_ticket_key_cb.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_tlsext_ticket_key_cb.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_tlsext_ticket_key_cb 3"
-.TH SSL_CTX_set_tlsext_ticket_key_cb 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_tlsext_ticket_key_cb 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_tmp_dh_callback.3 b/secure/lib/libssl/man/SSL_CTX_set_tmp_dh_callback.3
index fc014875478e..c04a9e0bb97f 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_tmp_dh_callback.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_tmp_dh_callback.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_tmp_dh_callback 3"
-.TH SSL_CTX_set_tmp_dh_callback 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_tmp_dh_callback 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@@ -184,25 +184,8 @@ even if he gets hold of the normal (certified) key, as this key was
only used for signing.
.PP
In order to perform a \s-1DH\s0 key exchange the server must use a \s-1DH\s0 group
-(\s-1DH\s0 parameters) and generate a \s-1DH\s0 key.
-The server will always generate a new \s-1DH\s0 key during the negotiation
-if either the \s-1DH\s0 parameters are supplied via callback or the
-\&\s-1SSL_OP_SINGLE_DH_USE\s0 option of \fISSL_CTX_set_options\fR\|(3) is set (or both).
-It will immediately create a \s-1DH\s0 key if \s-1DH\s0 parameters are supplied via
-\&\fISSL_CTX_set_tmp_dh()\fR and \s-1SSL_OP_SINGLE_DH_USE\s0 is not set.
-In this case,
-it may happen that a key is generated on initialization without later
-being needed, while on the other hand the computer time during the
-negotiation is being saved.
-.PP
-If \*(L"strong\*(R" primes were used to generate the \s-1DH\s0 parameters, it is not strictly
-necessary to generate a new key for each handshake but it does improve forward
-secrecy. If it is not assured that \*(L"strong\*(R" primes were used,
-\&\s-1SSL_OP_SINGLE_DH_USE\s0 must be used in order to prevent small subgroup
-attacks. Always using \s-1SSL_OP_SINGLE_DH_USE\s0 has an impact on the
-computer time needed during negotiation, but it is not very large, so
-application authors/users should consider always enabling this option.
-The option is required to implement perfect forward secrecy (\s-1PFS\s0).
+(\s-1DH\s0 parameters) and generate a \s-1DH\s0 key. The server will always generate
+a new \s-1DH\s0 key during the negotiation.
.PP
As generating \s-1DH\s0 parameters is extremely time consuming, an application
should not generate the parameters on the fly but supply the parameters.
@@ -229,10 +212,9 @@ can supply the \s-1DH\s0 parameters via a callback function.
Previous versions of the callback used \fBis_export\fR and \fBkeylength\fR
parameters to control parameter generation for export and non-export
cipher suites. Modern servers that do not support export ciphersuites
-are advised to either use \fISSL_CTX_set_tmp_dh()\fR in combination with
-\&\s-1SSL_OP_SINGLE_DH_USE,\s0 or alternatively, use the callback but ignore
-\&\fBkeylength\fR and \fBis_export\fR and simply supply at least 2048\-bit
-parameters in the callback.
+are advised to either use \fISSL_CTX_set_tmp_dh()\fR or alternatively, use
+the callback but ignore \fBkeylength\fR and \fBis_export\fR and simply
+supply at least 2048\-bit parameters in the callback.
.SH "EXAMPLES"
.IX Header "EXAMPLES"
Setup \s-1DH\s0 parameters with a key length of 2048 bits. (Error handling
@@ -264,7 +246,6 @@ partly left out.)
\& if (SSL_CTX_set_tmp_dh(ctx, dh_2048) != 1) {
\& /* Error. */
\& }
-\& SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
\& ...
.Ve
.SH "RETURN VALUES"
diff --git a/secure/lib/libssl/man/SSL_CTX_set_tmp_rsa_callback.3 b/secure/lib/libssl/man/SSL_CTX_set_tmp_rsa_callback.3
index 0eda38b759e0..abdb8243c762 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_tmp_rsa_callback.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_tmp_rsa_callback.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_tmp_rsa_callback 3"
-.TH SSL_CTX_set_tmp_rsa_callback 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_tmp_rsa_callback 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_set_verify.3 b/secure/lib/libssl/man/SSL_CTX_set_verify.3
index ea6782839da6..2e7fdbbaadc9 100644
--- a/secure/lib/libssl/man/SSL_CTX_set_verify.3
+++ b/secure/lib/libssl/man/SSL_CTX_set_verify.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_set_verify 3"
-.TH SSL_CTX_set_verify 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_set_verify 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_use_certificate.3 b/secure/lib/libssl/man/SSL_CTX_use_certificate.3
index 1e5b7e8958f3..c24675a379cd 100644
--- a/secure/lib/libssl/man/SSL_CTX_use_certificate.3
+++ b/secure/lib/libssl/man/SSL_CTX_use_certificate.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_use_certificate 3"
-.TH SSL_CTX_use_certificate 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_use_certificate 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_use_psk_identity_hint.3 b/secure/lib/libssl/man/SSL_CTX_use_psk_identity_hint.3
index 198578b0f4e8..79d2f6eb55d8 100644
--- a/secure/lib/libssl/man/SSL_CTX_use_psk_identity_hint.3
+++ b/secure/lib/libssl/man/SSL_CTX_use_psk_identity_hint.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_use_psk_identity_hint 3"
-.TH SSL_CTX_use_psk_identity_hint 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_use_psk_identity_hint 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_CTX_use_serverinfo.3 b/secure/lib/libssl/man/SSL_CTX_use_serverinfo.3
index 948529cb51ea..bce5345f2877 100644
--- a/secure/lib/libssl/man/SSL_CTX_use_serverinfo.3
+++ b/secure/lib/libssl/man/SSL_CTX_use_serverinfo.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_CTX_use_serverinfo 3"
-.TH SSL_CTX_use_serverinfo 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_CTX_use_serverinfo 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_SESSION_free.3 b/secure/lib/libssl/man/SSL_SESSION_free.3
index 03d8b0e69abf..e473ebf204a7 100644
--- a/secure/lib/libssl/man/SSL_SESSION_free.3
+++ b/secure/lib/libssl/man/SSL_SESSION_free.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_SESSION_free 3"
-.TH SSL_SESSION_free 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_SESSION_free 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_SESSION_get_ex_new_index.3 b/secure/lib/libssl/man/SSL_SESSION_get_ex_new_index.3
index 293278238f76..fbc75bbb36e7 100644
--- a/secure/lib/libssl/man/SSL_SESSION_get_ex_new_index.3
+++ b/secure/lib/libssl/man/SSL_SESSION_get_ex_new_index.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_SESSION_get_ex_new_index 3"
-.TH SSL_SESSION_get_ex_new_index 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_SESSION_get_ex_new_index 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_SESSION_get_time.3 b/secure/lib/libssl/man/SSL_SESSION_get_time.3
index 0878ddcc9737..8d814bdfbb67 100644
--- a/secure/lib/libssl/man/SSL_SESSION_get_time.3
+++ b/secure/lib/libssl/man/SSL_SESSION_get_time.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_SESSION_get_time 3"
-.TH SSL_SESSION_get_time 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_SESSION_get_time 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_accept.3 b/secure/lib/libssl/man/SSL_accept.3
index 85b68a24acb8..c6953adae1a4 100644
--- a/secure/lib/libssl/man/SSL_accept.3
+++ b/secure/lib/libssl/man/SSL_accept.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_accept 3"
-.TH SSL_accept 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_accept 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_alert_type_string.3 b/secure/lib/libssl/man/SSL_alert_type_string.3
index 59571f20d3ae..b049a426275e 100644
--- a/secure/lib/libssl/man/SSL_alert_type_string.3
+++ b/secure/lib/libssl/man/SSL_alert_type_string.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_alert_type_string 3"
-.TH SSL_alert_type_string 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_alert_type_string 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_check_chain.3 b/secure/lib/libssl/man/SSL_check_chain.3
index afd73e596149..bd424ae62337 100644
--- a/secure/lib/libssl/man/SSL_check_chain.3
+++ b/secure/lib/libssl/man/SSL_check_chain.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_check_chain 3"
-.TH SSL_check_chain 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_check_chain 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_clear.3 b/secure/lib/libssl/man/SSL_clear.3
index 8889174a7e3f..417fc0077adf 100644
--- a/secure/lib/libssl/man/SSL_clear.3
+++ b/secure/lib/libssl/man/SSL_clear.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_clear 3"
-.TH SSL_clear 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_clear 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_connect.3 b/secure/lib/libssl/man/SSL_connect.3
index 748c3f505e41..5b761503bf9b 100644
--- a/secure/lib/libssl/man/SSL_connect.3
+++ b/secure/lib/libssl/man/SSL_connect.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_connect 3"
-.TH SSL_connect 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_connect 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_do_handshake.3 b/secure/lib/libssl/man/SSL_do_handshake.3
index 988ae4d063ed..f23876cf4381 100644
--- a/secure/lib/libssl/man/SSL_do_handshake.3
+++ b/secure/lib/libssl/man/SSL_do_handshake.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_do_handshake 3"
-.TH SSL_do_handshake 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_do_handshake 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_free.3 b/secure/lib/libssl/man/SSL_free.3
index cb704d584077..22014b663e97 100644
--- a/secure/lib/libssl/man/SSL_free.3
+++ b/secure/lib/libssl/man/SSL_free.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_free 3"
-.TH SSL_free 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_free 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_SSL_CTX.3 b/secure/lib/libssl/man/SSL_get_SSL_CTX.3
index c36c73455ddd..628adc96e525 100644
--- a/secure/lib/libssl/man/SSL_get_SSL_CTX.3
+++ b/secure/lib/libssl/man/SSL_get_SSL_CTX.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_SSL_CTX 3"
-.TH SSL_get_SSL_CTX 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_SSL_CTX 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_ciphers.3 b/secure/lib/libssl/man/SSL_get_ciphers.3
index 6eee14fa2a90..2ded7803745d 100644
--- a/secure/lib/libssl/man/SSL_get_ciphers.3
+++ b/secure/lib/libssl/man/SSL_get_ciphers.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_ciphers 3"
-.TH SSL_get_ciphers 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_ciphers 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_client_CA_list.3 b/secure/lib/libssl/man/SSL_get_client_CA_list.3
index 6294a424711a..04f5dbf85860 100644
--- a/secure/lib/libssl/man/SSL_get_client_CA_list.3
+++ b/secure/lib/libssl/man/SSL_get_client_CA_list.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_client_CA_list 3"
-.TH SSL_get_client_CA_list 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_client_CA_list 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_current_cipher.3 b/secure/lib/libssl/man/SSL_get_current_cipher.3
index 8fa10a61151e..a431506964e0 100644
--- a/secure/lib/libssl/man/SSL_get_current_cipher.3
+++ b/secure/lib/libssl/man/SSL_get_current_cipher.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_current_cipher 3"
-.TH SSL_get_current_cipher 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_current_cipher 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_default_timeout.3 b/secure/lib/libssl/man/SSL_get_default_timeout.3
index 24835f04d0ef..3e6d71223d80 100644
--- a/secure/lib/libssl/man/SSL_get_default_timeout.3
+++ b/secure/lib/libssl/man/SSL_get_default_timeout.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_default_timeout 3"
-.TH SSL_get_default_timeout 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_default_timeout 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_error.3 b/secure/lib/libssl/man/SSL_get_error.3
index 5c2485db7c6e..156769754830 100644
--- a/secure/lib/libssl/man/SSL_get_error.3
+++ b/secure/lib/libssl/man/SSL_get_error.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_error 3"
-.TH SSL_get_error 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_error 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_ex_data_X509_STORE_CTX_idx.3 b/secure/lib/libssl/man/SSL_get_ex_data_X509_STORE_CTX_idx.3
index 7db9989c2bdb..2f57f76a5ac0 100644
--- a/secure/lib/libssl/man/SSL_get_ex_data_X509_STORE_CTX_idx.3
+++ b/secure/lib/libssl/man/SSL_get_ex_data_X509_STORE_CTX_idx.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_ex_data_X509_STORE_CTX_idx 3"
-.TH SSL_get_ex_data_X509_STORE_CTX_idx 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_ex_data_X509_STORE_CTX_idx 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_ex_new_index.3 b/secure/lib/libssl/man/SSL_get_ex_new_index.3
index f4aae89d89f0..dd95649cb859 100644
--- a/secure/lib/libssl/man/SSL_get_ex_new_index.3
+++ b/secure/lib/libssl/man/SSL_get_ex_new_index.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_ex_new_index 3"
-.TH SSL_get_ex_new_index 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_ex_new_index 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_fd.3 b/secure/lib/libssl/man/SSL_get_fd.3
index 5f49b89af236..1871375b4c96 100644
--- a/secure/lib/libssl/man/SSL_get_fd.3
+++ b/secure/lib/libssl/man/SSL_get_fd.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_fd 3"
-.TH SSL_get_fd 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_fd 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_peer_cert_chain.3 b/secure/lib/libssl/man/SSL_get_peer_cert_chain.3
index 90fa8cf345a2..0780140439b2 100644
--- a/secure/lib/libssl/man/SSL_get_peer_cert_chain.3
+++ b/secure/lib/libssl/man/SSL_get_peer_cert_chain.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_peer_cert_chain 3"
-.TH SSL_get_peer_cert_chain 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_peer_cert_chain 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_peer_certificate.3 b/secure/lib/libssl/man/SSL_get_peer_certificate.3
index d3f83bc5aad4..5395ae47ae6b 100644
--- a/secure/lib/libssl/man/SSL_get_peer_certificate.3
+++ b/secure/lib/libssl/man/SSL_get_peer_certificate.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_peer_certificate 3"
-.TH SSL_get_peer_certificate 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_peer_certificate 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_psk_identity.3 b/secure/lib/libssl/man/SSL_get_psk_identity.3
index 918aa1a86d49..19cef683aacd 100644
--- a/secure/lib/libssl/man/SSL_get_psk_identity.3
+++ b/secure/lib/libssl/man/SSL_get_psk_identity.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_psk_identity 3"
-.TH SSL_get_psk_identity 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_psk_identity 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_rbio.3 b/secure/lib/libssl/man/SSL_get_rbio.3
index cf64cc924967..256d5db24182 100644
--- a/secure/lib/libssl/man/SSL_get_rbio.3
+++ b/secure/lib/libssl/man/SSL_get_rbio.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_rbio 3"
-.TH SSL_get_rbio 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_rbio 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_session.3 b/secure/lib/libssl/man/SSL_get_session.3
index d4554dad8860..7f6b591c2707 100644
--- a/secure/lib/libssl/man/SSL_get_session.3
+++ b/secure/lib/libssl/man/SSL_get_session.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_session 3"
-.TH SSL_get_session 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_session 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_verify_result.3 b/secure/lib/libssl/man/SSL_get_verify_result.3
index 8c3aad56b59f..81d30682cf71 100644
--- a/secure/lib/libssl/man/SSL_get_verify_result.3
+++ b/secure/lib/libssl/man/SSL_get_verify_result.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_verify_result 3"
-.TH SSL_get_verify_result 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_verify_result 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_get_version.3 b/secure/lib/libssl/man/SSL_get_version.3
index 7035ce624a83..1664a41bab9c 100644
--- a/secure/lib/libssl/man/SSL_get_version.3
+++ b/secure/lib/libssl/man/SSL_get_version.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_get_version 3"
-.TH SSL_get_version 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_get_version 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_library_init.3 b/secure/lib/libssl/man/SSL_library_init.3
index 38b95af59765..33fb880dcef6 100644
--- a/secure/lib/libssl/man/SSL_library_init.3
+++ b/secure/lib/libssl/man/SSL_library_init.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_library_init 3"
-.TH SSL_library_init 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_library_init 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_load_client_CA_file.3 b/secure/lib/libssl/man/SSL_load_client_CA_file.3
index 61b43a067928..17de1dcbf129 100644
--- a/secure/lib/libssl/man/SSL_load_client_CA_file.3
+++ b/secure/lib/libssl/man/SSL_load_client_CA_file.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_load_client_CA_file 3"
-.TH SSL_load_client_CA_file 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_load_client_CA_file 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_new.3 b/secure/lib/libssl/man/SSL_new.3
index 7ed211498aaf..f05a985dbb8a 100644
--- a/secure/lib/libssl/man/SSL_new.3
+++ b/secure/lib/libssl/man/SSL_new.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_new 3"
-.TH SSL_new 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_new 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_pending.3 b/secure/lib/libssl/man/SSL_pending.3
index d3903fcd6762..b10ea7eefbc0 100644
--- a/secure/lib/libssl/man/SSL_pending.3
+++ b/secure/lib/libssl/man/SSL_pending.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_pending 3"
-.TH SSL_pending 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_pending 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_read.3 b/secure/lib/libssl/man/SSL_read.3
index 8fc6323722c3..3b2728e79605 100644
--- a/secure/lib/libssl/man/SSL_read.3
+++ b/secure/lib/libssl/man/SSL_read.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_read 3"
-.TH SSL_read 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_read 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_rstate_string.3 b/secure/lib/libssl/man/SSL_rstate_string.3
index 57095ddf0585..acd782e9d6fc 100644
--- a/secure/lib/libssl/man/SSL_rstate_string.3
+++ b/secure/lib/libssl/man/SSL_rstate_string.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_rstate_string 3"
-.TH SSL_rstate_string 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_rstate_string 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_session_reused.3 b/secure/lib/libssl/man/SSL_session_reused.3
index 4bd1b89b9d99..79624966f335 100644
--- a/secure/lib/libssl/man/SSL_session_reused.3
+++ b/secure/lib/libssl/man/SSL_session_reused.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_session_reused 3"
-.TH SSL_session_reused 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_session_reused 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_set_bio.3 b/secure/lib/libssl/man/SSL_set_bio.3
index ec6fd412cdf2..bd2d51957b70 100644
--- a/secure/lib/libssl/man/SSL_set_bio.3
+++ b/secure/lib/libssl/man/SSL_set_bio.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_set_bio 3"
-.TH SSL_set_bio 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_set_bio 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_set_connect_state.3 b/secure/lib/libssl/man/SSL_set_connect_state.3
index 5e2fed817705..8e51c95689e6 100644
--- a/secure/lib/libssl/man/SSL_set_connect_state.3
+++ b/secure/lib/libssl/man/SSL_set_connect_state.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_set_connect_state 3"
-.TH SSL_set_connect_state 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_set_connect_state 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_set_fd.3 b/secure/lib/libssl/man/SSL_set_fd.3
index 5cb627c6c9a8..a8dec759253a 100644
--- a/secure/lib/libssl/man/SSL_set_fd.3
+++ b/secure/lib/libssl/man/SSL_set_fd.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_set_fd 3"
-.TH SSL_set_fd 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_set_fd 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_set_session.3 b/secure/lib/libssl/man/SSL_set_session.3
index 7c9b269bbae6..55633c74bd2e 100644
--- a/secure/lib/libssl/man/SSL_set_session.3
+++ b/secure/lib/libssl/man/SSL_set_session.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_set_session 3"
-.TH SSL_set_session 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_set_session 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_set_shutdown.3 b/secure/lib/libssl/man/SSL_set_shutdown.3
index 8983bfa8c7a9..6f93de769dda 100644
--- a/secure/lib/libssl/man/SSL_set_shutdown.3
+++ b/secure/lib/libssl/man/SSL_set_shutdown.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_set_shutdown 3"
-.TH SSL_set_shutdown 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_set_shutdown 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_set_verify_result.3 b/secure/lib/libssl/man/SSL_set_verify_result.3
index 6492b9d30ffe..c5428546622f 100644
--- a/secure/lib/libssl/man/SSL_set_verify_result.3
+++ b/secure/lib/libssl/man/SSL_set_verify_result.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_set_verify_result 3"
-.TH SSL_set_verify_result 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_set_verify_result 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_shutdown.3 b/secure/lib/libssl/man/SSL_shutdown.3
index 7975e98d35ac..02ededfb32ea 100644
--- a/secure/lib/libssl/man/SSL_shutdown.3
+++ b/secure/lib/libssl/man/SSL_shutdown.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_shutdown 3"
-.TH SSL_shutdown 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_shutdown 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_state_string.3 b/secure/lib/libssl/man/SSL_state_string.3
index f8aad0c8cbaa..af8df58f924d 100644
--- a/secure/lib/libssl/man/SSL_state_string.3
+++ b/secure/lib/libssl/man/SSL_state_string.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_state_string 3"
-.TH SSL_state_string 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_state_string 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_want.3 b/secure/lib/libssl/man/SSL_want.3
index 417f2fc28c2d..de4a5472c508 100644
--- a/secure/lib/libssl/man/SSL_want.3
+++ b/secure/lib/libssl/man/SSL_want.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_want 3"
-.TH SSL_want 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_want 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/SSL_write.3 b/secure/lib/libssl/man/SSL_write.3
index d1e018d1114b..f1ff03bff3da 100644
--- a/secure/lib/libssl/man/SSL_write.3
+++ b/secure/lib/libssl/man/SSL_write.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SSL_write 3"
-.TH SSL_write 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SSL_write 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/d2i_SSL_SESSION.3 b/secure/lib/libssl/man/d2i_SSL_SESSION.3
index 746576e9f68e..533612512d57 100644
--- a/secure/lib/libssl/man/d2i_SSL_SESSION.3
+++ b/secure/lib/libssl/man/d2i_SSL_SESSION.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "d2i_SSL_SESSION 3"
-.TH d2i_SSL_SESSION 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH d2i_SSL_SESSION 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/lib/libssl/man/ssl.3 b/secure/lib/libssl/man/ssl.3
index 90fd9fbf8e50..bc27534c2821 100644
--- a/secure/lib/libssl/man/ssl.3
+++ b/secure/lib/libssl/man/ssl.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ssl 3"
-.TH ssl 3 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ssl 3 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/CA.pl.1 b/secure/usr.bin/openssl/man/CA.pl.1
index 1a9f97a7b5c7..81b0bf7b02a5 100644
--- a/secure/usr.bin/openssl/man/CA.pl.1
+++ b/secure/usr.bin/openssl/man/CA.pl.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CA.PL 1"
-.TH CA.PL 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CA.PL 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/asn1parse.1 b/secure/usr.bin/openssl/man/asn1parse.1
index f02283d8e2dc..afc7a532b4bf 100644
--- a/secure/usr.bin/openssl/man/asn1parse.1
+++ b/secure/usr.bin/openssl/man/asn1parse.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ASN1PARSE 1"
-.TH ASN1PARSE 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ASN1PARSE 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/c_rehash.1 b/secure/usr.bin/openssl/man/c_rehash.1
index b13de85c5769..a60ccb5cdd91 100644
--- a/secure/usr.bin/openssl/man/c_rehash.1
+++ b/secure/usr.bin/openssl/man/c_rehash.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "C_REHASH 1"
-.TH C_REHASH 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH C_REHASH 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/ca.1 b/secure/usr.bin/openssl/man/ca.1
index 1d55714a014e..d4cb79e9e51d 100644
--- a/secure/usr.bin/openssl/man/ca.1
+++ b/secure/usr.bin/openssl/man/ca.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CA 1"
-.TH CA 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CA 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/ciphers.1 b/secure/usr.bin/openssl/man/ciphers.1
index 934ce08ff678..e10144adc728 100644
--- a/secure/usr.bin/openssl/man/ciphers.1
+++ b/secure/usr.bin/openssl/man/ciphers.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CIPHERS 1"
-.TH CIPHERS 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CIPHERS 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/cms.1 b/secure/usr.bin/openssl/man/cms.1
index 8c862b978ae9..7355c9a03206 100644
--- a/secure/usr.bin/openssl/man/cms.1
+++ b/secure/usr.bin/openssl/man/cms.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CMS 1"
-.TH CMS 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CMS 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/crl.1 b/secure/usr.bin/openssl/man/crl.1
index 6e584721ad40..24c4efe2f764 100644
--- a/secure/usr.bin/openssl/man/crl.1
+++ b/secure/usr.bin/openssl/man/crl.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CRL 1"
-.TH CRL 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CRL 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/crl2pkcs7.1 b/secure/usr.bin/openssl/man/crl2pkcs7.1
index fa7eb924de3b..f8d4573e2243 100644
--- a/secure/usr.bin/openssl/man/crl2pkcs7.1
+++ b/secure/usr.bin/openssl/man/crl2pkcs7.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "CRL2PKCS7 1"
-.TH CRL2PKCS7 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH CRL2PKCS7 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/dgst.1 b/secure/usr.bin/openssl/man/dgst.1
index fa01dddf9140..746b2add1077 100644
--- a/secure/usr.bin/openssl/man/dgst.1
+++ b/secure/usr.bin/openssl/man/dgst.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DGST 1"
-.TH DGST 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DGST 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/dhparam.1 b/secure/usr.bin/openssl/man/dhparam.1
index 601ba5c8caa7..28959e35c148 100644
--- a/secure/usr.bin/openssl/man/dhparam.1
+++ b/secure/usr.bin/openssl/man/dhparam.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DHPARAM 1"
-.TH DHPARAM 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DHPARAM 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/dsa.1 b/secure/usr.bin/openssl/man/dsa.1
index 0bceba98df3c..933fb28a05f6 100644
--- a/secure/usr.bin/openssl/man/dsa.1
+++ b/secure/usr.bin/openssl/man/dsa.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DSA 1"
-.TH DSA 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DSA 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/dsaparam.1 b/secure/usr.bin/openssl/man/dsaparam.1
index d09fba7e7f51..58622b954e65 100644
--- a/secure/usr.bin/openssl/man/dsaparam.1
+++ b/secure/usr.bin/openssl/man/dsaparam.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "DSAPARAM 1"
-.TH DSAPARAM 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH DSAPARAM 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/ec.1 b/secure/usr.bin/openssl/man/ec.1
index bec981fb4843..5382d829fe90 100644
--- a/secure/usr.bin/openssl/man/ec.1
+++ b/secure/usr.bin/openssl/man/ec.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "EC 1"
-.TH EC 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH EC 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/ecparam.1 b/secure/usr.bin/openssl/man/ecparam.1
index 81bf55db2c17..3737f865075a 100644
--- a/secure/usr.bin/openssl/man/ecparam.1
+++ b/secure/usr.bin/openssl/man/ecparam.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ECPARAM 1"
-.TH ECPARAM 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ECPARAM 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/enc.1 b/secure/usr.bin/openssl/man/enc.1
index 27bd55daac89..8378679178fb 100644
--- a/secure/usr.bin/openssl/man/enc.1
+++ b/secure/usr.bin/openssl/man/enc.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ENC 1"
-.TH ENC 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ENC 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/errstr.1 b/secure/usr.bin/openssl/man/errstr.1
index 1c171c0f1c06..558f9f4faf5e 100644
--- a/secure/usr.bin/openssl/man/errstr.1
+++ b/secure/usr.bin/openssl/man/errstr.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "ERRSTR 1"
-.TH ERRSTR 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH ERRSTR 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/gendsa.1 b/secure/usr.bin/openssl/man/gendsa.1
index 9c95a779520f..e98a2814de9f 100644
--- a/secure/usr.bin/openssl/man/gendsa.1
+++ b/secure/usr.bin/openssl/man/gendsa.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "GENDSA 1"
-.TH GENDSA 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH GENDSA 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/genpkey.1 b/secure/usr.bin/openssl/man/genpkey.1
index 15cd25b22089..ad8fbd306d2a 100644
--- a/secure/usr.bin/openssl/man/genpkey.1
+++ b/secure/usr.bin/openssl/man/genpkey.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "GENPKEY 1"
-.TH GENPKEY 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH GENPKEY 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/genrsa.1 b/secure/usr.bin/openssl/man/genrsa.1
index 94fbcb4a989a..f8415b0d8c1d 100644
--- a/secure/usr.bin/openssl/man/genrsa.1
+++ b/secure/usr.bin/openssl/man/genrsa.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "GENRSA 1"
-.TH GENRSA 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH GENRSA 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/nseq.1 b/secure/usr.bin/openssl/man/nseq.1
index a760b1d8056c..f78ebd37c246 100644
--- a/secure/usr.bin/openssl/man/nseq.1
+++ b/secure/usr.bin/openssl/man/nseq.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "NSEQ 1"
-.TH NSEQ 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH NSEQ 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/ocsp.1 b/secure/usr.bin/openssl/man/ocsp.1
index fc08fefffd4f..da78b9b38f08 100644
--- a/secure/usr.bin/openssl/man/ocsp.1
+++ b/secure/usr.bin/openssl/man/ocsp.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "OCSP 1"
-.TH OCSP 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH OCSP 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/openssl.1 b/secure/usr.bin/openssl/man/openssl.1
index f8e9017e13fa..bcdb8750930f 100644
--- a/secure/usr.bin/openssl/man/openssl.1
+++ b/secure/usr.bin/openssl/man/openssl.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "OPENSSL 1"
-.TH OPENSSL 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH OPENSSL 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/passwd.1 b/secure/usr.bin/openssl/man/passwd.1
index a65ad30a62a6..6fd59b80174c 100644
--- a/secure/usr.bin/openssl/man/passwd.1
+++ b/secure/usr.bin/openssl/man/passwd.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PASSWD 1"
-.TH PASSWD 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PASSWD 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/pkcs12.1 b/secure/usr.bin/openssl/man/pkcs12.1
index 7f0e7ce641e9..c43b106c75e2 100644
--- a/secure/usr.bin/openssl/man/pkcs12.1
+++ b/secure/usr.bin/openssl/man/pkcs12.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PKCS12 1"
-.TH PKCS12 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PKCS12 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/pkcs7.1 b/secure/usr.bin/openssl/man/pkcs7.1
index 002224689b4e..7ea5a4d2ca3f 100644
--- a/secure/usr.bin/openssl/man/pkcs7.1
+++ b/secure/usr.bin/openssl/man/pkcs7.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PKCS7 1"
-.TH PKCS7 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PKCS7 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/pkcs8.1 b/secure/usr.bin/openssl/man/pkcs8.1
index 11d9d0e988e4..bccfbefc7d8d 100644
--- a/secure/usr.bin/openssl/man/pkcs8.1
+++ b/secure/usr.bin/openssl/man/pkcs8.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PKCS8 1"
-.TH PKCS8 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PKCS8 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/pkey.1 b/secure/usr.bin/openssl/man/pkey.1
index 3198c5ae3a3a..a2da1932841c 100644
--- a/secure/usr.bin/openssl/man/pkey.1
+++ b/secure/usr.bin/openssl/man/pkey.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PKEY 1"
-.TH PKEY 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PKEY 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/pkeyparam.1 b/secure/usr.bin/openssl/man/pkeyparam.1
index 7be5d4c7e614..809cdf0ee60a 100644
--- a/secure/usr.bin/openssl/man/pkeyparam.1
+++ b/secure/usr.bin/openssl/man/pkeyparam.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PKEYPARAM 1"
-.TH PKEYPARAM 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PKEYPARAM 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/pkeyutl.1 b/secure/usr.bin/openssl/man/pkeyutl.1
index fe398ffe4e13..7311f5234f09 100644
--- a/secure/usr.bin/openssl/man/pkeyutl.1
+++ b/secure/usr.bin/openssl/man/pkeyutl.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PKEYUTL 1"
-.TH PKEYUTL 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH PKEYUTL 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/rand.1 b/secure/usr.bin/openssl/man/rand.1
index 788373c4274d..2f0804979d0b 100644
--- a/secure/usr.bin/openssl/man/rand.1
+++ b/secure/usr.bin/openssl/man/rand.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RAND 1"
-.TH RAND 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RAND 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/req.1 b/secure/usr.bin/openssl/man/req.1
index d173049c628f..2b8eb1b30ce4 100644
--- a/secure/usr.bin/openssl/man/req.1
+++ b/secure/usr.bin/openssl/man/req.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "REQ 1"
-.TH REQ 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH REQ 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/rsa.1 b/secure/usr.bin/openssl/man/rsa.1
index 0feeb417b31c..12f6bb785ec7 100644
--- a/secure/usr.bin/openssl/man/rsa.1
+++ b/secure/usr.bin/openssl/man/rsa.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSA 1"
-.TH RSA 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSA 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/rsautl.1 b/secure/usr.bin/openssl/man/rsautl.1
index 76d0a6857aba..5d1d7ec1efd6 100644
--- a/secure/usr.bin/openssl/man/rsautl.1
+++ b/secure/usr.bin/openssl/man/rsautl.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "RSAUTL 1"
-.TH RSAUTL 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH RSAUTL 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/s_client.1 b/secure/usr.bin/openssl/man/s_client.1
index bfed887e39dc..74aae106804f 100644
--- a/secure/usr.bin/openssl/man/s_client.1
+++ b/secure/usr.bin/openssl/man/s_client.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "S_CLIENT 1"
-.TH S_CLIENT 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH S_CLIENT 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/s_server.1 b/secure/usr.bin/openssl/man/s_server.1
index ec7ad93e07a5..0436ae1d047a 100644
--- a/secure/usr.bin/openssl/man/s_server.1
+++ b/secure/usr.bin/openssl/man/s_server.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "S_SERVER 1"
-.TH S_SERVER 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH S_SERVER 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/s_time.1 b/secure/usr.bin/openssl/man/s_time.1
index 4d2026ffc458..284acc1cf999 100644
--- a/secure/usr.bin/openssl/man/s_time.1
+++ b/secure/usr.bin/openssl/man/s_time.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "S_TIME 1"
-.TH S_TIME 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH S_TIME 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@@ -160,7 +160,7 @@ s_time \- SSL/TLS performance timing program
[\fB\-cipher cipherlist\fR]
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
-The \fBs_client\fR command implements a generic \s-1SSL/TLS\s0 client which connects to a
+The \fBs_time\fR command implements a generic \s-1SSL/TLS\s0 client which connects to a
remote host using \s-1SSL/TLS.\s0 It can request a page from the server and includes
the time to transfer the payload data in its timing measurements. It measures
the number of connections within a given timeframe, the amount of data
@@ -242,7 +242,7 @@ optionally transfer payload data from a server. Server and client performance
and the link speed determine how many connections \fBs_time\fR can establish.
.SH "NOTES"
.IX Header "NOTES"
-\&\fBs_client\fR can be used to measure the performance of an \s-1SSL\s0 connection.
+\&\fBs_time\fR can be used to measure the performance of an \s-1SSL\s0 connection.
To connect to an \s-1SSL HTTP\s0 server and get the default page the command
.PP
.Vb 1
diff --git a/secure/usr.bin/openssl/man/sess_id.1 b/secure/usr.bin/openssl/man/sess_id.1
index fe6a3c909296..b0c54f70aeed 100644
--- a/secure/usr.bin/openssl/man/sess_id.1
+++ b/secure/usr.bin/openssl/man/sess_id.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SESS_ID 1"
-.TH SESS_ID 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SESS_ID 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/smime.1 b/secure/usr.bin/openssl/man/smime.1
index 943717f9b5d1..092218e781fd 100644
--- a/secure/usr.bin/openssl/man/smime.1
+++ b/secure/usr.bin/openssl/man/smime.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SMIME 1"
-.TH SMIME 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SMIME 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/speed.1 b/secure/usr.bin/openssl/man/speed.1
index 217b068cd464..08639bd50c8d 100644
--- a/secure/usr.bin/openssl/man/speed.1
+++ b/secure/usr.bin/openssl/man/speed.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SPEED 1"
-.TH SPEED 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SPEED 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/spkac.1 b/secure/usr.bin/openssl/man/spkac.1
index 7fc5fbfac086..8a551794a143 100644
--- a/secure/usr.bin/openssl/man/spkac.1
+++ b/secure/usr.bin/openssl/man/spkac.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "SPKAC 1"
-.TH SPKAC 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH SPKAC 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/ts.1 b/secure/usr.bin/openssl/man/ts.1
index 29357eb8f328..ba62c06a9061 100644
--- a/secure/usr.bin/openssl/man/ts.1
+++ b/secure/usr.bin/openssl/man/ts.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "TS 1"
-.TH TS 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH TS 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/tsget.1 b/secure/usr.bin/openssl/man/tsget.1
index 8bbec0d76034..5faa438b6a6e 100644
--- a/secure/usr.bin/openssl/man/tsget.1
+++ b/secure/usr.bin/openssl/man/tsget.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "TSGET 1"
-.TH TSGET 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH TSGET 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/verify.1 b/secure/usr.bin/openssl/man/verify.1
index c987a55461b0..9141659ef38d 100644
--- a/secure/usr.bin/openssl/man/verify.1
+++ b/secure/usr.bin/openssl/man/verify.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "VERIFY 1"
-.TH VERIFY 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH VERIFY 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/version.1 b/secure/usr.bin/openssl/man/version.1
index 1e22bab85419..40ec2acd256f 100644
--- a/secure/usr.bin/openssl/man/version.1
+++ b/secure/usr.bin/openssl/man/version.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "VERSION 1"
-.TH VERSION 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH VERSION 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/x509.1 b/secure/usr.bin/openssl/man/x509.1
index 546fd9088ca2..46a9476d94be 100644
--- a/secure/usr.bin/openssl/man/x509.1
+++ b/secure/usr.bin/openssl/man/x509.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509 1"
-.TH X509 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/secure/usr.bin/openssl/man/x509v3_config.1 b/secure/usr.bin/openssl/man/x509v3_config.1
index d5936ecc5d88..b4f3246f1002 100644
--- a/secure/usr.bin/openssl/man/x509v3_config.1
+++ b/secure/usr.bin/openssl/man/x509v3_config.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
.\"
.\" Standard preamble:
.\" ========================================================================
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "X509V3_CONFIG 1"
-.TH X509V3_CONFIG 1 "2015-12-03" "1.0.2e" "OpenSSL"
+.TH X509V3_CONFIG 1 "2016-01-28" "1.0.2f" "OpenSSL"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
diff --git a/share/i18n/esdb/MISC/MISC.alias b/share/i18n/esdb/MISC/MISC.alias
index 90e2ccd6f126..6ffad5d45cf6 100644
--- a/share/i18n/esdb/MISC/MISC.alias
+++ b/share/i18n/esdb/MISC/MISC.alias
@@ -29,10 +29,10 @@ JISX0208:1990 x0208
JOHAB cp1361
-SHIFT_JIS csshiftjis
-SHIFT_JIS ms_kanji
-SHIFT_JIS sjis
+Shift_JIS csshiftjis
+Shift_JIS ms_kanji
+Shift_JIS sjis
-SHIFT_JIS-2004 shift_jisx0213
+Shift_JIS-2004 shift_jisx0213
TDS565 iso-ir-230
diff --git a/share/man/man4/filemon.4 b/share/man/man4/filemon.4
index a1522c8df6ca..c0b4a51c5b4a 100644
--- a/share/man/man4/filemon.4
+++ b/share/man/man4/filemon.4
@@ -31,7 +31,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 14, 2013
+.Dd January 28, 2016
.Dt FILEMON 4
.Os
.Sh NAME
@@ -49,6 +49,18 @@ responds to two
.Xr ioctl 2
calls.
.Pp
+.Nm
+is not intended to be a security auditing tool.
+Many syscalls are not tracked and binaries of foreign ABI will not be fully
+audited.
+It is intended for auditing of processes for the purpose of determining its
+dependencies in an efficient and easily parsable format.
+An example of this is
+.Xr make 1
+which uses this module with
+.Sy .MAKE.MODE=meta
+to handle incremental builds more smartly.
+.Pp
System calls are denoted using the following single letters:
.Pp
.Bl -tag -width indent -compact
@@ -173,3 +185,12 @@ A
.Nm
device appeared in
.Fx 9.1 .
+.Sh BUGS
+Loading
+.Nm
+may reduce system performance for the noted syscalls.
+.Pp
+Only children of the set process are logged.
+Processes can escape being traced by double forking.
+This is not seen as a problem as the intended use is build monitoring, which
+does not make sense to have daemons for.
diff --git a/share/man/man4/inet.4 b/share/man/man4/inet.4
index a1d0a1cf82e3..07e7354e6083 100644
--- a/share/man/man4/inet.4
+++ b/share/man/man4/inet.4
@@ -28,7 +28,7 @@
.\" From: @(#)inet.4 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
-.Dd April 7, 2015
+.Dd Feb 4, 2016
.Dt INET 4
.Os
.Sh NAME
@@ -164,33 +164,11 @@ MIB.
In addition to the variables supported by the transport protocols
(for which the respective manual pages may be consulted),
the following general variables are defined:
-.Bl -tag -width IPCTL_FASTFORWARDING
+.Bl -tag -width IPCTL_ACCEPTSOURCEROUTE
.It Dv IPCTL_FORWARDING
.Pq ip.forwarding
Boolean: enable/disable forwarding of IP packets.
Defaults to off.
-.It Dv IPCTL_FASTFORWARDING
-.Pq ip.fastforwarding
-Boolean: enable/disable the use of
-.Tn fast IP forwarding
-code.
-Defaults to off.
-When
-.Tn fast IP forwarding
-is enabled, IP packets are forwarded directly to the appropriate network
-interface with direct processing to completion, which greatly improves
-the throughput.
-All packets for local IP addresses, non-unicast, or with IP options are
-handled by the normal IP input processing path.
-All features of the normal (slow) IP forwarding path are supported
-including firewall (through
-.Xr pfil 9
-hooks) checking, except
-.Xr ipsec 4
-tunnel brokering.
-The
-.Tn IP fastforwarding
-path does not generate ICMP redirect or source quench messages.
.It Dv IPCTL_SENDREDIRECTS
.Pq ip.redirect
Boolean: enable/disable sending of ICMP redirects in response to
diff --git a/share/man/man4/nvd.4 b/share/man/man4/nvd.4
index f5210bf4a146..f7786790cd3f 100644
--- a/share/man/man4/nvd.4
+++ b/share/man/man4/nvd.4
@@ -1,5 +1,5 @@
.\"
-.\" Copyright (c) 2012-2014 Intel Corporation
+.\" Copyright (c) 2012-2016 Intel Corporation
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 18, 2014
+.Dd January 28, 2016
.Dt NVD 4
.Os
.Sh NAME
@@ -74,6 +74,15 @@ Note that device nodes from the
driver are not
.Xr GEOM 4
disks and cannot be partitioned.
+.Sh CONFIGURATION
+The
+.Nm
+driver defines a system-wide maximum delete size for NVMe devices. The
+default is 1GB. To select a different value, set the following tunable in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+hw.nvd.delete_max=<delete size in bytes>
+.Ed
.Sh SEE ALSO
.Xr GEOM 4 ,
.Xr nvme 4 ,
diff --git a/share/mk/bsd.dep.mk b/share/mk/bsd.dep.mk
index 948f31008a71..0300e77d7e5f 100644
--- a/share/mk/bsd.dep.mk
+++ b/share/mk/bsd.dep.mk
@@ -206,12 +206,13 @@ depend: beforedepend ${DEPENDFILE} afterdepend
_CFLAGS_INCLUDES= ${CFLAGS:Q:S/\\ /,/g:C/-include,/-include%/g:C/,/ /g:M-include*:C/%/ /g}
_CXXFLAGS_INCLUDES= ${CXXFLAGS:Q:S/\\ /,/g:C/-include,/-include%/g:C/,/ /g:M-include*:C/%/ /g}
# XXX: Temporary hack to workaround .depend files not tracking -include
-.if !empty(_CFLAGS_INCLUDES)
-${OBJS} ${POBJS} ${SOBJS}: ${_CFLAGS_INCLUDES:M*.h}
-.endif
-.if !empty(_CXXFLAGS_INCLUDES)
-${OBJS} ${POBJS} ${SOBJS}: ${_CXXFLAGS_INCLUDES:M*.h}
+_hdrincludes=${_CFLAGS_INCLUDES:M*.h} ${_CXXFLAGS_INCLUDES:M*.h}
+.for _hdr in ${_hdrincludes:O:u}
+.if exists(${_hdr})
+${OBJS} ${POBJS} ${SOBJS}: ${_hdr}
.endif
+.endfor
+.undef _hdrincludes
# Different types of sources are compiled with slightly different flags.
# Split up the sources, and filter out headers and non-applicable flags.
diff --git a/share/mk/bsd.incs.mk b/share/mk/bsd.incs.mk
index 8ea97ba14fc8..0897e8d8ca35 100644
--- a/share/mk/bsd.incs.mk
+++ b/share/mk/bsd.incs.mk
@@ -80,8 +80,7 @@ _${group}INS: ${_${group}INCS}
.if defined(INCSLINKS) && !empty(INCSLINKS)
installincludes:
.for s t in ${INCSLINKS}
- @${ECHO} "$t -> $s" ; \
- ${INSTALL_SYMLINK} $s ${DESTDIR}$t
+ ${INSTALL_SYMLINK} ${s} ${DESTDIR}${t}
.endfor
.endif
.endif # !target(installincludes)
diff --git a/share/mk/bsd.links.mk b/share/mk/bsd.links.mk
index 4f8565c255f9..9e24af86624f 100644
--- a/share/mk/bsd.links.mk
+++ b/share/mk/bsd.links.mk
@@ -8,10 +8,8 @@ afterinstall: _installlinks
.ORDER: realinstall _installlinks
_installlinks:
.for s t in ${LINKS}
- @${ECHO} "$t -> $s" ;\
- ${INSTALL_LINK} ${DESTDIR}$s ${DESTDIR}$t
+ ${INSTALL_LINK} ${DESTDIR}${s} ${DESTDIR}${t}
.endfor
.for s t in ${SYMLINKS}
- @${ECHO} "$t -> $s" ;\
- ${INSTALL_SYMLINK} $s ${DESTDIR}/$t
+ ${INSTALL_SYMLINK} ${s} ${DESTDIR}${t}
.endfor
diff --git a/share/mk/bsd.man.mk b/share/mk/bsd.man.mk
index d0992b630dfb..5cfada030949 100644
--- a/share/mk/bsd.man.mk
+++ b/share/mk/bsd.man.mk
@@ -171,6 +171,17 @@ ${__target}: ${__page}
.endif # ${MK_MANCOMPRESS} == "no"
+.if !defined(NO_MLINKS) && defined(MLINKS) && !empty(MLINKS)
+.for _oname _osect _dname _dsect in ${MLINKS:C/\.([^.]*)$/.\1 \1/}
+_MANLINKS+= ${MANDIR}${_osect}${MANSUBDIR}/${_oname} \
+ ${MANDIR}${_dsect}${MANSUBDIR}/${_dname}
+.if defined(MANBUILDCAT) && !empty(MANBUILDCAT)
+_MANLINKS+= ${CATDIR}${_osect}${MANSUBDIR}/${_oname} \
+ ${CATDIR}${_dsect}${MANSUBDIR}/${_dname}
+.endif
+.endfor
+.endif
+
maninstall: _maninstall
_maninstall:
.if defined(MAN) && !empty(MAN)
@@ -215,25 +226,10 @@ _maninstall: ${MAN}
.endfor
.endif # ${MK_MANCOMPRESS} == "no"
.endif
-
-.if !defined(NO_MLINKS) && defined(MLINKS) && !empty(MLINKS)
-.for _oname _osect _dname _dsect in ${MLINKS:C/\.([^.]*)$/.\1 \1/}
- @l=${DESTDIR}${MANDIR}${_osect}${MANSUBDIR}/${_oname}; \
- t=${DESTDIR}${MANDIR}${_dsect}${MANSUBDIR}/${_dname}; \
- ${ECHO} $${t}${ZEXT} -\> $${l}${ZEXT}; \
- rm -f $${t} $${t}${MCOMPRESS_EXT}; \
- ${INSTALL_LINK} $${l}${ZEXT} $${t}${ZEXT}
+.for l t in ${_MANLINKS}
+ rm -f ${DESTDIR}${t} ${DESTDIR}${t}${MCOMPRESS_EXT}; \
+ ${INSTALL_LINK} ${DESTDIR}${l}${ZEXT} ${DESTDIR}${t}${ZEXT}
.endfor
-.if defined(MANBUILDCAT) && !empty(MANBUILDCAT)
-.for _oname _osect _dname _dsect in ${MLINKS:C/\.([^.]*)$/.\1 \1/}
- @l=${DESTDIR}${MANDIR}${_osect}${MANSUBDIR}/${_oname}; \
- t=${DESTDIR}${MANDIR}${_dsect}${MANSUBDIR}/${_dname}; \
- ${ECHO} $${t}${ZEXT} -\> $${l}${ZEXT}; \
- rm -f $${t} $${t}${MCOMPRESS_EXT}; \
- ${INSTALL_LINK} $${l}${ZEXT} $${t}${ZEXT}
-.endfor
-.endif
-.endif
manlint:
.if defined(MAN) && !empty(MAN)
diff --git a/share/mk/bsd.nls.mk b/share/mk/bsd.nls.mk
index c578361fdd53..d160a2bcf2d4 100644
--- a/share/mk/bsd.nls.mk
+++ b/share/mk/bsd.nls.mk
@@ -73,6 +73,9 @@ SYMLINKS+= ${NLSSYMLINKS}
.for file in ${NLS}
NLSNAME_${file:T}= ${file:T:R}/${NLSNAME}.cat
.if defined(NLSLINKS_${file:R}) && !empty(NLSLINKS_${file:R})
+.if !empty(NLSLINKS_${file:R}:M${file:R})
+.error NLSLINKS_${file:R} contains itself: ${file:R}
+.endif
NLSLINKS+= ${file:R}
.endif
.for dst in ${NLSLINKS_${file:R}}
diff --git a/sys/amd64/amd64/uma_machdep.c b/sys/amd64/amd64/uma_machdep.c
index db566ae89d47..fc343cabe52f 100644
--- a/sys/amd64/amd64/uma_machdep.c
+++ b/sys/amd64/amd64/uma_machdep.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/systm.h>
+#include <sys/taskqueue.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <vm/vm_pageout.h>
diff --git a/sys/arm/allwinner/a20/a20_mp.c b/sys/arm/allwinner/a20/a20_mp.c
index 27cbb3d32280..ba9ce9af0b35 100644
--- a/sys/arm/allwinner/a20/a20_mp.c
+++ b/sys/arm/allwinner/a20/a20_mp.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <machine/cpu.h>
#include <machine/smp.h>
#include <machine/fdt.h>
#include <machine/intr.h>
@@ -101,8 +102,7 @@ platform_mp_start_ap(void)
&cpucfg) != 0)
panic("Couldn't map the CPUCFG\n");
- cpu_idcache_wbinv_all();
- cpu_l2cache_wbinv_all();
+ dcache_wbinv_poc_all();
bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_P_REG0,
pmap_kextract((vm_offset_t)mpentry));
diff --git a/sys/arm/altera/socfpga/socfpga_mp.c b/sys/arm/altera/socfpga/socfpga_mp.c
index 46977f6f4804..e057eb3d706a 100644
--- a/sys/arm/altera/socfpga/socfpga_mp.c
+++ b/sys/arm/altera/socfpga/socfpga_mp.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <machine/cpu.h>
#include <machine/smp.h>
#include <machine/fdt.h>
#include <machine/intr.h>
@@ -162,8 +163,7 @@ platform_mp_start_ap(void)
bus_space_write_region_4(fdtbus_bs_tag, ram, 0,
(uint32_t *)&socfpga_trampoline, 8);
- cpu_idcache_wbinv_all();
- cpu_l2cache_wbinv_all();
+ dcache_wbinv_poc_all();
/* Put CPU1 out from reset */
bus_space_write_4(fdtbus_bs_tag, rst, MPUMODRST, 0);
diff --git a/sys/arm/amlogic/aml8726/aml8726_mp.c b/sys/arm/amlogic/aml8726/aml8726_mp.c
index 779a793e3008..c5081350df09 100644
--- a/sys/arm/amlogic/aml8726/aml8726_mp.c
+++ b/sys/arm/amlogic/aml8726/aml8726_mp.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <machine/cpu.h>
#include <machine/bus.h>
#include <machine/smp.h>
#include <machine/fdt.h>
@@ -485,7 +486,7 @@ platform_mp_start_ap(void)
value |= AML_SCU_CONTROL_ENABLE;
SCU_WRITE_4(AML_SCU_CONTROL_REG, value);
SCU_BARRIER(AML_SCU_CONTROL_REG);
- cpu_idcache_wbinv_all();
+ dcache_wbinv_poc_all();
/* Set the boot address and power on each AP. */
paddr = pmap_kextract((vm_offset_t)mpentry);
diff --git a/sys/arm/annapurna/alpine/alpine_machdep.c b/sys/arm/annapurna/alpine/alpine_machdep.c
index 959b30faa12b..dc6d3a4245db 100644
--- a/sys/arm/annapurna/alpine/alpine_machdep.c
+++ b/sys/arm/annapurna/alpine/alpine_machdep.c
@@ -123,7 +123,7 @@ platform_late_init(void)
}
/*
- * Construct pmap_devmap[] with DT-derived config data.
+ * Construct devmap table with DT-derived config data.
*/
int
platform_devmap_init(void)
diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c
index 0dd9241f27df..139899139346 100644
--- a/sys/arm/arm/cpufunc.c
+++ b/sys/arm/arm/cpufunc.c
@@ -60,18 +60,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpuconf.h>
#include <machine/cpufunc.h>
-#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
-#include <arm/xscale/i80321/i80321reg.h>
-#include <arm/xscale/i80321/i80321var.h>
-#endif
-
-/*
- * Some definitions in i81342reg.h clash with i80321reg.h.
- * This only happens for the LINT kernel. As it happens,
- * we don't need anything from i81342reg.h that we already
- * got from somewhere else during a LINT compile.
- */
-#if defined(CPU_XSCALE_81342) && !defined(COMPILING_LINT)
+#if defined(CPU_XSCALE_81342)
#include <arm/xscale/i8134x/i81342reg.h>
#endif
@@ -99,35 +88,26 @@ u_int arm_cache_level;
u_int arm_cache_type[14];
u_int arm_cache_loc;
-int ctrl;
-
#ifdef CPU_ARM9
struct cpu_functions arm9_cpufuncs = {
/* CPU functions */
- cpufunc_id, /* id */
cpufunc_nullop, /* cpwait */
/* MMU functions */
cpufunc_control, /* control */
- cpufunc_domains, /* Domain */
arm9_setttb, /* Setttb */
- cpufunc_faultstatus, /* Faultstatus */
- cpufunc_faultaddress, /* Faultaddress */
/* TLB functions */
armv4_tlb_flushID, /* tlb_flushID */
arm9_tlb_flushID_SE, /* tlb_flushID_SE */
- armv4_tlb_flushI, /* tlb_flushI */
- (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
armv4_tlb_flushD, /* tlb_flushD */
armv4_tlb_flushD_SE, /* tlb_flushD_SE */
/* Cache operations */
- arm9_icache_sync_all, /* icache_sync_all */
arm9_icache_sync_range, /* icache_sync_range */
arm9_dcache_wbinv_all, /* dcache_wbinv_all */
@@ -146,18 +126,12 @@ struct cpu_functions arm9_cpufuncs = {
/* Other functions */
- cpufunc_nullop, /* flush_prefetchbuf */
armv4_drain_writebuf, /* drain_writebuf */
- cpufunc_nullop, /* flush_brnchtgt_C */
- (void *)cpufunc_nullop, /* flush_brnchtgt_E */
(void *)cpufunc_nullop, /* sleep */
/* Soft functions */
- cpufunc_null_fixup, /* dataabt_fixup */
- cpufunc_null_fixup, /* prefetchabt_fixup */
-
arm9_context_switch, /* context_switch */
arm9_setup /* cpu setup */
@@ -169,29 +143,22 @@ struct cpu_functions arm9_cpufuncs = {
struct cpu_functions armv5_ec_cpufuncs = {
/* CPU functions */
- cpufunc_id, /* id */
cpufunc_nullop, /* cpwait */
/* MMU functions */
cpufunc_control, /* control */
- cpufunc_domains, /* Domain */
armv5_ec_setttb, /* Setttb */
- cpufunc_faultstatus, /* Faultstatus */
- cpufunc_faultaddress, /* Faultaddress */
/* TLB functions */
armv4_tlb_flushID, /* tlb_flushID */
- arm10_tlb_flushID_SE, /* tlb_flushID_SE */
- armv4_tlb_flushI, /* tlb_flushI */
- arm10_tlb_flushI_SE, /* tlb_flushI_SE */
+ arm9_tlb_flushID_SE, /* tlb_flushID_SE */
armv4_tlb_flushD, /* tlb_flushD */
armv4_tlb_flushD_SE, /* tlb_flushD_SE */
/* Cache operations */
- armv5_ec_icache_sync_all, /* icache_sync_all */
armv5_ec_icache_sync_range, /* icache_sync_range */
armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */
@@ -211,19 +178,13 @@ struct cpu_functions armv5_ec_cpufuncs = {
/* Other functions */
- cpufunc_nullop, /* flush_prefetchbuf */
armv4_drain_writebuf, /* drain_writebuf */
- cpufunc_nullop, /* flush_brnchtgt_C */
- (void *)cpufunc_nullop, /* flush_brnchtgt_E */
(void *)cpufunc_nullop, /* sleep */
/* Soft functions */
- cpufunc_null_fixup, /* dataabt_fixup */
- cpufunc_null_fixup, /* prefetchabt_fixup */
-
- arm10_context_switch, /* context_switch */
+ arm9_context_switch, /* context_switch */
arm10_setup /* cpu setup */
@@ -232,29 +193,22 @@ struct cpu_functions armv5_ec_cpufuncs = {
struct cpu_functions sheeva_cpufuncs = {
/* CPU functions */
- cpufunc_id, /* id */
cpufunc_nullop, /* cpwait */
/* MMU functions */
cpufunc_control, /* control */
- cpufunc_domains, /* Domain */
sheeva_setttb, /* Setttb */
- cpufunc_faultstatus, /* Faultstatus */
- cpufunc_faultaddress, /* Faultaddress */
/* TLB functions */
armv4_tlb_flushID, /* tlb_flushID */
- arm10_tlb_flushID_SE, /* tlb_flushID_SE */
- armv4_tlb_flushI, /* tlb_flushI */
- arm10_tlb_flushI_SE, /* tlb_flushI_SE */
+ arm9_tlb_flushID_SE, /* tlb_flushID_SE */
armv4_tlb_flushD, /* tlb_flushD */
armv4_tlb_flushD_SE, /* tlb_flushD_SE */
/* Cache operations */
- armv5_ec_icache_sync_all, /* icache_sync_all */
armv5_ec_icache_sync_range, /* icache_sync_range */
armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */
@@ -274,19 +228,13 @@ struct cpu_functions sheeva_cpufuncs = {
/* Other functions */
- cpufunc_nullop, /* flush_prefetchbuf */
armv4_drain_writebuf, /* drain_writebuf */
- cpufunc_nullop, /* flush_brnchtgt_C */
- (void *)cpufunc_nullop, /* flush_brnchtgt_E */
sheeva_cpu_sleep, /* sleep */
/* Soft functions */
- cpufunc_null_fixup, /* dataabt_fixup */
- cpufunc_null_fixup, /* prefetchabt_fixup */
-
- arm10_context_switch, /* context_switch */
+ arm9_context_switch, /* context_switch */
arm10_setup /* cpu setup */
};
@@ -296,28 +244,21 @@ struct cpu_functions sheeva_cpufuncs = {
struct cpu_functions pj4bv7_cpufuncs = {
/* CPU functions */
- cpufunc_id, /* id */
armv7_drain_writebuf, /* cpwait */
/* MMU functions */
cpufunc_control, /* control */
- cpufunc_domains, /* Domain */
armv7_setttb, /* Setttb */
- cpufunc_faultstatus, /* Faultstatus */
- cpufunc_faultaddress, /* Faultaddress */
/* TLB functions */
armv7_tlb_flushID, /* tlb_flushID */
armv7_tlb_flushID_SE, /* tlb_flushID_SE */
- armv7_tlb_flushID, /* tlb_flushI */
- armv7_tlb_flushID_SE, /* tlb_flushI_SE */
armv7_tlb_flushID, /* tlb_flushD */
armv7_tlb_flushID_SE, /* tlb_flushD_SE */
/* Cache operations */
- armv7_idcache_wbinv_all, /* icache_sync_all */
armv7_icache_sync_range, /* icache_sync_range */
armv7_dcache_wbinv_all, /* dcache_wbinv_all */
@@ -337,54 +278,38 @@ struct cpu_functions pj4bv7_cpufuncs = {
/* Other functions */
- cpufunc_nullop, /* flush_prefetchbuf */
armv7_drain_writebuf, /* drain_writebuf */
- cpufunc_nullop, /* flush_brnchtgt_C */
- (void *)cpufunc_nullop, /* flush_brnchtgt_E */
(void *)cpufunc_nullop, /* sleep */
/* Soft functions */
-
- cpufunc_null_fixup, /* dataabt_fixup */
- cpufunc_null_fixup, /* prefetchabt_fixup */
-
armv7_context_switch, /* context_switch */
pj4bv7_setup /* cpu setup */
};
#endif /* CPU_MV_PJ4B */
-#if defined(CPU_XSCALE_80321) || \
- defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
- defined(CPU_XSCALE_80219)
+#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425)
struct cpu_functions xscale_cpufuncs = {
/* CPU functions */
- cpufunc_id, /* id */
xscale_cpwait, /* cpwait */
/* MMU functions */
xscale_control, /* control */
- cpufunc_domains, /* domain */
xscale_setttb, /* setttb */
- cpufunc_faultstatus, /* faultstatus */
- cpufunc_faultaddress, /* faultaddress */
/* TLB functions */
armv4_tlb_flushID, /* tlb_flushID */
xscale_tlb_flushID_SE, /* tlb_flushID_SE */
- armv4_tlb_flushI, /* tlb_flushI */
- (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
armv4_tlb_flushD, /* tlb_flushD */
armv4_tlb_flushD_SE, /* tlb_flushD_SE */
/* Cache operations */
- xscale_cache_syncI, /* icache_sync_all */
xscale_cache_syncI_rng, /* icache_sync_range */
xscale_cache_purgeD, /* dcache_wbinv_all */
@@ -403,53 +328,39 @@ struct cpu_functions xscale_cpufuncs = {
/* Other functions */
- cpufunc_nullop, /* flush_prefetchbuf */
armv4_drain_writebuf, /* drain_writebuf */
- cpufunc_nullop, /* flush_brnchtgt_C */
- (void *)cpufunc_nullop, /* flush_brnchtgt_E */
xscale_cpu_sleep, /* sleep */
/* Soft functions */
- cpufunc_null_fixup, /* dataabt_fixup */
- cpufunc_null_fixup, /* prefetchabt_fixup */
-
xscale_context_switch, /* context_switch */
xscale_setup /* cpu setup */
};
#endif
-/* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
- CPU_XSCALE_80219 */
+/* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */
#ifdef CPU_XSCALE_81342
struct cpu_functions xscalec3_cpufuncs = {
/* CPU functions */
- cpufunc_id, /* id */
xscale_cpwait, /* cpwait */
/* MMU functions */
xscale_control, /* control */
- cpufunc_domains, /* domain */
xscalec3_setttb, /* setttb */
- cpufunc_faultstatus, /* faultstatus */
- cpufunc_faultaddress, /* faultaddress */
/* TLB functions */
armv4_tlb_flushID, /* tlb_flushID */
xscale_tlb_flushID_SE, /* tlb_flushID_SE */
- armv4_tlb_flushI, /* tlb_flushI */
- (void *)armv4_tlb_flushI, /* tlb_flushI_SE */
armv4_tlb_flushD, /* tlb_flushD */
armv4_tlb_flushD_SE, /* tlb_flushD_SE */
/* Cache operations */
- xscalec3_cache_syncI, /* icache_sync_all */
xscalec3_cache_syncI_rng, /* icache_sync_range */
xscalec3_cache_purgeD, /* dcache_wbinv_all */
@@ -468,18 +379,12 @@ struct cpu_functions xscalec3_cpufuncs = {
/* Other functions */
- cpufunc_nullop, /* flush_prefetchbuf */
armv4_drain_writebuf, /* drain_writebuf */
- cpufunc_nullop, /* flush_brnchtgt_C */
- (void *)cpufunc_nullop, /* flush_brnchtgt_E */
xscale_cpu_sleep, /* sleep */
/* Soft functions */
- cpufunc_null_fixup, /* dataabt_fixup */
- cpufunc_null_fixup, /* prefetchabt_fixup */
-
xscalec3_context_switch, /* context_switch */
xscale_setup /* cpu setup */
@@ -491,29 +396,22 @@ struct cpu_functions xscalec3_cpufuncs = {
struct cpu_functions fa526_cpufuncs = {
/* CPU functions */
- cpufunc_id, /* id */
cpufunc_nullop, /* cpwait */
/* MMU functions */
cpufunc_control, /* control */
- cpufunc_domains, /* domain */
fa526_setttb, /* setttb */
- cpufunc_faultstatus, /* faultstatus */
- cpufunc_faultaddress, /* faultaddress */
/* TLB functions */
armv4_tlb_flushID, /* tlb_flushID */
fa526_tlb_flushID_SE, /* tlb_flushID_SE */
- armv4_tlb_flushI, /* tlb_flushI */
- fa526_tlb_flushI_SE, /* tlb_flushI_SE */
armv4_tlb_flushD, /* tlb_flushD */
armv4_tlb_flushD_SE, /* tlb_flushD_SE */
/* Cache operations */
- fa526_icache_sync_all, /* icache_sync_all */
fa526_icache_sync_range, /* icache_sync_range */
fa526_dcache_wbinv_all, /* dcache_wbinv_all */
@@ -532,17 +430,12 @@ struct cpu_functions fa526_cpufuncs = {
/* Other functions */
- fa526_flush_prefetchbuf, /* flush_prefetchbuf */
armv4_drain_writebuf, /* drain_writebuf */
- cpufunc_nullop, /* flush_brnchtgt_C */
- fa526_flush_brnchtgt_E, /* flush_brnchtgt_E */
fa526_cpu_sleep, /* sleep */
/* Soft functions */
- cpufunc_null_fixup, /* dataabt_fixup */
- cpufunc_null_fixup, /* prefetchabt_fixup */
fa526_context_switch, /* context_switch */
@@ -554,29 +447,22 @@ struct cpu_functions fa526_cpufuncs = {
struct cpu_functions arm1176_cpufuncs = {
/* CPU functions */
- cpufunc_id, /* id */
cpufunc_nullop, /* cpwait */
/* MMU functions */
cpufunc_control, /* control */
- cpufunc_domains, /* Domain */
arm11x6_setttb, /* Setttb */
- cpufunc_faultstatus, /* Faultstatus */
- cpufunc_faultaddress, /* Faultaddress */
/* TLB functions */
arm11_tlb_flushID, /* tlb_flushID */
arm11_tlb_flushID_SE, /* tlb_flushID_SE */
- arm11_tlb_flushI, /* tlb_flushI */
- arm11_tlb_flushI_SE, /* tlb_flushI_SE */
arm11_tlb_flushD, /* tlb_flushD */
arm11_tlb_flushD_SE, /* tlb_flushD_SE */
/* Cache operations */
- arm11x6_icache_sync_all, /* icache_sync_all */
arm11x6_icache_sync_range, /* icache_sync_range */
arm11x6_dcache_wbinv_all, /* dcache_wbinv_all */
@@ -596,18 +482,12 @@ struct cpu_functions arm1176_cpufuncs = {
/* Other functions */
- arm11x6_flush_prefetchbuf, /* flush_prefetchbuf */
arm11_drain_writebuf, /* drain_writebuf */
- cpufunc_nullop, /* flush_brnchtgt_C */
- (void *)cpufunc_nullop, /* flush_brnchtgt_E */
arm11x6_sleep, /* sleep */
/* Soft functions */
- cpufunc_null_fixup, /* dataabt_fixup */
- cpufunc_null_fixup, /* prefetchabt_fixup */
-
arm11_context_switch, /* context_switch */
arm11x6_setup /* cpu setup */
@@ -618,16 +498,12 @@ struct cpu_functions arm1176_cpufuncs = {
struct cpu_functions cortexa_cpufuncs = {
/* CPU functions */
- cpufunc_id, /* id */
cpufunc_nullop, /* cpwait */
/* MMU functions */
cpufunc_control, /* control */
- cpufunc_domains, /* Domain */
armv7_setttb, /* Setttb */
- cpufunc_faultstatus, /* Faultstatus */
- cpufunc_faultaddress, /* Faultaddress */
/*
* TLB functions. ARMv7 does all TLB ops based on a unified TLB model
@@ -637,14 +513,11 @@ struct cpu_functions cortexa_cpufuncs = {
armv7_tlb_flushID, /* tlb_flushID */
armv7_tlb_flushID_SE, /* tlb_flushID_SE */
- armv7_tlb_flushID, /* tlb_flushI */
- armv7_tlb_flushID_SE, /* tlb_flushI_SE */
armv7_tlb_flushID, /* tlb_flushD */
armv7_tlb_flushID_SE, /* tlb_flushD_SE */
/* Cache operations */
- armv7_icache_sync_all, /* icache_sync_all */
armv7_icache_sync_range, /* icache_sync_range */
armv7_dcache_wbinv_all, /* dcache_wbinv_all */
@@ -668,18 +541,12 @@ struct cpu_functions cortexa_cpufuncs = {
/* Other functions */
- cpufunc_nullop, /* flush_prefetchbuf */
armv7_drain_writebuf, /* drain_writebuf */
- cpufunc_nullop, /* flush_brnchtgt_C */
- (void *)cpufunc_nullop, /* flush_brnchtgt_E */
armv7_cpu_sleep, /* sleep */
/* Soft functions */
- cpufunc_null_fixup, /* dataabt_fixup */
- cpufunc_null_fixup, /* prefetchabt_fixup */
-
armv7_context_switch, /* context_switch */
cortexa_setup /* cpu setup */
@@ -696,10 +563,10 @@ u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */
#if defined(CPU_ARM9) || \
defined (CPU_ARM9E) || \
- defined(CPU_ARM1176) || defined(CPU_XSCALE_80321) || \
+ defined(CPU_ARM1176) || \
defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
defined(CPU_FA526) || defined(CPU_MV_PJ4B) || \
- defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
+ defined(CPU_XSCALE_81342) || \
defined(CPU_CORTEXA) || defined(CPU_KRAIT)
/* Global cache line sizes, use 32 as default */
@@ -726,7 +593,7 @@ get_cachetype_cp15()
__asm __volatile("mrc p15, 0, %0, c0, c0, 1"
: "=r" (ctype));
- cpuid = cpufunc_id();
+ cpuid = cpu_ident();
/*
* ...and thus spake the ARM ARM:
*
@@ -833,7 +700,7 @@ get_cachetype_cp15()
int
set_cpufuncs()
{
- cputype = cpufunc_id();
+ cputype = cpu_ident();
cputype &= CPU_ID_CPU_MASK;
#ifdef CPU_ARM9
@@ -889,9 +756,6 @@ set_cpufuncs()
cpufuncs = arm1176_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */
get_cachetype_cp15();
-
- pmap_pte_init_mmu_v6();
-
goto out;
}
#endif /* CPU_ARM1176 */
@@ -915,8 +779,6 @@ set_cpufuncs()
cpufuncs = cortexa_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */
get_cachetype_cp15();
-
- pmap_pte_init_mmu_v6();
goto out;
}
#endif /* CPU_CORTEXA */
@@ -927,7 +789,6 @@ set_cpufuncs()
cputype == CPU_ID_ARM_88SV581X_V7) {
cpufuncs = pj4bv7_cpufuncs;
get_cachetype_cp15();
- pmap_pte_init_mmu_v6();
goto out;
}
#endif /* CPU_MV_PJ4B */
@@ -943,18 +804,6 @@ set_cpufuncs()
}
#endif /* CPU_FA526 */
-#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219)
- if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 ||
- cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0 ||
- cputype == CPU_ID_80219_400 || cputype == CPU_ID_80219_600) {
- cpufuncs = xscale_cpufuncs;
- cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */
- get_cachetype_cp15();
- pmap_pte_init_xscale();
- goto out;
- }
-#endif /* CPU_XSCALE_80321 */
-
#if defined(CPU_XSCALE_81342)
if (cputype == CPU_ID_81342) {
cpufuncs = xscalec3_cpufuncs;
@@ -1001,27 +850,6 @@ out:
}
/*
- * Fixup routines for data and prefetch aborts.
- *
- * Several compile time symbols are used
- *
- * DEBUG_FAULT_CORRECTION - Print debugging information during the
- * correction of registers after a fault.
- */
-
-
-/*
- * Null abort fixup routine.
- * For use when no fixup is required.
- */
-int
-cpufunc_null_fixup(arg)
- void *arg;
-{
- return(ABORT_FIXUP_OK);
-}
-
-/*
* CPU Setup code
*/
@@ -1059,7 +887,6 @@ arm9_setup(void)
/* Set the control register */
cpu_control(cpuctrlmask, cpuctrl);
- ctrl = cpuctrl;
}
#endif /* CPU_ARM9 */
@@ -1098,7 +925,6 @@ arm10_setup(void)
cpuctrl |= CPU_CONTROL_VECRELOC;
/* Set the control register */
- ctrl = cpuctrl;
cpu_control(0xffffffff, cpuctrl);
/* And again. */
@@ -1140,46 +966,11 @@ cpu_scc_setup_ccnt(void)
void
arm11x6_setup(void)
{
- int cpuctrl, cpuctrl_wax;
uint32_t auxctrl, auxctrl_wax;
uint32_t tmp, tmp2;
- uint32_t sbz=0;
uint32_t cpuid;
- cpuid = cpufunc_id();
-
- cpuctrl =
- CPU_CONTROL_MMU_ENABLE |
- CPU_CONTROL_DC_ENABLE |
- CPU_CONTROL_WBUF_ENABLE |
- CPU_CONTROL_32BP_ENABLE |
- CPU_CONTROL_32BD_ENABLE |
- CPU_CONTROL_LABT_ENABLE |
- CPU_CONTROL_SYST_ENABLE |
- CPU_CONTROL_IC_ENABLE |
- CPU_CONTROL_UNAL_ENABLE;
-
- /*
- * "write as existing" bits
- * inverse of this is mask
- */
- cpuctrl_wax =
- (3 << 30) | /* SBZ */
- (1 << 29) | /* FA */
- (1 << 28) | /* TR */
- (3 << 26) | /* SBZ */
- (3 << 19) | /* SBZ */
- (1 << 17); /* SBZ */
-
- cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
- cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
-
-#ifdef __ARMEB__
- cpuctrl |= CPU_CONTROL_BEND_ENABLE;
-#endif
-
- if (vector_page == ARM_VECTORS_HIGH)
- cpuctrl |= CPU_CONTROL_VECRELOC;
+ cpuid = cpu_ident();
auxctrl = 0;
auxctrl_wax = ~0;
@@ -1192,19 +983,6 @@ arm11x6_setup(void)
auxctrl_wax = ~ARM1176_AUXCTL_PHD;
}
- /* Clear out the cache */
- cpu_idcache_wbinv_all();
-
- /* Now really make sure they are clean. */
- __asm volatile ("mcr\tp15, 0, %0, c7, c7, 0" : : "r"(sbz));
-
- /* Allow detection code to find the VFP if it's fitted. */
- cp15_cpacr_set(0x0fffffff);
-
- /* Set the control register */
- ctrl = cpuctrl;
- cpu_control(~cpuctrl_wax, cpuctrl);
-
tmp = cp15_actlr_get();
tmp2 = tmp;
tmp &= auxctrl_wax;
@@ -1212,9 +990,6 @@ arm11x6_setup(void)
if (tmp != tmp2)
cp15_actlr_set(tmp);
- /* And again. */
- cpu_idcache_wbinv_all();
-
cpu_scc_setup_ccnt();
}
#endif /* CPU_ARM1176 */
@@ -1223,33 +998,8 @@ arm11x6_setup(void)
void
pj4bv7_setup(void)
{
- int cpuctrl;
pj4b_config();
-
- cpuctrl = CPU_CONTROL_MMU_ENABLE;
-#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
- cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
-#endif
- cpuctrl |= CPU_CONTROL_DC_ENABLE;
- cpuctrl |= (0xf << 3);
- cpuctrl |= CPU_CONTROL_BPRD_ENABLE;
- cpuctrl |= CPU_CONTROL_IC_ENABLE;
- if (vector_page == ARM_VECTORS_HIGH)
- cpuctrl |= CPU_CONTROL_VECRELOC;
- cpuctrl |= (0x5 << 16) | (1 < 22);
- cpuctrl |= CPU_CONTROL_V6_EXTPAGE;
-
- /* Clear out the cache */
- cpu_idcache_wbinv_all();
-
- /* Set the control register */
- ctrl = cpuctrl;
- cpu_control(0xFFFFFFFF, cpuctrl);
-
- /* And again. */
- cpu_idcache_wbinv_all();
-
cpu_scc_setup_ccnt();
}
#endif /* CPU_MV_PJ4B */
@@ -1259,45 +1009,6 @@ pj4bv7_setup(void)
void
cortexa_setup(void)
{
- int cpuctrl, cpuctrlmask;
-
- cpuctrlmask = CPU_CONTROL_MMU_ENABLE | /* MMU enable [0] */
- CPU_CONTROL_AFLT_ENABLE | /* Alignment fault [1] */
- CPU_CONTROL_DC_ENABLE | /* DCache enable [2] */
- CPU_CONTROL_BPRD_ENABLE | /* Branch prediction [11] */
- CPU_CONTROL_IC_ENABLE | /* ICache enable [12] */
- CPU_CONTROL_VECRELOC; /* Vector relocation [13] */
-
- cpuctrl = CPU_CONTROL_MMU_ENABLE |
- CPU_CONTROL_IC_ENABLE |
- CPU_CONTROL_DC_ENABLE |
- CPU_CONTROL_BPRD_ENABLE;
-
-#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
- cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
-#endif
-
- /* Switch to big endian */
-#ifdef __ARMEB__
- cpuctrl |= CPU_CONTROL_BEND_ENABLE;
-#endif
-
- /* Check if the vector page is at the high address (0xffff0000) */
- if (vector_page == ARM_VECTORS_HIGH)
- cpuctrl |= CPU_CONTROL_VECRELOC;
-
- /* Clear out the cache */
- cpu_idcache_wbinv_all();
-
- /* Set the control register */
- ctrl = cpuctrl;
- cpu_control(cpuctrlmask, cpuctrl);
-
- /* And again. */
- cpu_idcache_wbinv_all();
-#if defined(SMP) && !defined(ARM_NEW_PMAP)
- armv7_auxctrl((1 << 6) | (1 << 0), (1 << 6) | (1 << 0)); /* Enable SMP + TLB broadcasting */
-#endif
cpu_scc_setup_ccnt();
}
@@ -1337,14 +1048,12 @@ fa526_setup(void)
cpu_idcache_wbinv_all();
/* Set the control register */
- ctrl = cpuctrl;
cpu_control(0xffffffff, cpuctrl);
}
#endif /* CPU_FA526 */
-#if defined(CPU_XSCALE_80321) || \
- defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
- defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
+#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
+ defined(CPU_XSCALE_81342)
void
xscale_setup(void)
{
@@ -1392,7 +1101,6 @@ xscale_setup(void)
* Set the control register. Note that bits 6:3 must always
* be set to 1.
*/
- ctrl = cpuctrl;
/* cpu_control(cpuctrlmask, cpuctrl);*/
cpu_control(0xffffffff, cpuctrl);
@@ -1411,5 +1119,4 @@ xscale_setup(void)
__asm __volatile("mcr p15, 0, %0, c1, c0, 1"
: : "r" (auxctl));
}
-#endif /* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
- CPU_XSCALE_80219 */
+#endif /* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */
diff --git a/sys/arm/arm/cpufunc_asm.S b/sys/arm/arm/cpufunc_asm.S
index 12f5840365d1..2f733f564cbf 100644
--- a/sys/arm/arm/cpufunc_asm.S
+++ b/sys/arm/arm/cpufunc_asm.S
@@ -62,15 +62,10 @@ END(cpufunc_nullop)
*
*/
-ENTRY(cpufunc_id)
+ENTRY(cpu_ident)
mrc p15, 0, r0, c0, c0, 0
RET
-END(cpufunc_id)
-
-ENTRY(cpufunc_cpuid)
- mrc p15, 0, r0, c0, c0, 0
- RET
-END(cpufunc_cpuid)
+END(cpu_ident)
ENTRY(cpu_get_control)
mrc p15, 0, r0, c1, c0, 0
@@ -82,15 +77,15 @@ ENTRY(cpu_read_cache_config)
RET
END(cpu_read_cache_config)
-ENTRY(cpufunc_faultstatus)
+ENTRY(cpu_faultstatus)
mrc p15, 0, r0, c5, c0, 0
RET
-END(cpufunc_faultstatus)
+END(cpu_faultstatus)
-ENTRY(cpufunc_faultaddress)
+ENTRY(cpu_faultaddress)
mrc p15, 0, r0, c6, c0, 0
RET
-END(cpufunc_faultaddress)
+END(cpu_faultaddress)
/*
* Generic functions to write the internal coprocessor registers
@@ -110,10 +105,10 @@ ENTRY(cpufunc_control)
END(cpufunc_control)
#endif
-ENTRY(cpufunc_domains)
+ENTRY(cpu_domains)
mcr p15, 0, r0, c3, c0, 0
RET
-END(cpufunc_domains)
+END(cpu_domains)
/*
* Generic functions to read/modify/write the internal coprocessor registers
diff --git a/sys/arm/arm/cpufunc_asm_arm10.S b/sys/arm/arm/cpufunc_asm_arm10.S
deleted file mode 100644
index ab5f791976aa..000000000000
--- a/sys/arm/arm/cpufunc_asm_arm10.S
+++ /dev/null
@@ -1,76 +0,0 @@
-/* $NetBSD: cpufunc_asm_arm10.S,v 1.1 2003/09/06 09:12:29 rearnsha Exp $ */
-
-/*-
- * Copyright (c) 2002 ARM Limited
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the company may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR 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.
- *
- * ARM10 assembly functions for CPU / MMU / TLB specific operations
- *
- */
-
-#include <machine/asm.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * TLB functions
- */
-ENTRY(arm10_tlb_flushID_SE)
- mcr p15, 0, r0, c8, c6, 1 /* flush D tlb single entry */
- mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */
- bx lr
-END(arm10_tlb_flushID_SE)
-
-ENTRY(arm10_tlb_flushI_SE)
- mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */
- bx lr
-END(arm10_tlb_flushI_SE)
-
-
-/*
- * Context switch.
- *
- * These is the CPU-specific parts of the context switcher cpu_switch()
- * These functions actually perform the TTB reload.
- *
- * NOTE: Special calling convention
- * r1, r4-r13 must be preserved
- */
-ENTRY(arm10_context_switch)
- /*
- * We can assume that the caches will only contain kernel addresses
- * at this point. So no need to flush them again.
- */
- mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
- mcr p15, 0, r0, c2, c0, 0 /* set the new TTB */
- mcr p15, 0, r0, c8, c7, 0 /* and flush the I+D tlbs */
-
- /* Paranoia -- make sure the pipeline is empty. */
- nop
- nop
- nop
- bx lr
-END(arm10_context_switch)
diff --git a/sys/arm/arm/cpufunc_asm_arm11.S b/sys/arm/arm/cpufunc_asm_arm11.S
index a25decbf0fb1..f83f819d963d 100644
--- a/sys/arm/arm/cpufunc_asm_arm11.S
+++ b/sys/arm/arm/cpufunc_asm_arm11.S
@@ -47,12 +47,6 @@ ENTRY(arm11_tlb_flushID_SE)
RET
END(arm11_tlb_flushID_SE)
-ENTRY(arm11_tlb_flushI_SE)
- mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */
- mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
- RET
-END(arm11_tlb_flushI_SE)
-
/*
* Context switch.
*
@@ -87,12 +81,6 @@ ENTRY(arm11_tlb_flushID)
mov pc, lr
END(arm11_tlb_flushID)
-ENTRY(arm11_tlb_flushI)
- mcr p15, 0, r0, c8, c5, 0 /* flush I tlb */
- mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
- mov pc, lr
-END(arm11_tlb_flushI)
-
ENTRY(arm11_tlb_flushD)
mcr p15, 0, r0, c8, c6, 0 /* flush D tlb */
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
diff --git a/sys/arm/arm/cpufunc_asm_arm11x6.S b/sys/arm/arm/cpufunc_asm_arm11x6.S
index b88c0fd67ee2..793c690c9fd3 100644
--- a/sys/arm/arm/cpufunc_asm_arm11x6.S
+++ b/sys/arm/arm/cpufunc_asm_arm11x6.S
@@ -132,17 +132,6 @@ ENTRY_NP(arm11x6_dcache_wbinv_all)
RET
END(arm11x6_dcache_wbinv_all)
-ENTRY_NP(arm11x6_icache_sync_all)
- Flush_D_cache(r0)
- Invalidate_I_cache(r0, r1)
- RET
-END(arm11x6_icache_sync_all)
-
-ENTRY_NP(arm11x6_flush_prefetchbuf)
- mcr p15, 0, r0, c7, c5, 4 /* Flush Prefetch Buffer */
- RET
-END(arm11x6_flush_prefetchbuf)
-
ENTRY_NP(arm11x6_icache_sync_range)
add r1, r1, r0
sub r1, r1, #1
diff --git a/sys/arm/arm/cpufunc_asm_arm9.S b/sys/arm/arm/cpufunc_asm_arm9.S
index 9247b0c42b1c..aaadcfe6cc2b 100644
--- a/sys/arm/arm/cpufunc_asm_arm9.S
+++ b/sys/arm/arm/cpufunc_asm_arm9.S
@@ -85,9 +85,7 @@ ENTRY_NP(arm9_icache_sync_range)
subs r1, r1, ip
bhi .Larm9_sync_next
mov pc, lr
-END(arm9_icache_sync_range)
-ENTRY_NP(arm9_icache_sync_all)
.Larm9_icache_sync_all:
/*
* We assume that the code here can never be out of sync with the
@@ -109,7 +107,7 @@ ENTRY_NP(arm9_icache_sync_all)
subs s_max, s_max, s_inc
bhs .Lnext_set /* Next set */
mov pc, lr
-END(arm9_icache_sync_all)
+END(arm9_icache_sync_range)
.Larm9_line_size:
.word _C_LABEL(arm_pdcache_line_size)
diff --git a/sys/arm/arm/cpufunc_asm_armv4.S b/sys/arm/arm/cpufunc_asm_armv4.S
index a61a3dc2a306..6d665acf512e 100644
--- a/sys/arm/arm/cpufunc_asm_armv4.S
+++ b/sys/arm/arm/cpufunc_asm_armv4.S
@@ -48,11 +48,6 @@ ENTRY(armv4_tlb_flushID)
RET
END(armv4_tlb_flushID)
-ENTRY(armv4_tlb_flushI)
- mcr p15, 0, r0, c8, c5, 0 /* flush I tlb */
- RET
-END(armv4_tlb_flushI)
-
ENTRY(armv4_tlb_flushD)
mcr p15, 0, r0, c8, c6, 0 /* flush D tlb */
RET
diff --git a/sys/arm/arm/cpufunc_asm_armv5_ec.S b/sys/arm/arm/cpufunc_asm_armv5_ec.S
index 31174c659377..29e22b0975f0 100644
--- a/sys/arm/arm/cpufunc_asm_armv5_ec.S
+++ b/sys/arm/arm/cpufunc_asm_armv5_ec.S
@@ -91,9 +91,7 @@ ENTRY_NP(armv5_ec_icache_sync_range)
bpl 1b
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
RET
-END(armv5_ec_icache_sync_range)
-ENTRY_NP(armv5_ec_icache_sync_all)
.Larmv5_ec_icache_sync_all:
/*
* We assume that the code here can never be out of sync with the
@@ -109,7 +107,7 @@ ENTRY_NP(armv5_ec_icache_sync_all)
bne 1b /* More to do? */
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
RET
-END(armv5_ec_icache_sync_all)
+END(armv5_ec_icache_sync_range)
.Larmv5_ec_line_size:
.word _C_LABEL(arm_pdcache_line_size)
diff --git a/sys/arm/arm/cpufunc_asm_armv7.S b/sys/arm/arm/cpufunc_asm_armv7.S
index 42ccc6dd47e2..affd52811282 100644
--- a/sys/arm/arm/cpufunc_asm_armv7.S
+++ b/sys/arm/arm/cpufunc_asm_armv7.S
@@ -252,16 +252,6 @@ ENTRY(armv7_idcache_wbinv_range)
RET
END(armv7_idcache_wbinv_range)
-ENTRY_NP(armv7_icache_sync_all)
-#ifdef SMP
- mcr CP15_ICIALLUIS
-#else
- mcr CP15_ICIALLU
-#endif
- dsb /* data synchronization barrier */
- isb /* instruction synchronization barrier */
- RET
-END(armv7_icache_sync_all)
ENTRY_NP(armv7_icache_sync_range)
ldr ip, .Larmv7_icache_line_size
diff --git a/sys/arm/arm/cpufunc_asm_fa526.S b/sys/arm/arm/cpufunc_asm_fa526.S
index 55c2f376f738..20530ac41951 100644
--- a/sys/arm/arm/cpufunc_asm_fa526.S
+++ b/sys/arm/arm/cpufunc_asm_fa526.S
@@ -64,14 +64,6 @@ ENTRY(fa526_tlb_flushID_SE)
mov pc, lr
END(fa526_tlb_flushID_SE)
-/*
- * TLB functions
- */
-ENTRY(fa526_tlb_flushI_SE)
- mcr p15, 0, r0, c8, c5, 1 /* flush Itlb single entry */
- mov pc, lr
-END(fa526_tlb_flushI_SE)
-
ENTRY(fa526_cpu_sleep)
mov r0, #0
/* nop
@@ -80,12 +72,6 @@ ENTRY(fa526_cpu_sleep)
mov pc, lr
END(fa526_cpu_sleep)
-ENTRY(fa526_flush_prefetchbuf)
- mov r0, #0
- mcr p15, 0, r0, c7, c5, 4 /* Pre-fetch flush */
- mov pc, lr
-END(fa526_flush_prefetchbuf)
-
/*
* Cache functions
*/
@@ -97,12 +83,6 @@ ENTRY(fa526_idcache_wbinv_all)
mov pc, lr
END(fa526_idcache_wbinv_all)
-ENTRY(fa526_icache_sync_all)
- mov r0, #0
- mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ */
- mov pc, lr
-END(fa526_icache_sync_all)
-
ENTRY(fa526_dcache_wbinv_all)
mov r0, #0
mcr p15, 0, r0, c7, c14, 0 /* clean and invalidate D$ */
@@ -184,7 +164,7 @@ END(fa526_idcache_wbinv_range)
ENTRY(fa526_icache_sync_range)
cmp r1, #0x4000
- bhs _C_LABEL(fa526_icache_sync_all)
+ bhs .Lfa526_icache_sync_all
and r2, r0, #(CACHELINE_SIZE - 1)
add r1, r1, r2
@@ -198,13 +178,12 @@ ENTRY(fa526_icache_sync_range)
2: mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
mov pc, lr
-END(fa526_icache_sync_range)
-ENTRY(fa526_flush_brnchtgt_E)
+.Lfa526_icache_sync_all:
mov r0, #0
- mcr p15, 0, r0, c7, c5, 6 /* invalidate BTB cache */
+ mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ */
mov pc, lr
-END(fa526_flush_brnchtgt_E)
+END(fa526_icache_sync_range)
ENTRY(fa526_context_switch)
/*
diff --git a/sys/arm/arm/cpufunc_asm_xscale.S b/sys/arm/arm/cpufunc_asm_xscale.S
index 3031b8c150f9..8b9848ccb15f 100644
--- a/sys/arm/arm/cpufunc_asm_xscale.S
+++ b/sys/arm/arm/cpufunc_asm_xscale.S
@@ -80,9 +80,6 @@ __FBSDID("$FreeBSD$");
*/
#define DCACHE_SIZE 0x00008000
-.Lblock_userspace_access:
- .word _C_LABEL(block_userspace_access)
-
/*
* CPWAIT -- Canonical method to wait for CP15 update.
* From: Intel 80200 manual, section 2.3.3.
@@ -137,11 +134,6 @@ ENTRY(xscale_setttb)
mrs r3, cpsr
orr r1, r3, #(PSR_I | PSR_F)
msr cpsr_fsxc, r1
-#else
- ldr r3, .Lblock_userspace_access
- ldr r2, [r3]
- orr r1, r2, #1
- str r1, [r3]
#endif
stmfd sp!, {r0-r3, lr}
bl _C_LABEL(xscale_cache_cleanID)
@@ -165,8 +157,6 @@ ENTRY(xscale_setttb)
#ifdef CACHE_CLEAN_BLOCK_INTR
msr cpsr_fsxc, r3
-#else
- str r2, [r3]
#endif
RET
END(xscale_setttb)
@@ -273,14 +263,9 @@ _C_LABEL(xscale_minidata_clean_size):
#define XSCALE_CACHE_CLEAN_UNBLOCK \
msr cpsr_fsxc, r3
#else
-#define XSCALE_CACHE_CLEAN_BLOCK \
- ldr r3, .Lblock_userspace_access ; \
- ldr ip, [r3] ; \
- orr r0, ip, #1 ; \
- str r0, [r3]
+#define XSCALE_CACHE_CLEAN_BLOCK
-#define XSCALE_CACHE_CLEAN_UNBLOCK \
- str ip, [r3]
+#define XSCALE_CACHE_CLEAN_UNBLOCK
#endif /* CACHE_CLEAN_BLOCK_INTR */
#define XSCALE_CACHE_CLEAN_PROLOGUE \
diff --git a/sys/arm/arm/cpufunc_asm_xscale_c3.S b/sys/arm/arm/cpufunc_asm_xscale_c3.S
index cb770a8b873a..4e2c99999cac 100644
--- a/sys/arm/arm/cpufunc_asm_xscale_c3.S
+++ b/sys/arm/arm/cpufunc_asm_xscale_c3.S
@@ -82,9 +82,6 @@ __FBSDID("$FreeBSD$");
*/
#define DCACHE_SIZE 0x00008000
-.Lblock_userspace_access:
- .word _C_LABEL(block_userspace_access)
-
/*
* CPWAIT -- Canonical method to wait for CP15 update.
* From: Intel 80200 manual, section 2.3.3.
@@ -130,16 +127,8 @@ __FBSDID("$FreeBSD$");
msr cpsr_fsxc, r4 ; \
ldmfd sp!, {r4}
#else
-#define XSCALE_CACHE_CLEAN_BLOCK \
- stmfd sp!, {r4} ; \
- ldr r4, .Lblock_userspace_access ; \
- ldr ip, [r4] ; \
- orr r0, ip, #1 ; \
- str r0, [r4]
-
-#define XSCALE_CACHE_CLEAN_UNBLOCK \
- str ip, [r3] ; \
- ldmfd sp!, {r4}
+#define XSCALE_CACHE_CLEAN_BLOCK
+#define XSCALE_CACHE_CLEAN_UNBLOCK
#endif /* CACHE_CLEAN_BLOCK_INTR */
@@ -352,11 +341,6 @@ ENTRY(xscalec3_setttb)
mrs r3, cpsr
orr r1, r3, #(PSR_I | PSR_F)
msr cpsr_fsxc, r1
-#else
- ldr r3, .Lblock_userspace_access
- ldr r2, [r3]
- orr r1, r2, #1
- str r1, [r3]
#endif
stmfd sp!, {r0-r3, lr}
bl _C_LABEL(xscalec3_cache_cleanID)
diff --git a/sys/arm/arm/cpuinfo.c b/sys/arm/arm/cpuinfo.c
index 5e96cae90775..b2d96a7b3ef1 100644
--- a/sys/arm/arm/cpuinfo.c
+++ b/sys/arm/arm/cpuinfo.c
@@ -31,8 +31,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <machine/cpu.h>
#include <machine/cpuinfo.h>
-#include <machine/cpu-v6.h>
struct cpuinfo cpuinfo =
{
@@ -83,14 +83,16 @@ cpuinfo_init(void)
/* CP15 c0,c0 regs 0-7 exist on all CPUs (although aliased with MIDR) */
cpuinfo.ctr = cp15_ctr_get();
cpuinfo.tcmtr = cp15_tcmtr_get();
+#if __ARM_ARCH >= 6
cpuinfo.tlbtr = cp15_tlbtr_get();
cpuinfo.mpidr = cp15_mpidr_get();
cpuinfo.revidr = cp15_revidr_get();
+#endif
/* if CPU is not v7 cpu id scheme */
if (cpuinfo.architecture != 0xF)
return;
-
+#if __ARM_ARCH >= 6
cpuinfo.id_pfr0 = cp15_id_pfr0_get();
cpuinfo.id_pfr1 = cp15_id_pfr1_get();
cpuinfo.id_dfr0 = cp15_id_dfr0_get();
@@ -144,6 +146,7 @@ cpuinfo_init(void)
}
cpuinfo.dcache_line_mask = cpuinfo.dcache_line_size - 1;
cpuinfo.icache_line_mask = cpuinfo.icache_line_size - 1;
+#endif
}
/*
diff --git a/sys/arm/arm/db_interface.c b/sys/arm/arm/db_interface.c
index 43831462d896..bc49dc6e49c0 100644
--- a/sys/arm/arm/db_interface.c
+++ b/sys/arm/arm/db_interface.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
+#include <sys/cons.h>
#include <sys/proc.h>
#include <sys/reboot.h>
#include <sys/systm.h> /* just for boothowto */
@@ -53,9 +54,9 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_extern.h>
#include <machine/db_machdep.h>
+#include <machine/cpu.h>
#include <machine/machdep.h>
#include <machine/vmparam.h>
-#include <machine/cpu.h>
#include <ddb/ddb.h>
#include <ddb/db_access.h>
@@ -63,7 +64,7 @@ __FBSDID("$FreeBSD$");
#include <ddb/db_output.h>
#include <ddb/db_variables.h>
#include <ddb/db_sym.h>
-#include <sys/cons.h>
+
static int nil = 0;
@@ -170,7 +171,7 @@ db_validate_address(vm_offset_t addr)
addr >= VM_MIN_KERNEL_ADDRESS
#endif
)
- pmap = pmap_kernel();
+ pmap = kernel_pmap;
else
pmap = p->p_vmspace->vm_map.pmap;
@@ -245,11 +246,10 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data)
}
/* make sure the caches and memory are in sync */
- cpu_icache_sync_range(addr, size);
+ icache_sync(addr, size);
/* In case the current page tables have been modified ... */
- cpu_tlb_flushID();
- cpu_cpwait();
+ tlb_flush_all();
return (0);
}
diff --git a/sys/arm/arm/debug_monitor.c b/sys/arm/arm/debug_monitor.c
index 7eba5959f8e3..eaf88e9d1f07 100644
--- a/sys/arm/arm/debug_monitor.c
+++ b/sys/arm/arm/debug_monitor.c
@@ -35,14 +35,17 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/kdb.h>
#include <sys/pcpu.h>
+#include <sys/smp.h>
#include <sys/systm.h>
+#include <machine/atomic.h>
#include <machine/armreg.h>
#include <machine/cpu.h>
#include <machine/debug_monitor.h>
#include <machine/kdb.h>
#include <machine/param.h>
#include <machine/pcb.h>
+#include <machine/reg.h>
#include <ddb/ddb.h>
#include <ddb/db_access.h>
@@ -80,7 +83,7 @@ static boolean_t dbg_ossr; /* OS Save and Restore implemented */
static uint32_t dbg_watchpoint_num;
static uint32_t dbg_breakpoint_num;
-static int dbg_ref_count_mme[MAXCPU]; /* Times monitor mode was enabled */
+static int dbg_ref_count_mme; /* Times monitor mode was enabled */
/* ID_DFR0 - Debug Feature Register 0 */
#define ID_DFR0_CP_DEBUG_M_SHIFT 0
@@ -542,11 +545,9 @@ dbg_enable_monitor(void)
{
uint32_t dbg_dscr;
- /* Already enabled? Just increment reference counter and return */
- if (dbg_monitor_is_enabled()) {
- dbg_ref_count_mme[PCPU_GET(cpuid)]++;
+ /* Already enabled? Just return */
+ if (dbg_monitor_is_enabled())
return (0);
- }
dbg_dscr = cp14_dbgdscrint_get();
@@ -565,10 +566,8 @@ dbg_enable_monitor(void)
isb();
/* Verify that Monitor mode is set */
- if (dbg_monitor_is_enabled()) {
- dbg_ref_count_mme[PCPU_GET(cpuid)]++;
+ if (dbg_monitor_is_enabled())
return (0);
- }
return (ENXIO);
}
@@ -581,9 +580,6 @@ dbg_disable_monitor(void)
if (!dbg_monitor_is_enabled())
return (0);
- if (--dbg_ref_count_mme[PCPU_GET(cpuid)] > 0)
- return (0);
-
dbg_dscr = cp14_dbgdscrint_get();
switch (dbg_model) {
case ID_DFR0_CP_DEBUG_M_V6:
@@ -607,11 +603,13 @@ dbg_disable_monitor(void)
static int
dbg_setup_xpoint(struct dbg_wb_conf *conf)
{
+ struct pcpu *pcpu;
+ struct dbreg *d;
const char *typestr;
uint32_t cr_size, cr_priv, cr_access;
uint32_t reg_ctrl, reg_addr, ctrl, addr;
boolean_t is_bkpt;
- u_int cpuid;
+ u_int cpuid, cpu;
u_int i;
int err;
@@ -705,20 +703,52 @@ dbg_setup_xpoint(struct dbg_wb_conf *conf)
dbg_wb_write_reg(reg_addr, i, addr);
dbg_wb_write_reg(reg_ctrl, i, ctrl);
- return (dbg_enable_monitor());
+ err = dbg_enable_monitor();
+ if (err != 0)
+ return (err);
+
+ /* Increment monitor enable counter */
+ dbg_ref_count_mme++;
+
+ /*
+ * Save watchpoint settings for all CPUs.
+ * We don't need to do the same with breakpoints since HW breakpoints
+ * are only used to perform single stepping.
+ */
+ if (!is_bkpt) {
+ CPU_FOREACH(cpu) {
+ pcpu = pcpu_find(cpu);
+ /* Fill out the settings for watchpoint */
+ d = (struct dbreg *)pcpu->pc_dbreg;
+ d->dbg_wvr[i] = addr;
+ d->dbg_wcr[i] = ctrl;
+ /* Skip update command for the current CPU */
+ if (cpu != cpuid)
+ pcpu->pc_dbreg_cmd = PC_DBREG_CMD_LOAD;
+ }
+ }
+ /* Ensure all data is written before waking other CPUs */
+ atomic_thread_fence_rel();
+
+ return (0);
}
static int
dbg_remove_xpoint(struct dbg_wb_conf *conf)
{
+ struct pcpu *pcpu;
+ struct dbreg *d;
uint32_t reg_ctrl, reg_addr, addr;
- u_int cpuid;
+ boolean_t is_bkpt;
+ u_int cpuid, cpu;
u_int i;
int err;
if (!dbg_capable)
return (ENXIO);
+ is_bkpt = (conf->type == DBG_TYPE_BREAKPOINT);
+
cpuid = PCPU_GET(cpuid);
if (!dbg_ready[cpuid]) {
err = dbg_reset_state();
@@ -729,7 +759,7 @@ dbg_remove_xpoint(struct dbg_wb_conf *conf)
addr = conf->address;
- if (conf->type == DBG_TYPE_BREAKPOINT) {
+ if (is_bkpt) {
i = conf->slot;
reg_ctrl = DBG_REG_BASE_BCR;
reg_addr = DBG_REG_BASE_BVR;
@@ -746,7 +776,40 @@ dbg_remove_xpoint(struct dbg_wb_conf *conf)
dbg_wb_write_reg(reg_ctrl, i, 0);
dbg_wb_write_reg(reg_addr, i, 0);
- return (dbg_disable_monitor());
+ /* Decrement monitor enable counter */
+ dbg_ref_count_mme--;
+ if (dbg_ref_count_mme < 0)
+ dbg_ref_count_mme = 0;
+
+ atomic_thread_fence_rel();
+
+ if (dbg_ref_count_mme == 0) {
+ err = dbg_disable_monitor();
+ if (err != 0)
+ return (err);
+ }
+
+ /*
+ * Save watchpoint settings for all CPUs.
+ * We don't need to do the same with breakpoints since HW breakpoints
+ * are only used to perform single stepping.
+ */
+ if (!is_bkpt) {
+ CPU_FOREACH(cpu) {
+ pcpu = pcpu_find(cpu);
+ /* Fill out the settings for watchpoint */
+ d = (struct dbreg *)pcpu->pc_dbreg;
+ d->dbg_wvr[i] = 0;
+ d->dbg_wcr[i] = 0;
+ /* Skip update command for the current CPU */
+ if (cpu != cpuid)
+ pcpu->pc_dbreg_cmd = PC_DBREG_CMD_LOAD;
+ }
+ /* Ensure all data is written before waking other CPUs */
+ atomic_thread_fence_rel();
+ }
+
+ return (0);
}
static __inline uint32_t
@@ -782,8 +845,10 @@ dbg_arch_supported(void)
{
switch (dbg_model) {
+#ifdef not_yet
case ID_DFR0_CP_DEBUG_M_V6:
case ID_DFR0_CP_DEBUG_M_V6_1:
+#endif
case ID_DFR0_CP_DEBUG_M_V7:
case ID_DFR0_CP_DEBUG_M_V7_1: /* fall through */
return (TRUE);
@@ -941,3 +1006,67 @@ dbg_monitor_init(void)
db_printf("HW Breakpoints/Watchpoints not enabled on CPU%d\n",
PCPU_GET(cpuid));
}
+
+CTASSERT(sizeof(struct dbreg) == sizeof(((struct pcpu *)NULL)->pc_dbreg));
+
+void
+dbg_resume_dbreg(void)
+{
+ struct dbreg *d;
+ u_int cpuid;
+ u_int i;
+ int err;
+
+ /*
+ * This flag is set on the primary CPU
+ * and its meaning is valid for other CPUs too.
+ */
+ if (!dbg_capable)
+ return;
+
+ atomic_thread_fence_acq();
+
+ switch (PCPU_GET(dbreg_cmd)) {
+ case PC_DBREG_CMD_LOAD:
+ d = (struct dbreg *)PCPU_PTR(dbreg);
+ cpuid = PCPU_GET(cpuid);
+
+ /* Reset Debug Architecture State if not done earlier */
+ if (!dbg_ready[cpuid]) {
+ err = dbg_reset_state();
+ if (err != 0) {
+ /*
+ * Something is very wrong.
+ * WPs/BPs will not work correctly in this CPU.
+ */
+ panic("%s: Failed to reset Debug Architecture "
+ "state on CPU%d", __func__, cpuid);
+ }
+ dbg_ready[cpuid] = TRUE;
+ }
+
+ /* Restore watchpoints */
+ for (i = 0; i < dbg_watchpoint_num; i++) {
+ dbg_wb_write_reg(DBG_REG_BASE_WVR, i, d->dbg_wvr[i]);
+ dbg_wb_write_reg(DBG_REG_BASE_WCR, i, d->dbg_wcr[i]);
+ }
+
+ if ((dbg_ref_count_mme > 0) && !dbg_monitor_is_enabled()) {
+ err = dbg_enable_monitor();
+ if (err != 0) {
+ panic("%s: Failed to enable Debug Monitor "
+ "on CPU%d", __func__, cpuid);
+ }
+ }
+ if ((dbg_ref_count_mme == 0) && dbg_monitor_is_enabled()) {
+ err = dbg_disable_monitor();
+ if (err != 0) {
+ panic("%s: Failed to disable Debug Monitor "
+ "on CPU%d", __func__, cpuid);
+ }
+ }
+
+ PCPU_SET(dbreg_cmd, PC_DBREG_CMD_NONE);
+ break;
+ }
+}
diff --git a/sys/arm/arm/devmap.c b/sys/arm/arm/devmap.c
index 823210f90604..011b5797881a 100644
--- a/sys/arm/arm/devmap.c
+++ b/sys/arm/arm/devmap.c
@@ -40,6 +40,9 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <vm/pmap.h>
+#ifdef __arm__
+#include <machine/acle-compat.h>
+#endif
#include <machine/armreg.h>
#include <machine/devmap.h>
#include <machine/vmparam.h>
@@ -204,8 +207,13 @@ arm_devmap_bootstrap(vm_offset_t l1pt, const struct arm_devmap_entry *table)
for (pd = devmap_table; pd->pd_size != 0; ++pd) {
#if defined(__arm__)
+#if __ARM_ARCH >= 6
+ pmap_preboot_map_attr(pd->pd_pa, pd->pd_va, pd->pd_size,
+ pd->pd_prot, pd->pd_cache);
+#else
pmap_map_chunk(l1pt, pd->pd_va, pd->pd_pa, pd->pd_size,
- pd->pd_prot,pd->pd_cache);
+ pd->pd_prot, pd->pd_cache);
+#endif
#elif defined(__aarch64__)
pmap_kenter_device(pd->pd_va, pd->pd_size, pd->pd_pa);
#endif
diff --git a/sys/arm/arm/dump_machdep.c b/sys/arm/arm/dump_machdep.c
index e87d3e7c835d..2c11141c4b0e 100644
--- a/sys/arm/arm/dump_machdep.c
+++ b/sys/arm/arm/dump_machdep.c
@@ -59,8 +59,7 @@ dumpsys_wbinv_all(void)
* have already been stopped, and their flush/invalidate was done as
* part of stopping.
*/
- cpu_idcache_wbinv_all();
- cpu_l2cache_wbinv_all();
+ dcache_wbinv_poc_all();
#ifdef __XSCALE__
xscale_cache_clean_minidata();
#endif
diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c
index 7dbdc912c821..2ec659aba802 100644
--- a/sys/arm/arm/elf_machdep.c
+++ b/sys/arm/arm/elf_machdep.c
@@ -282,7 +282,7 @@ elf_cpu_load_file(linker_file_t lf)
#else
cpu_dcache_wb_range((vm_offset_t)lf->address, (vm_size_t)lf->size);
cpu_l2cache_wb_range((vm_offset_t)lf->address, (vm_size_t)lf->size);
- cpu_icache_sync_all();
+ cpu_icache_sync_range((vm_offset_t)lf->address, (vm_size_t)lf->size);
#endif
return (0);
}
diff --git a/sys/arm/arm/elf_trampoline.c b/sys/arm/arm/elf_trampoline.c
index c3a7eeddfc93..22f0f44ae575 100644
--- a/sys/arm/arm/elf_trampoline.c
+++ b/sys/arm/arm/elf_trampoline.c
@@ -49,7 +49,7 @@ void _start(void);
void __start(void);
void __startC(void);
-extern unsigned int cpufunc_id(void);
+extern unsigned int cpu_ident(void);
extern void armv6_idcache_wbinv_all(void);
extern void armv7_idcache_wbinv_all(void);
extern void do_call(void *, void *, void *, int);
@@ -67,9 +67,7 @@ extern void fa526_idcache_wbinv_all(void);
extern void armv5_ec_idcache_wbinv_all(void);
#elif defined(CPU_ARM1176)
#define cpu_idcache_wbinv_all armv6_idcache_wbinv_all
-#elif defined(CPU_XSCALE_80321) || \
- defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
- defined(CPU_XSCALE_80219)
+#elif defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425)
#define cpu_idcache_wbinv_all xscale_cache_purgeID
extern void xscale_cache_purgeID(void);
#elif defined(CPU_XSCALE_81342)
@@ -127,7 +125,6 @@ static int arm_dcache_l2_assoc;
static int arm_dcache_l2_linesize;
-int block_userspace_access = 0;
extern int arm9_dcache_sets_inc;
extern int arm9_dcache_sets_max;
extern int arm9_dcache_index_max;
@@ -248,7 +245,7 @@ _startC(void)
#ifndef KZIP
#ifdef CPU_ARM9
/* So that idcache_wbinv works; */
- if ((cpufunc_id() & 0x0000f000) == 0x00009000)
+ if ((cpu_ident() & 0x0000f000) == 0x00009000)
arm9_setup();
#endif
#endif
@@ -266,7 +263,7 @@ get_cachetype_cp15()
__asm __volatile("mrc p15, 0, %0, c0, c0, 1"
: "=r" (ctype));
- cpuid = cpufunc_id();
+ cpuid = cpu_ident();
/*
* ...and thus spake the ARM ARM:
*
@@ -683,7 +680,7 @@ __start(void)
#ifdef CPU_ARM9
/* So that idcache_wbinv works; */
- if ((cpufunc_id() & 0x0000f000) == 0x00009000)
+ if ((cpu_ident() & 0x0000f000) == 0x00009000)
arm9_setup();
#endif
setup_pagetables(pt_addr, (vm_paddr_t)curaddr,
diff --git a/sys/arm/arm/fiq.c b/sys/arm/arm/fiq.c
index 94231dea22c8..f475a303d3c4 100644
--- a/sys/arm/arm/fiq.c
+++ b/sys/arm/arm/fiq.c
@@ -81,8 +81,8 @@ fiq_installhandler(void *func, size_t size)
#if !defined(__ARM_FIQ_INDIRECT)
vector_page_setprot(VM_PROT_READ);
- cpu_icache_sync_range((vm_offset_t) fiqvector, size);
#endif
+ icache_sync((vm_offset_t) fiqvector, size);
}
/*
diff --git a/sys/arm/arm/fusu.S b/sys/arm/arm/fusu.S
index 54d263c7984a..ba50e67f8656 100644
--- a/sys/arm/arm/fusu.S
+++ b/sys/arm/arm/fusu.S
@@ -183,51 +183,10 @@ END(fusword)
*/
ENTRY(fuswintr)
- ldr r3, =(VM_MAXUSER_ADDRESS-1)
- cmp r0, r3
- mvncs r0, #0
- RETc(cs)
-
- ldr r2, Lblock_userspace_access
- ldr r2, [r2]
- teq r2, #0
- mvnne r0, #0x00000000
- RETne
-
- GET_PCB(r2)
- ldr r2, [r2]
-
-#ifdef DIAGNOSTIC
- teq r2, #0x00000000
- beq .Lfusupcbfault
-#endif
-
- adr r1, _C_LABEL(fusubailout)
- str r1, [r2, #PCB_ONFAULT]
-
- ldrbt r3, [r0], #1
- ldrbt ip, [r0]
-#ifdef __ARMEB__
- orr r0, ip, r3, asl #8
-#else
- orr r0, r3, ip, asl #8
-#endif
-
- mov r1, #0x00000000
- str r1, [r2, #PCB_ONFAULT]
+ mov r0, #-1
RET
END(fuswintr)
-Lblock_userspace_access:
- .word _C_LABEL(block_userspace_access)
-
- .data
- .align 2
- .global _C_LABEL(block_userspace_access)
-_C_LABEL(block_userspace_access):
- .word 0
- .text
-
/*
* fubyte(caddr_t uaddr);
* Fetch a byte from the user's address space.
@@ -268,20 +227,6 @@ END(fubyte)
mvn r0, #0x00000000
RET
-/*
- * Handle faults from [fs]u*(). Clean up and return -1. This differs from
- * fusufault() in that trap() will recognise it and return immediately rather
- * than trying to page fault.
- */
-
-/* label must be global as fault.c references it */
- .global _C_LABEL(fusubailout)
-_C_LABEL(fusubailout):
- mov r0, #0x00000000
- str r0, [r2, #PCB_ONFAULT]
- mvn r0, #0x00000000
- RET
-
#ifdef DIAGNOSTIC
/*
* Handle earlier faults from [fs]u*(), due to no pcb
@@ -335,39 +280,7 @@ END(suword)
*/
ENTRY(suswintr)
- ldr r3, =(VM_MAXUSER_ADDRESS-1)
- cmp r0, r3
- mvncs r0, #0
- RETc(cs)
-
- ldr r2, Lblock_userspace_access
- ldr r2, [r2]
- teq r2, #0
- mvnne r0, #0x00000000
- RETne
-
- GET_PCB(r2)
- ldr r2, [r2]
-
-#ifdef DIAGNOSTIC
- teq r2, #0x00000000
- beq .Lfusupcbfault
-#endif
-
- adr r3, _C_LABEL(fusubailout)
- str r3, [r2, #PCB_ONFAULT]
-
-#ifdef __ARMEB__
- mov ip, r1, lsr #8
- strbt ip, [r0], #1
-#else
- strbt r1, [r0], #1
- mov r1, r1, lsr #8
-#endif
- strbt r1, [r0]
-
- mov r0, #0x00000000
- str r0, [r2, #PCB_ONFAULT]
+ mov r0, #-1
RET
END(suswintr)
diff --git a/sys/arm/arm/genassym.c b/sys/arm/arm/genassym.c
index 659c47153fd6..41497714619f 100644
--- a/sys/arm/arm/genassym.c
+++ b/sys/arm/arm/genassym.c
@@ -45,11 +45,9 @@ __FBSDID("$FreeBSD$");
#include <machine/frame.h>
#include <machine/pcb.h>
#include <machine/cpu.h>
-#include <machine/cpu-v6.h>
#include <machine/proc.h>
#include <machine/cpufunc.h>
#include <machine/cpuinfo.h>
-#include <machine/pte.h>
#include <machine/intr.h>
#include <machine/sysarch.h>
@@ -60,17 +58,15 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip_var.h>
ASSYM(KERNBASE, KERNBASE);
-ASSYM(PCB_NOALIGNFLT, PCB_NOALIGNFLT);
-#ifdef ARM_NEW_PMAP
+#if __ARM_ARCH >= 6
ASSYM(CPU_ASID_KERNEL,CPU_ASID_KERNEL);
#endif
ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
-#ifndef ARM_NEW_PMAP
+#if __ARM_ARCH < 6
ASSYM(PCB_DACR, offsetof(struct pcb, pcb_dacr));
#endif
-ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
ASSYM(PCB_PAGEDIR, offsetof(struct pcb, pcb_pagedir));
-#ifndef ARM_NEW_PMAP
+#if __ARM_ARCH < 6
ASSYM(PCB_L1VEC, offsetof(struct pcb, pcb_l1vec));
ASSYM(PCB_PL1VEC, offsetof(struct pcb, pcb_pl1vec));
#endif
@@ -94,24 +90,15 @@ ASSYM(M_DATA, offsetof(struct mbuf, m_data));
ASSYM(M_NEXT, offsetof(struct mbuf, m_next));
ASSYM(IP_SRC, offsetof(struct ip, ip_src));
ASSYM(IP_DST, offsetof(struct ip, ip_dst));
-ASSYM(CF_SETTTB, offsetof(struct cpu_functions, cf_setttb));
-ASSYM(CF_CONTROL, offsetof(struct cpu_functions, cf_control));
ASSYM(CF_CONTEXT_SWITCH, offsetof(struct cpu_functions, cf_context_switch));
ASSYM(CF_DCACHE_WB_RANGE, offsetof(struct cpu_functions, cf_dcache_wb_range));
-ASSYM(CF_L2CACHE_WB_RANGE, offsetof(struct cpu_functions, cf_l2cache_wb_range));
ASSYM(CF_IDCACHE_WBINV_ALL, offsetof(struct cpu_functions, cf_idcache_wbinv_all));
ASSYM(CF_L2CACHE_WBINV_ALL, offsetof(struct cpu_functions, cf_l2cache_wbinv_all));
ASSYM(CF_TLB_FLUSHID_SE, offsetof(struct cpu_functions, cf_tlb_flushID_SE));
-ASSYM(CF_ICACHE_SYNC, offsetof(struct cpu_functions, cf_icache_sync_all));
-
-ASSYM(V_TRAP, offsetof(struct vmmeter, v_trap));
-ASSYM(V_SOFT, offsetof(struct vmmeter, v_soft));
-ASSYM(V_INTR, offsetof(struct vmmeter, v_intr));
ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
ASSYM(TD_PROC, offsetof(struct thread, td_proc));
-ASSYM(TD_FRAME, offsetof(struct thread, td_frame));
ASSYM(TD_MD, offsetof(struct thread, td_md));
ASSYM(TD_LOCK, offsetof(struct thread, td_lock));
ASSYM(MD_TP, offsetof(struct mdthread, md_tp));
@@ -148,10 +135,6 @@ ASSYM(PMAP_INCLUDE_PTE_SYNC, 1);
#endif
ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);
ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
-ASSYM(P_TRACED, P_TRACED);
-ASSYM(P_SIGEVENT, P_SIGEVENT);
-ASSYM(P_PROFIL, P_PROFIL);
-ASSYM(TRAPFRAMESIZE, sizeof(struct trapframe));
ASSYM(MAXCOMLEN, MAXCOMLEN);
ASSYM(MAXCPU, MAXCPU);
diff --git a/sys/arm/arm/identcpu.c b/sys/arm/arm/identcpu.c
index 6c5764c297ce..2b7fec4d05dc 100644
--- a/sys/arm/arm/identcpu.c
+++ b/sys/arm/arm/identcpu.c
@@ -321,7 +321,6 @@ print_enadis(int enadis, char *s)
printf(" %s %sabled", s, (enadis == 0) ? "dis" : "en");
}
-extern int ctrl;
enum cpu_class cpu_class = CPU_CLASS_NONE;
u_int cpu_pfr(int num)
@@ -388,9 +387,10 @@ void
identify_arm_cpu(void)
{
u_int cpuid, reg, size, sets, ways;
- u_int8_t type, linesize;
+ u_int8_t type, linesize, ctrl;
int i;
+ ctrl = cpu_get_control();
cpuid = cpu_ident();
if (cpuid == 0) {
diff --git a/sys/arm/arm/locore-v6.S b/sys/arm/arm/locore-v6.S
index b66b60183c61..b93af2c4b6b5 100644
--- a/sys/arm/arm/locore-v6.S
+++ b/sys/arm/arm/locore-v6.S
@@ -30,6 +30,7 @@
#include "assym.s"
#include <sys/syscall.h>
+#include <machine/acle-compat.h>
#include <machine/asm.h>
#include <machine/asmacros.h>
#include <machine/armreg.h>
@@ -39,11 +40,6 @@
__FBSDID("$FreeBSD$");
-#ifndef ARM_NEW_PMAP
-#define PTE1_OFFSET L1_S_OFFSET
-#define PTE1_SHIFT L1_S_SHIFT
-#define PTE1_SIZE L1_S_SIZE
-#endif
#if __ARM_ARCH >= 7
#if defined(__ARM_ARCH_7VE__) || defined(__clang__)
@@ -136,9 +132,9 @@ ASENTRY_NP(_start)
bic r7, #CPU_CONTROL_DC_ENABLE
bic r7, #CPU_CONTROL_MMU_ENABLE
bic r7, #CPU_CONTROL_IC_ENABLE
- bic r7, #CPU_CONTROL_UNAL_ENABLE
bic r7, #CPU_CONTROL_BPRD_ENABLE
bic r7, #CPU_CONTROL_SW_ENABLE
+ orr r7, #CPU_CONTROL_UNAL_ENABLE
orr r7, #CPU_CONTROL_AFLT_ENABLE
orr r7, #CPU_CONTROL_VECRELOC
mcr CP15_SCTLR(r7)
@@ -287,7 +283,6 @@ ASENTRY_NP(init_mmu)
mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
mcr CP15_DACR(r0)
-#ifdef ARM_NEW_PMAP
/*
* Set TEX remap registers
* - All is set to uncacheable memory
@@ -296,7 +291,6 @@ ASENTRY_NP(init_mmu)
mcr CP15_PRRR(r0)
mov r0, #0
mcr CP15_NMRR(r0)
-#endif
mcr CP15_TLBIALL /* Flush TLB */
DSB
ISB
@@ -305,9 +299,7 @@ ASENTRY_NP(init_mmu)
mrc CP15_SCTLR(r0)
orr r0, r0, #CPU_CONTROL_MMU_ENABLE
orr r0, r0, #CPU_CONTROL_V6_EXTPAGE
-#ifdef ARM_NEW_PMAP
orr r0, r0, #CPU_CONTROL_TR_ENABLE
-#endif
orr r0, r0, #CPU_CONTROL_AF_ENABLE
mcr CP15_SCTLR(r0)
DSB
@@ -398,23 +390,11 @@ END(reinit_mmu)
* Addresses must be 1MiB aligned
*/
build_device_pagetables:
-#if defined(ARM_NEW_PMAP)
ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0
-#elif defined(SMP)
- ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW)|L1_SHARED)
-#else
- ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW))
-#endif
b 1f
build_pagetables:
/* Set the required page attributed */
-#if defined(ARM_NEW_PMAP)
ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0
-#elif defined(SMP)
- ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)|L1_SHARED)
-#else
- ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
-#endif
1:
orr r1, r4
@@ -476,9 +456,9 @@ ASENTRY_NP(mpentry)
bic r0, #CPU_CONTROL_MMU_ENABLE
bic r0, #CPU_CONTROL_DC_ENABLE
bic r0, #CPU_CONTROL_IC_ENABLE
- bic r0, #CPU_CONTROL_UNAL_ENABLE
bic r0, #CPU_CONTROL_BPRD_ENABLE
bic r0, #CPU_CONTROL_SW_ENABLE
+ orr r0, #CPU_CONTROL_UNAL_ENABLE
orr r0, #CPU_CONTROL_AFLT_ENABLE
orr r0, #CPU_CONTROL_VECRELOC
mcr CP15_SCTLR(r0)
diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index d2811a6dc071..4e7cb70c84bb 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -123,7 +123,6 @@ __FBSDID("$FreeBSD$");
#include <ddb/ddb.h>
#if __ARM_ARCH >= 6
-#include <machine/cpu-v6.h>
DB_SHOW_COMMAND(cp15, db_show_cp15)
{
@@ -199,7 +198,7 @@ static char *loader_envp;
vm_paddr_t pmap_pa;
-#ifdef ARM_NEW_PMAP
+#if __ARM_ARCH >= 6
vm_offset_t systempage;
vm_offset_t irqstack;
vm_offset_t undstack;
@@ -397,7 +396,7 @@ arm_vector_init(vm_offset_t va, int which)
}
/* Now sync the vectors. */
- cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int));
+ icache_sync(va, (ARM_NVEC * 2) * sizeof(u_int));
vector_page = va;
@@ -427,11 +426,9 @@ cpu_startup(void *dummy)
{
struct pcb *pcb = thread0.td_pcb;
const unsigned int mbyte = 1024 * 1024;
-#ifdef ARM_TP_ADDRESS
-#ifndef ARM_CACHE_LOCK_ENABLE
+#if __ARM_ARCH < 6 && !defined(ARM_CACHE_LOCK_ENABLE)
vm_page_t m;
#endif
-#endif
identify_arm_cpu();
@@ -455,12 +452,10 @@ cpu_startup(void *dummy)
vm_pager_bufferinit();
pcb->pcb_regs.sf_sp = (u_int)thread0.td_kstack +
USPACE_SVC_STACK_TOP;
- pmap_set_pcb_pagedir(pmap_kernel(), pcb);
-#ifndef ARM_NEW_PMAP
+ pmap_set_pcb_pagedir(kernel_pmap, pcb);
+#if __ARM_ARCH < 6
vector_page_setprot(VM_PROT_READ);
pmap_postinit();
-#endif
-#ifdef ARM_TP_ADDRESS
#ifdef ARM_CACHE_LOCK_ENABLE
pmap_kenter_user(ARM_TP_ADDRESS, ARM_TP_ADDRESS);
arm_lock_cache_line(ARM_TP_ADDRESS);
@@ -483,12 +478,7 @@ void
cpu_flush_dcache(void *ptr, size_t len)
{
- cpu_dcache_wb_range((uintptr_t)ptr, len);
-#ifdef ARM_L2_PIPT
- cpu_l2cache_wb_range((uintptr_t)vtophys(ptr), len);
-#else
- cpu_l2cache_wb_range((uintptr_t)ptr, len);
-#endif
+ dcache_wb_poc((vm_offset_t)ptr, (vm_paddr_t)vtophys(ptr), len);
}
/* Get current clock frequency for the given cpu id. */
@@ -1283,7 +1273,7 @@ arm_predict_branch(void *cookie, u_int insn, register_t pc, register_t *new_pc,
}
}
-#ifdef ARM_NEW_PMAP
+#if __ARM_ARCH >= 6
void
set_stackptrs(int cpu)
{
@@ -1447,7 +1437,7 @@ print_kenv(void)
debugf(" %x %s\n", (uint32_t)cp, cp);
}
-#ifndef ARM_NEW_PMAP
+#if __ARM_ARCH < 6
void *
initarm(struct arm_boot_params *abp)
{
@@ -1626,7 +1616,7 @@ initarm(struct arm_boot_params *abp)
cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) | DOMAIN_CLIENT);
pmap_pa = kernel_l1pt.pv_pa;
- setttb(kernel_l1pt.pv_pa);
+ cpu_setttb(kernel_l1pt.pv_pa);
cpu_tlb_flushID();
cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2));
@@ -1679,7 +1669,7 @@ initarm(struct arm_boot_params *abp)
/*
* We must now clean the cache again....
* Cleaning may be done by reading new data to displace any
- * dirty data in the cache. This will have happened in setttb()
+ * dirty data in the cache. This will have happened in cpu_setttb()
* but since we are boot strapping the addresses used for the read
* may have just been remapped and thus the cache could be out
* of sync. A re-clean after the switch will cure this.
@@ -1717,7 +1707,7 @@ initarm(struct arm_boot_params *abp)
return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
sizeof(struct pcb)));
}
-#else /* !ARM_NEW_PMAP */
+#else /* __ARM_ARCH < 6 */
void *
initarm(struct arm_boot_params *abp)
{
@@ -1871,7 +1861,7 @@ initarm(struct arm_boot_params *abp)
/*
* We must now clean the cache again....
* Cleaning may be done by reading new data to displace any
- * dirty data in the cache. This will have happened in setttb()
+ * dirty data in the cache. This will have happened in cpu_setttb()
* but since we are boot strapping the addresses used for the read
* may have just been remapped and thus the cache could be out
* of sync. A re-clean after the switch will cure this.
@@ -1905,7 +1895,7 @@ initarm(struct arm_boot_params *abp)
}
-#endif /* !ARM_NEW_PMAP */
+#endif /* __ARM_ARCH < 6 */
#endif /* FDT */
uint32_t (*arm_cpu_fill_vdso_timehands)(struct vdso_timehands *,
diff --git a/sys/arm/arm/mem.c b/sys/arm/arm/mem.c
index 2e4128b55196..1218ea474209 100644
--- a/sys/arm/arm/mem.c
+++ b/sys/arm/arm/mem.c
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <vm/pmap.h>
#include <vm/vm_extern.h>
+#include <machine/acle-compat.h>
#include <machine/memdev.h>
#include <machine/vmparam.h>
@@ -113,7 +114,7 @@ memrw(struct cdev *dev, struct uio *uio, int flags)
return (EINVAL);
sx_xlock(&tmppt_lock);
pmap_kenter((vm_offset_t)_tmppt, v);
-#ifdef ARM_NEW_PMAP
+#if __ARM_ARCH >= 6
pmap_tlb_flush(kernel_pmap, (vm_offset_t)_tmppt);
#endif
o = (int)uio->uio_offset & PAGE_MASK;
diff --git a/sys/arm/arm/minidump_machdep.c b/sys/arm/arm/minidump_machdep.c
index a351fb76095c..2eb4bfd01f86 100644
--- a/sys/arm/arm/minidump_machdep.c
+++ b/sys/arm/arm/minidump_machdep.c
@@ -45,11 +45,11 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/atomic.h>
+#include <machine/cpu.h>
#include <machine/elf.h>
#include <machine/md_var.h>
-#include <machine/vmparam.h>
#include <machine/minidump.h>
-#include <machine/cpufunc.h>
+#include <machine/vmparam.h>
CTASSERT(sizeof(struct kerneldumpheader) == 512);
@@ -203,8 +203,7 @@ minidumpsys(struct dumperinfo *di)
* by time we get to here, all that remains is to flush the L1 for the
* current CPU, then the L2.
*/
- cpu_idcache_wbinv_all();
- cpu_l2cache_wbinv_all();
+ dcache_wbinv_poc_all();
counter = 0;
/* Walk page table pages, set bits in vm_page_dump */
diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c
index 60bb59895a44..8643860792d5 100644
--- a/sys/arm/arm/mp_machdep.c
+++ b/sys/arm/arm/mp_machdep.c
@@ -43,13 +43,14 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_kern.h>
#include <vm/pmap.h>
+#include <machine/acle-compat.h>
#include <machine/armreg.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
+#include <machine/debug_monitor.h>
#include <machine/smp.h>
#include <machine/pcb.h>
#include <machine/pmap.h>
-#include <machine/pte.h>
#include <machine/physmem.h>
#include <machine/intr.h>
#include <machine/vmparam.h>
@@ -122,9 +123,7 @@ cpu_mp_start(void)
dpcpu[i] = (void *)kmem_malloc(kernel_arena, DPCPU_SIZE,
M_WAITOK | M_ZERO);
- cpu_idcache_wbinv_all();
- cpu_l2cache_wbinv_all();
- cpu_idcache_wbinv_all();
+ dcache_wbinv_poc_all();
/* Initialize boot code and start up processors */
platform_mp_start_ap();
@@ -154,7 +153,6 @@ init_secondary(int cpu)
#ifndef ARM_INTRNG
int start = 0, end = 0;
#endif
-#ifdef ARM_NEW_PMAP
uint32_t actlr_mask, actlr_set;
pmap_set_tex();
@@ -166,11 +164,6 @@ init_secondary(int cpu)
set_stackptrs(cpu);
enable_interrupts(PSR_A);
-#else /* ARM_NEW_PMAP */
- cpu_setup();
- setttb(pmap_pa);
- cpu_tlb_flushID();
-#endif /* ARM_NEW_PMAP */
pc = &__pcpu[cpu];
/*
@@ -182,10 +175,6 @@ init_secondary(int cpu)
pcpu_init(pc, cpu, sizeof(struct pcpu));
dpcpu_init(dpcpu[cpu - 1], cpu);
-#ifndef ARM_NEW_PMAP
- /* Provide stack pointers for other processor modes. */
- set_stackptrs(cpu);
-#endif
/* Signal our startup to BSP */
atomic_add_rel_32(&mp_naps, 1);
@@ -292,7 +281,7 @@ ipi_stop(void *dummy __unused)
* stop will do the l2 cache flush after all other cores
* have done their l1 flushes and stopped.
*/
- cpu_idcache_wbinv_all();
+ dcache_wbinv_poc_all();
/* Indicate we are stopped */
CPU_SET_ATOMIC(cpu, &stopped_cpus);
@@ -303,6 +292,9 @@ ipi_stop(void *dummy __unused)
CPU_CLR_ATOMIC(cpu, &started_cpus);
CPU_CLR_ATOMIC(cpu, &stopped_cpus);
+#ifdef DDB
+ dbg_resume_dbreg();
+#endif
CTR0(KTR_SMP, "IPI_STOP (restart)");
}
@@ -346,13 +338,6 @@ ipi_hardclock(void *arg)
critical_exit();
}
-static void
-ipi_tlb(void *dummy __unused)
-{
-
- CTR1(KTR_SMP, "%s: IPI_TLB", __func__);
- cpufuncs.cf_tlb_flushID();
-}
#else
static int
ipi_handler(void *arg)
@@ -394,7 +379,7 @@ ipi_handler(void *arg)
* stop will do the l2 cache flush after all other cores
* have done their l1 flushes and stopped.
*/
- cpu_idcache_wbinv_all();
+ dcache_wbinv_poc_all();
/* Indicate we are stopped */
CPU_SET_ATOMIC(cpu, &stopped_cpus);
@@ -405,6 +390,9 @@ ipi_handler(void *arg)
CPU_CLR_ATOMIC(cpu, &started_cpus);
CPU_CLR_ATOMIC(cpu, &stopped_cpus);
+#ifdef DDB
+ dbg_resume_dbreg();
+#endif
CTR0(KTR_SMP, "IPI_STOP (restart)");
break;
case IPI_PREEMPT:
@@ -415,10 +403,6 @@ ipi_handler(void *arg)
CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__);
hardclockintr();
break;
- case IPI_TLB:
- CTR1(KTR_SMP, "%s: IPI_TLB", __func__);
- cpufuncs.cf_tlb_flushID();
- break;
default:
panic("Unknown IPI 0x%0x on cpu %d", ipi, curcpu);
}
@@ -448,7 +432,6 @@ release_aps(void *dummy __unused)
intr_ipi_set_handler(IPI_STOP, "stop", ipi_stop, NULL, 0);
intr_ipi_set_handler(IPI_PREEMPT, "preempt", ipi_preempt, NULL, 0);
intr_ipi_set_handler(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL, 0);
- intr_ipi_set_handler(IPI_TLB, "tlb", ipi_tlb, NULL, 0);
#else
#ifdef IPI_IRQ_START
@@ -540,10 +523,3 @@ ipi_selected(cpuset_t cpus, u_int ipi)
platform_ipi_send(cpus, ipi);
}
-void
-tlb_broadcast(int ipi)
-{
-
- if (smp_started)
- ipi_all_but_self(ipi);
-}
diff --git a/sys/arm/arm/pmap-v6-new.c b/sys/arm/arm/pmap-v6-new.c
deleted file mode 100644
index 2996898a4510..000000000000
--- a/sys/arm/arm/pmap-v6-new.c
+++ /dev/null
@@ -1,6634 +0,0 @@
-/*-
- * Copyright (c) 1991 Regents of the University of California.
- * Copyright (c) 1994 John S. Dyson
- * Copyright (c) 1994 David Greenman
- * Copyright (c) 2005-2010 Alan L. Cox <alc@cs.rice.edu>
- * Copyright (c) 2014 Svatopluk Kraus <onwahe@gmail.com>
- * Copyright (c) 2014 Michal Meloun <meloun@miracle.cz>
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * the Systems Programming Group of the University of Utah Computer
- * Science Department and William Jolitz of UUNET Technologies Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the 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: @(#)pmap.c 7.7 (Berkeley) 5/12/91
- */
-/*-
- * Copyright (c) 2003 Networks Associates Technology, Inc.
- * All rights reserved.
- *
- * This software was developed for the FreeBSD Project by Jake Burkholder,
- * Safeport Network Services, and Network Associates Laboratories, the
- * Security Research Division of Network Associates, Inc. under
- * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
- * CHATS research program.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * Manages physical address maps.
- *
- * Since the information managed by this module is
- * also stored by the logical address mapping module,
- * this module may throw away valid virtual-to-physical
- * mappings at almost any time. However, invalidations
- * of virtual-to-physical mappings must be done as
- * requested.
- *
- * In order to cope with hardware architectures which
- * make virtual-to-physical map invalidates expensive,
- * this module may delay invalidate or reduced protection
- * operations until such time as they are actually
- * necessary. This module is given full information as
- * to which processors are currently using which maps,
- * and to when physical maps must be made correct.
- */
-
-#include "opt_vm.h"
-#include "opt_pmap.h"
-#include "opt_ddb.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/ktr.h>
-#include <sys/lock.h>
-#include <sys/proc.h>
-#include <sys/rwlock.h>
-#include <sys/malloc.h>
-#include <sys/vmmeter.h>
-#include <sys/malloc.h>
-#include <sys/mman.h>
-#include <sys/sf_buf.h>
-#include <sys/smp.h>
-#include <sys/sched.h>
-#include <sys/sysctl.h>
-#ifdef SMP
-#include <sys/smp.h>
-#else
-#include <sys/cpuset.h>
-#endif
-
-#ifdef DDB
-#include <ddb/ddb.h>
-#endif
-
-#include <machine/physmem.h>
-#include <machine/vmparam.h>
-
-#include <vm/vm.h>
-#include <vm/uma.h>
-#include <vm/pmap.h>
-#include <vm/vm_param.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_object.h>
-#include <vm/vm_map.h>
-#include <vm/vm_page.h>
-#include <vm/vm_pageout.h>
-#include <vm/vm_phys.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_reserv.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-
-#include <machine/md_var.h>
-#include <machine/pmap_var.h>
-#include <machine/cpu.h>
-#include <machine/cpu-v6.h>
-#include <machine/pcb.h>
-#include <machine/sf_buf.h>
-#ifdef SMP
-#include <machine/smp.h>
-#endif
-
-#ifndef PMAP_SHPGPERPROC
-#define PMAP_SHPGPERPROC 200
-#endif
-
-#ifndef DIAGNOSTIC
-#define PMAP_INLINE __inline
-#else
-#define PMAP_INLINE
-#endif
-
-#ifdef PMAP_DEBUG
-static void pmap_zero_page_check(vm_page_t m);
-void pmap_debug(int level);
-int pmap_pid_dump(int pid);
-
-#define PDEBUG(_lev_,_stat_) \
- if (pmap_debug_level >= (_lev_)) \
- ((_stat_))
-#define dprintf printf
-int pmap_debug_level = 1;
-#else /* PMAP_DEBUG */
-#define PDEBUG(_lev_,_stat_) /* Nothing */
-#define dprintf(x, arg...)
-#endif /* PMAP_DEBUG */
-
-/*
- * Level 2 page tables map definion ('max' is excluded).
- */
-
-#define PT2V_MIN_ADDRESS ((vm_offset_t)PT2MAP)
-#define PT2V_MAX_ADDRESS ((vm_offset_t)PT2MAP + PT2MAP_SIZE)
-
-#define UPT2V_MIN_ADDRESS ((vm_offset_t)PT2MAP)
-#define UPT2V_MAX_ADDRESS \
- ((vm_offset_t)(PT2MAP + (KERNBASE >> PT2MAP_SHIFT)))
-
-/*
- * Promotion to a 1MB (PTE1) page mapping requires that the corresponding
- * 4KB (PTE2) page mappings have identical settings for the following fields:
- */
-#define PTE2_PROMOTE (PTE2_V | PTE2_A | PTE2_NM | PTE2_S | PTE2_NG | \
- PTE2_NX | PTE2_RO | PTE2_U | PTE2_W | \
- PTE2_ATTR_MASK)
-
-#define PTE1_PROMOTE (PTE1_V | PTE1_A | PTE1_NM | PTE1_S | PTE1_NG | \
- PTE1_NX | PTE1_RO | PTE1_U | PTE1_W | \
- PTE1_ATTR_MASK)
-
-#define ATTR_TO_L1(l2_attr) ((((l2_attr) & L2_TEX0) ? L1_S_TEX0 : 0) | \
- (((l2_attr) & L2_C) ? L1_S_C : 0) | \
- (((l2_attr) & L2_B) ? L1_S_B : 0) | \
- (((l2_attr) & PTE2_A) ? PTE1_A : 0) | \
- (((l2_attr) & PTE2_NM) ? PTE1_NM : 0) | \
- (((l2_attr) & PTE2_S) ? PTE1_S : 0) | \
- (((l2_attr) & PTE2_NG) ? PTE1_NG : 0) | \
- (((l2_attr) & PTE2_NX) ? PTE1_NX : 0) | \
- (((l2_attr) & PTE2_RO) ? PTE1_RO : 0) | \
- (((l2_attr) & PTE2_U) ? PTE1_U : 0) | \
- (((l2_attr) & PTE2_W) ? PTE1_W : 0))
-
-#define ATTR_TO_L2(l1_attr) ((((l1_attr) & L1_S_TEX0) ? L2_TEX0 : 0) | \
- (((l1_attr) & L1_S_C) ? L2_C : 0) | \
- (((l1_attr) & L1_S_B) ? L2_B : 0) | \
- (((l1_attr) & PTE1_A) ? PTE2_A : 0) | \
- (((l1_attr) & PTE1_NM) ? PTE2_NM : 0) | \
- (((l1_attr) & PTE1_S) ? PTE2_S : 0) | \
- (((l1_attr) & PTE1_NG) ? PTE2_NG : 0) | \
- (((l1_attr) & PTE1_NX) ? PTE2_NX : 0) | \
- (((l1_attr) & PTE1_RO) ? PTE2_RO : 0) | \
- (((l1_attr) & PTE1_U) ? PTE2_U : 0) | \
- (((l1_attr) & PTE1_W) ? PTE2_W : 0))
-
-/*
- * PTE2 descriptors creation macros.
- */
-#define PTE2_KPT(pa) PTE2_KERN(pa, PTE2_AP_KRW, pt_memattr)
-#define PTE2_KPT_NG(pa) PTE2_KERN_NG(pa, PTE2_AP_KRW, pt_memattr)
-
-#define PTE2_KRW(pa) PTE2_KERN(pa, PTE2_AP_KRW, PTE2_ATTR_NORMAL)
-#define PTE2_KRO(pa) PTE2_KERN(pa, PTE2_AP_KR, PTE2_ATTR_NORMAL)
-
-#define PV_STATS
-#ifdef PV_STATS
-#define PV_STAT(x) do { x ; } while (0)
-#else
-#define PV_STAT(x) do { } while (0)
-#endif
-
-/*
- * The boot_pt1 is used temporary in very early boot stage as L1 page table.
- * We can init many things with no memory allocation thanks to its static
- * allocation and this brings two main advantages:
- * (1) other cores can be started very simply,
- * (2) various boot loaders can be supported as its arguments can be processed
- * in virtual address space and can be moved to safe location before
- * first allocation happened.
- * Only disadvantage is that boot_pt1 is used only in very early boot stage.
- * However, the table is uninitialized and so lays in bss. Therefore kernel
- * image size is not influenced.
- *
- * QQQ: In the future, maybe, boot_pt1 can be used for soft reset and
- * CPU suspend/resume game.
- */
-extern pt1_entry_t boot_pt1[];
-
-vm_paddr_t base_pt1;
-pt1_entry_t *kern_pt1;
-pt2_entry_t *kern_pt2tab;
-pt2_entry_t *PT2MAP;
-
-static uint32_t ttb_flags;
-static vm_memattr_t pt_memattr;
-ttb_entry_t pmap_kern_ttb;
-
-/* XXX use converion function*/
-#define PTE2_ATTR_NORMAL VM_MEMATTR_DEFAULT
-#define PTE1_ATTR_NORMAL ATTR_TO_L1(PTE2_ATTR_NORMAL)
-
-struct pmap kernel_pmap_store;
-LIST_HEAD(pmaplist, pmap);
-static struct pmaplist allpmaps;
-static struct mtx allpmaps_lock;
-
-vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */
-vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */
-
-static vm_offset_t kernel_vm_end_new;
-vm_offset_t kernel_vm_end = KERNBASE + NKPT2PG * NPT2_IN_PG * PTE1_SIZE;
-vm_offset_t vm_max_kernel_address;
-vm_paddr_t kernel_l1pa;
-
-static struct rwlock __aligned(CACHE_LINE_SIZE) pvh_global_lock;
-
-/*
- * Data for the pv entry allocation mechanism
- */
-static TAILQ_HEAD(pch, pv_chunk) pv_chunks = TAILQ_HEAD_INITIALIZER(pv_chunks);
-static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0;
-static struct md_page *pv_table; /* XXX: Is it used only the list in md_page? */
-static int shpgperproc = PMAP_SHPGPERPROC;
-
-struct pv_chunk *pv_chunkbase; /* KVA block for pv_chunks */
-int pv_maxchunks; /* How many chunks we have KVA for */
-vm_offset_t pv_vafree; /* freelist stored in the PTE */
-
-vm_paddr_t first_managed_pa;
-#define pa_to_pvh(pa) (&pv_table[pte1_index(pa - first_managed_pa)])
-
-/*
- * All those kernel PT submaps that BSD is so fond of
- */
-struct sysmaps {
- struct mtx lock;
- pt2_entry_t *CMAP1;
- pt2_entry_t *CMAP2;
- pt2_entry_t *CMAP3;
- caddr_t CADDR1;
- caddr_t CADDR2;
- caddr_t CADDR3;
-};
-static struct sysmaps sysmaps_pcpu[MAXCPU];
-static pt2_entry_t *CMAP3;
-static caddr_t CADDR3;
-caddr_t _tmppt = 0;
-
-struct msgbuf *msgbufp = 0; /* XXX move it to machdep.c */
-
-/*
- * Crashdump maps.
- */
-static caddr_t crashdumpmap;
-
-static pt2_entry_t *PMAP1 = 0, *PMAP2;
-static pt2_entry_t *PADDR1 = 0, *PADDR2;
-#ifdef DDB
-static pt2_entry_t *PMAP3;
-static pt2_entry_t *PADDR3;
-static int PMAP3cpu __unused; /* for SMP only */
-#endif
-#ifdef SMP
-static int PMAP1cpu;
-static int PMAP1changedcpu;
-SYSCTL_INT(_debug, OID_AUTO, PMAP1changedcpu, CTLFLAG_RD,
- &PMAP1changedcpu, 0,
- "Number of times pmap_pte2_quick changed CPU with same PMAP1");
-#endif
-static int PMAP1changed;
-SYSCTL_INT(_debug, OID_AUTO, PMAP1changed, CTLFLAG_RD,
- &PMAP1changed, 0,
- "Number of times pmap_pte2_quick changed PMAP1");
-static int PMAP1unchanged;
-SYSCTL_INT(_debug, OID_AUTO, PMAP1unchanged, CTLFLAG_RD,
- &PMAP1unchanged, 0,
- "Number of times pmap_pte2_quick didn't change PMAP1");
-static struct mtx PMAP2mutex;
-
-static __inline void pt2_wirecount_init(vm_page_t m);
-static boolean_t pmap_demote_pte1(pmap_t pmap, pt1_entry_t *pte1p,
- vm_offset_t va);
-void cache_icache_sync_fresh(vm_offset_t va, vm_paddr_t pa, vm_size_t size);
-
-/*
- * Function to set the debug level of the pmap code.
- */
-#ifdef PMAP_DEBUG
-void
-pmap_debug(int level)
-{
-
- pmap_debug_level = level;
- dprintf("pmap_debug: level=%d\n", pmap_debug_level);
-}
-#endif /* PMAP_DEBUG */
-
-/*
- * This table must corespond with memory attribute configuration in vm.h.
- * First entry is used for normal system mapping.
- *
- * Device memory is always marked as shared.
- * Normal memory is shared only in SMP .
- * Not outer shareable bits are not used yet.
- * Class 6 cannot be used on ARM11.
- */
-#define TEXDEF_TYPE_SHIFT 0
-#define TEXDEF_TYPE_MASK 0x3
-#define TEXDEF_INNER_SHIFT 2
-#define TEXDEF_INNER_MASK 0x3
-#define TEXDEF_OUTER_SHIFT 4
-#define TEXDEF_OUTER_MASK 0x3
-#define TEXDEF_NOS_SHIFT 6
-#define TEXDEF_NOS_MASK 0x1
-
-#define TEX(t, i, o, s) \
- ((t) << TEXDEF_TYPE_SHIFT) | \
- ((i) << TEXDEF_INNER_SHIFT) | \
- ((o) << TEXDEF_OUTER_SHIFT | \
- ((s) << TEXDEF_NOS_SHIFT))
-
-static uint32_t tex_class[8] = {
-/* type inner cache outer cache */
- TEX(PRRR_MEM, NMRR_WB_WA, NMRR_WB_WA, 0), /* 0 - ATTR_WB_WA */
- TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 1 - ATTR_NOCACHE */
- TEX(PRRR_DEV, NMRR_NC, NMRR_NC, 0), /* 2 - ATTR_DEVICE */
- TEX(PRRR_SO, NMRR_NC, NMRR_NC, 0), /* 3 - ATTR_SO */
- TEX(PRRR_MEM, NMRR_WT, NMRR_WT, 0), /* 4 - ATTR_WT */
- TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 5 - NOT USED YET */
- TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 6 - NOT USED YET */
- TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 7 - NOT USED YET */
-};
-#undef TEX
-
-/*
- * Convert TEX definition entry to TTB flags.
- */
-static uint32_t
-encode_ttb_flags(int idx)
-{
- uint32_t inner, outer, nos, reg;
-
- inner = (tex_class[idx] >> TEXDEF_INNER_SHIFT) &
- TEXDEF_INNER_MASK;
- outer = (tex_class[idx] >> TEXDEF_OUTER_SHIFT) &
- TEXDEF_OUTER_MASK;
- nos = (tex_class[idx] >> TEXDEF_NOS_SHIFT) &
- TEXDEF_NOS_MASK;
-
- reg = nos << 5;
- reg |= outer << 3;
- if (cpuinfo.coherent_walk)
- reg |= (inner & 0x1) << 6;
- reg |= (inner & 0x2) >> 1;
-#ifdef SMP
- reg |= 1 << 1;
-#endif
- return reg;
-}
-
-/*
- * Set TEX remapping registers in current CPU.
- */
-void
-pmap_set_tex(void)
-{
- uint32_t prrr, nmrr;
- uint32_t type, inner, outer, nos;
- int i;
-
-#ifdef PMAP_PTE_NOCACHE
- /* XXX fixme */
- if (cpuinfo.coherent_walk) {
- pt_memattr = VM_MEMATTR_WB_WA;
- ttb_flags = encode_ttb_flags(0);
- }
- else {
- pt_memattr = VM_MEMATTR_NOCACHE;
- ttb_flags = encode_ttb_flags(1);
- }
-#else
- pt_memattr = VM_MEMATTR_WB_WA;
- ttb_flags = encode_ttb_flags(0);
-#endif
-
- prrr = 0;
- nmrr = 0;
-
- /* Build remapping register from TEX classes. */
- for (i = 0; i < 8; i++) {
- type = (tex_class[i] >> TEXDEF_TYPE_SHIFT) &
- TEXDEF_TYPE_MASK;
- inner = (tex_class[i] >> TEXDEF_INNER_SHIFT) &
- TEXDEF_INNER_MASK;
- outer = (tex_class[i] >> TEXDEF_OUTER_SHIFT) &
- TEXDEF_OUTER_MASK;
- nos = (tex_class[i] >> TEXDEF_NOS_SHIFT) &
- TEXDEF_NOS_MASK;
-
- prrr |= type << (i * 2);
- prrr |= nos << (i + 24);
- nmrr |= inner << (i * 2);
- nmrr |= outer << (i * 2 + 16);
- }
- /* Add shareable bits for device memory. */
- prrr |= PRRR_DS0 | PRRR_DS1;
-
- /* Add shareable bits for normal memory in SMP case. */
-#ifdef SMP
- prrr |= PRRR_NS1;
-#endif
- cp15_prrr_set(prrr);
- cp15_nmrr_set(nmrr);
-
- /* Caches are disabled, so full TLB flush should be enough. */
- tlb_flush_all_local();
-}
-
-/*
- * KERNBASE must be multiple of NPT2_IN_PG * PTE1_SIZE. In other words,
- * KERNBASE is mapped by first L2 page table in L2 page table page. It
- * meets same constrain due to PT2MAP being placed just under KERNBASE.
- */
-CTASSERT((KERNBASE & (NPT2_IN_PG * PTE1_SIZE - 1)) == 0);
-CTASSERT((KERNBASE - VM_MAXUSER_ADDRESS) >= PT2MAP_SIZE);
-
-/*
- * In crazy dreams, PAGE_SIZE could be a multiple of PTE2_SIZE in general.
- * For now, anyhow, the following check must be fulfilled.
- */
-CTASSERT(PAGE_SIZE == PTE2_SIZE);
-/*
- * We don't want to mess up MI code with all MMU and PMAP definitions,
- * so some things, which depend on other ones, are defined independently.
- * Now, it is time to check that we don't screw up something.
- */
-CTASSERT(PDRSHIFT == PTE1_SHIFT);
-/*
- * Check L1 and L2 page table entries definitions consistency.
- */
-CTASSERT(NB_IN_PT1 == (sizeof(pt1_entry_t) * NPTE1_IN_PT1));
-CTASSERT(NB_IN_PT2 == (sizeof(pt2_entry_t) * NPTE2_IN_PT2));
-/*
- * Check L2 page tables page consistency.
- */
-CTASSERT(PAGE_SIZE == (NPT2_IN_PG * NB_IN_PT2));
-CTASSERT((1 << PT2PG_SHIFT) == NPT2_IN_PG);
-/*
- * Check PT2TAB consistency.
- * PT2TAB_ENTRIES is defined as a division of NPTE1_IN_PT1 by NPT2_IN_PG.
- * This should be done without remainder.
- */
-CTASSERT(NPTE1_IN_PT1 == (PT2TAB_ENTRIES * NPT2_IN_PG));
-
-/*
- * A PT2MAP magic.
- *
- * All level 2 page tables (PT2s) are mapped continuously and accordingly
- * into PT2MAP address space. As PT2 size is less than PAGE_SIZE, this can
- * be done only if PAGE_SIZE is a multiple of PT2 size. All PT2s in one page
- * must be used together, but not necessary at once. The first PT2 in a page
- * must map things on correctly aligned address and the others must follow
- * in right order.
- */
-#define NB_IN_PT2TAB (PT2TAB_ENTRIES * sizeof(pt2_entry_t))
-#define NPT2_IN_PT2TAB (NB_IN_PT2TAB / NB_IN_PT2)
-#define NPG_IN_PT2TAB (NB_IN_PT2TAB / PAGE_SIZE)
-
-/*
- * Check PT2TAB consistency.
- * NPT2_IN_PT2TAB is defined as a division of NB_IN_PT2TAB by NB_IN_PT2.
- * NPG_IN_PT2TAB is defined as a division of NB_IN_PT2TAB by PAGE_SIZE.
- * The both should be done without remainder.
- */
-CTASSERT(NB_IN_PT2TAB == (NPT2_IN_PT2TAB * NB_IN_PT2));
-CTASSERT(NB_IN_PT2TAB == (NPG_IN_PT2TAB * PAGE_SIZE));
-/*
- * The implementation was made general, however, with the assumption
- * bellow in mind. In case of another value of NPG_IN_PT2TAB,
- * the code should be once more rechecked.
- */
-CTASSERT(NPG_IN_PT2TAB == 1);
-
-/*
- * Get offset of PT2 in a page
- * associated with given PT1 index.
- */
-static __inline u_int
-page_pt2off(u_int pt1_idx)
-{
-
- return ((pt1_idx & PT2PG_MASK) * NB_IN_PT2);
-}
-
-/*
- * Get physical address of PT2
- * associated with given PT2s page and PT1 index.
- */
-static __inline vm_paddr_t
-page_pt2pa(vm_paddr_t pgpa, u_int pt1_idx)
-{
-
- return (pgpa + page_pt2off(pt1_idx));
-}
-
-/*
- * Get first entry of PT2
- * associated with given PT2s page and PT1 index.
- */
-static __inline pt2_entry_t *
-page_pt2(vm_offset_t pgva, u_int pt1_idx)
-{
-
- return ((pt2_entry_t *)(pgva + page_pt2off(pt1_idx)));
-}
-
-/*
- * Get virtual address of PT2s page (mapped in PT2MAP)
- * which holds PT2 which holds entry which maps given virtual address.
- */
-static __inline vm_offset_t
-pt2map_pt2pg(vm_offset_t va)
-{
-
- va &= ~(NPT2_IN_PG * PTE1_SIZE - 1);
- return ((vm_offset_t)pt2map_entry(va));
-}
-
-/*****************************************************************************
- *
- * THREE pmap initialization milestones exist:
- *
- * locore.S
- * -> fundamental init (including MMU) in ASM
- *
- * initarm()
- * -> fundamental init continues in C
- * -> first available physical address is known
- *
- * pmap_bootstrap_prepare() -> FIRST PMAP MILESTONE (first epoch begins)
- * -> basic (safe) interface for physical address allocation is made
- * -> basic (safe) interface for virtual mapping is made
- * -> limited not SMP coherent work is possible
- *
- * -> more fundamental init continues in C
- * -> locks and some more things are available
- * -> all fundamental allocations and mappings are done
- *
- * pmap_bootstrap() -> SECOND PMAP MILESTONE (second epoch begins)
- * -> phys_avail[] and virtual_avail is set
- * -> control is passed to vm subsystem
- * -> physical and virtual address allocation are off limit
- * -> low level mapping functions, some SMP coherent,
- * are available, which cannot be used before vm subsystem
- * is being inited
- *
- * mi_startup()
- * -> vm subsystem is being inited
- *
- * pmap_init() -> THIRD PMAP MILESTONE (third epoch begins)
- * -> pmap is fully inited
- *
- *****************************************************************************/
-
-/*****************************************************************************
- *
- * PMAP first stage initialization and utility functions
- * for pre-bootstrap epoch.
- *
- * After pmap_bootstrap_prepare() is called, the following functions
- * can be used:
- *
- * (1) strictly only for this stage functions for physical page allocations,
- * virtual space allocations, and mappings:
- *
- * vm_paddr_t pmap_preboot_get_pages(u_int num);
- * void pmap_preboot_map_pages(vm_paddr_t pa, vm_offset_t va, u_int num);
- * vm_offset_t pmap_preboot_reserve_pages(u_int num);
- * vm_offset_t pmap_preboot_get_vpages(u_int num);
- * void pmap_preboot_map_attr(vm_paddr_t pa, vm_offset_t va, vm_size_t size,
- * int prot, int attr);
- *
- * (2) for all stages:
- *
- * vm_paddr_t pmap_kextract(vm_offset_t va);
- *
- * NOTE: This is not SMP coherent stage.
- *
- *****************************************************************************/
-
-#define KERNEL_P2V(pa) \
- ((vm_offset_t)((pa) - arm_physmem_kernaddr + KERNVIRTADDR))
-#define KERNEL_V2P(va) \
- ((vm_paddr_t)((va) - KERNVIRTADDR + arm_physmem_kernaddr))
-
-static vm_paddr_t last_paddr;
-
-/*
- * Pre-bootstrap epoch page allocator.
- */
-vm_paddr_t
-pmap_preboot_get_pages(u_int num)
-{
- vm_paddr_t ret;
-
- ret = last_paddr;
- last_paddr += num * PAGE_SIZE;
-
- return (ret);
-}
-
-/*
- * The fundamental initalization of PMAP stuff.
- *
- * Some things already happened in locore.S and some things could happen
- * before pmap_bootstrap_prepare() is called, so let's recall what is done:
- * 1. Caches are disabled.
- * 2. We are running on virtual addresses already with 'boot_pt1'
- * as L1 page table.
- * 3. So far, all virtual addresses can be converted to physical ones and
- * vice versa by the following macros:
- * KERNEL_P2V(pa) .... physical to virtual ones,
- * KERNEL_V2P(va) .... virtual to physical ones.
- *
- * What is done herein:
- * 1. The 'boot_pt1' is replaced by real kernel L1 page table 'kern_pt1'.
- * 2. PT2MAP magic is brought to live.
- * 3. Basic preboot functions for page allocations and mappings can be used.
- * 4. Everything is prepared for L1 cache enabling.
- *
- * Variations:
- * 1. To use second TTB register, so kernel and users page tables will be
- * separated. This way process forking - pmap_pinit() - could be faster,
- * it saves physical pages and KVA per a process, and it's simple change.
- * However, it will lead, due to hardware matter, to the following:
- * (a) 2G space for kernel and 2G space for users.
- * (b) 1G space for kernel in low addresses and 3G for users above it.
- * A question is: Is the case (b) really an option? Note that case (b)
- * does save neither physical memory and KVA.
- */
-void
-pmap_bootstrap_prepare(vm_paddr_t last)
-{
- vm_paddr_t pt2pg_pa, pt2tab_pa, pa, size;
- vm_offset_t pt2pg_va;
- pt1_entry_t *pte1p;
- pt2_entry_t *pte2p;
- u_int i;
- uint32_t actlr_mask, actlr_set;
-
- /*
- * Now, we are going to make real kernel mapping. Note that we are
- * already running on some mapping made in locore.S and we expect
- * that it's large enough to ensure nofault access to physical memory
- * allocated herein before switch.
- *
- * As kernel image and everything needed before are and will be mapped
- * by section mappings, we align last physical address to PTE1_SIZE.
- */
- last_paddr = pte1_roundup(last);
-
- /*
- * Allocate and zero page(s) for kernel L1 page table.
- *
- * Note that it's first allocation on space which was PTE1_SIZE
- * aligned and as such base_pt1 is aligned to NB_IN_PT1 too.
- */
- base_pt1 = pmap_preboot_get_pages(NPG_IN_PT1);
- kern_pt1 = (pt1_entry_t *)KERNEL_P2V(base_pt1);
- bzero((void*)kern_pt1, NB_IN_PT1);
- pte1_sync_range(kern_pt1, NB_IN_PT1);
-
- /* Allocate and zero page(s) for kernel PT2TAB. */
- pt2tab_pa = pmap_preboot_get_pages(NPG_IN_PT2TAB);
- kern_pt2tab = (pt2_entry_t *)KERNEL_P2V(pt2tab_pa);
- bzero(kern_pt2tab, NB_IN_PT2TAB);
- pte2_sync_range(kern_pt2tab, NB_IN_PT2TAB);
-
- /* Allocate and zero page(s) for kernel L2 page tables. */
- pt2pg_pa = pmap_preboot_get_pages(NKPT2PG);
- pt2pg_va = KERNEL_P2V(pt2pg_pa);
- size = NKPT2PG * PAGE_SIZE;
- bzero((void*)pt2pg_va, size);
- pte2_sync_range((pt2_entry_t *)pt2pg_va, size);
-
- /*
- * Add a physical memory segment (vm_phys_seg) corresponding to the
- * preallocated pages for kernel L2 page tables so that vm_page
- * structures representing these pages will be created. The vm_page
- * structures are required for promotion of the corresponding kernel
- * virtual addresses to section mappings.
- */
- vm_phys_add_seg(pt2tab_pa, pmap_preboot_get_pages(0));
-
- /*
- * Insert allocated L2 page table pages to PT2TAB and make
- * link to all PT2s in L1 page table. See how kernel_vm_end
- * is initialized.
- *
- * We play simple and safe. So every KVA will have underlaying
- * L2 page table, even kernel image mapped by sections.
- */
- pte2p = kern_pt2tab_entry(KERNBASE);
- for (pa = pt2pg_pa; pa < pt2pg_pa + size; pa += PTE2_SIZE)
- pt2tab_store(pte2p++, PTE2_KPT(pa));
-
- pte1p = kern_pte1(KERNBASE);
- for (pa = pt2pg_pa; pa < pt2pg_pa + size; pa += NB_IN_PT2)
- pte1_store(pte1p++, PTE1_LINK(pa));
-
- /* Make section mappings for kernel. */
- pte1p = kern_pte1(KERNBASE);
- for (pa = KERNEL_V2P(KERNBASE); pa < last; pa += PTE1_SIZE)
- pte1_store(pte1p++, PTE1_KERN(pa, PTE1_AP_KRW,
- ATTR_TO_L1(PTE2_ATTR_WB_WA)));
-
- /*
- * Get free and aligned space for PT2MAP and make L1 page table links
- * to L2 page tables held in PT2TAB.
- *
- * Note that pages holding PT2s are stored in PT2TAB as pt2_entry_t
- * descriptors and PT2TAB page(s) itself is(are) used as PT2s. Thus
- * each entry in PT2TAB maps all PT2s in a page. This implies that
- * virtual address of PT2MAP must be aligned to NPT2_IN_PG * PTE1_SIZE.
- */
- PT2MAP = (pt2_entry_t *)(KERNBASE - PT2MAP_SIZE);
- pte1p = kern_pte1((vm_offset_t)PT2MAP);
- for (pa = pt2tab_pa, i = 0; i < NPT2_IN_PT2TAB; i++, pa += NB_IN_PT2) {
- pte1_store(pte1p++, PTE1_LINK(pa));
- }
-
- /*
- * Store PT2TAB in PT2TAB itself, i.e. self reference mapping.
- * Each pmap will hold own PT2TAB, so the mapping should be not global.
- */
- pte2p = kern_pt2tab_entry((vm_offset_t)PT2MAP);
- for (pa = pt2tab_pa, i = 0; i < NPG_IN_PT2TAB; i++, pa += PTE2_SIZE) {
- pt2tab_store(pte2p++, PTE2_KPT_NG(pa));
- }
-
- /*
- * Choose correct L2 page table and make mappings for allocations
- * made herein which replaces temporary locore.S mappings after a while.
- * Note that PT2MAP cannot be used until we switch to kern_pt1.
- *
- * Note, that these allocations started aligned on 1M section and
- * kernel PT1 was allocated first. Making of mappings must follow
- * order of physical allocations as we've used KERNEL_P2V() macro
- * for virtual addresses resolution.
- */
- pte2p = kern_pt2tab_entry((vm_offset_t)kern_pt1);
- pt2pg_va = KERNEL_P2V(pte2_pa(pte2_load(pte2p)));
-
- pte2p = page_pt2(pt2pg_va, pte1_index((vm_offset_t)kern_pt1));
-
- /* Make mapping for kernel L1 page table. */
- for (pa = base_pt1, i = 0; i < NPG_IN_PT1; i++, pa += PTE2_SIZE)
- pte2_store(pte2p++, PTE2_KPT(pa));
-
- /* Make mapping for kernel PT2TAB. */
- for (pa = pt2tab_pa, i = 0; i < NPG_IN_PT2TAB; i++, pa += PTE2_SIZE)
- pte2_store(pte2p++, PTE2_KPT(pa));
-
- /* Finally, switch from 'boot_pt1' to 'kern_pt1'. */
- pmap_kern_ttb = base_pt1 | ttb_flags;
- cpuinfo_get_actlr_modifier(&actlr_mask, &actlr_set);
- reinit_mmu(pmap_kern_ttb, actlr_mask, actlr_set);
- /*
- * Initialize the first available KVA. As kernel image is mapped by
- * sections, we are leaving some gap behind.
- */
- virtual_avail = (vm_offset_t)kern_pt2tab + NPG_IN_PT2TAB * PAGE_SIZE;
-}
-
-/*
- * Setup L2 page table page for given KVA.
- * Used in pre-bootstrap epoch.
- *
- * Note that we have allocated NKPT2PG pages for L2 page tables in advance
- * and used them for mapping KVA starting from KERNBASE. However, this is not
- * enough. Vectors and devices need L2 page tables too. Note that they are
- * even above VM_MAX_KERNEL_ADDRESS.
- */
-static __inline vm_paddr_t
-pmap_preboot_pt2pg_setup(vm_offset_t va)
-{
- pt2_entry_t *pte2p, pte2;
- vm_paddr_t pt2pg_pa;
-
- /* Get associated entry in PT2TAB. */
- pte2p = kern_pt2tab_entry(va);
-
- /* Just return, if PT2s page exists already. */
- pte2 = pt2tab_load(pte2p);
- if (pte2_is_valid(pte2))
- return (pte2_pa(pte2));
-
- KASSERT(va >= VM_MAX_KERNEL_ADDRESS,
- ("%s: NKPT2PG too small", __func__));
-
- /*
- * Allocate page for PT2s and insert it to PT2TAB.
- * In other words, map it into PT2MAP space.
- */
- pt2pg_pa = pmap_preboot_get_pages(1);
- pt2tab_store(pte2p, PTE2_KPT(pt2pg_pa));
-
- /* Zero all PT2s in allocated page. */
- bzero((void*)pt2map_pt2pg(va), PAGE_SIZE);
- pte2_sync_range((pt2_entry_t *)pt2map_pt2pg(va), PAGE_SIZE);
-
- return (pt2pg_pa);
-}
-
-/*
- * Setup L2 page table for given KVA.
- * Used in pre-bootstrap epoch.
- */
-static void
-pmap_preboot_pt2_setup(vm_offset_t va)
-{
- pt1_entry_t *pte1p;
- vm_paddr_t pt2pg_pa, pt2_pa;
-
- /* Setup PT2's page. */
- pt2pg_pa = pmap_preboot_pt2pg_setup(va);
- pt2_pa = page_pt2pa(pt2pg_pa, pte1_index(va));
-
- /* Insert PT2 to PT1. */
- pte1p = kern_pte1(va);
- pte1_store(pte1p, PTE1_LINK(pt2_pa));
-}
-
-/*
- * Get L2 page entry associated with given KVA.
- * Used in pre-bootstrap epoch.
- */
-static __inline pt2_entry_t*
-pmap_preboot_vtopte2(vm_offset_t va)
-{
- pt1_entry_t *pte1p;
-
- /* Setup PT2 if needed. */
- pte1p = kern_pte1(va);
- if (!pte1_is_valid(pte1_load(pte1p))) /* XXX - sections ?! */
- pmap_preboot_pt2_setup(va);
-
- return (pt2map_entry(va));
-}
-
-/*
- * Pre-bootstrap epoch page(s) mapping(s).
- */
-void
-pmap_preboot_map_pages(vm_paddr_t pa, vm_offset_t va, u_int num)
-{
- u_int i;
- pt2_entry_t *pte2p;
-
- /* Map all the pages. */
- for (i = 0; i < num; i++) {
- pte2p = pmap_preboot_vtopte2(va);
- pte2_store(pte2p, PTE2_KRW(pa));
- va += PAGE_SIZE;
- pa += PAGE_SIZE;
- }
-}
-
-/*
- * Pre-bootstrap epoch virtual space alocator.
- */
-vm_offset_t
-pmap_preboot_reserve_pages(u_int num)
-{
- u_int i;
- vm_offset_t start, va;
- pt2_entry_t *pte2p;
-
- /* Allocate virtual space. */
- start = va = virtual_avail;
- virtual_avail += num * PAGE_SIZE;
-
- /* Zero the mapping. */
- for (i = 0; i < num; i++) {
- pte2p = pmap_preboot_vtopte2(va);
- pte2_store(pte2p, 0);
- va += PAGE_SIZE;
- }
-
- return (start);
-}
-
-/*
- * Pre-bootstrap epoch page(s) allocation and mapping(s).
- */
-vm_offset_t
-pmap_preboot_get_vpages(u_int num)
-{
- vm_paddr_t pa;
- vm_offset_t va;
-
- /* Allocate physical page(s). */
- pa = pmap_preboot_get_pages(num);
-
- /* Allocate virtual space. */
- va = virtual_avail;
- virtual_avail += num * PAGE_SIZE;
-
- /* Map and zero all. */
- pmap_preboot_map_pages(pa, va, num);
- bzero((void *)va, num * PAGE_SIZE);
-
- return (va);
-}
-
-/*
- * Pre-bootstrap epoch page mapping(s) with attributes.
- */
-void
-pmap_preboot_map_attr(vm_paddr_t pa, vm_offset_t va, vm_size_t size, int prot,
- int attr)
-{
- u_int num;
- u_int l1_attr, l1_prot;
- pt1_entry_t *pte1p;
- pt2_entry_t *pte2p;
-
- l1_prot = ATTR_TO_L1(prot);
- l1_attr = ATTR_TO_L1(attr);
-
- /* Map all the pages. */
- num = round_page(size);
- while (num > 0) {
- if ((((va | pa) & PTE1_OFFSET) == 0) && (num >= PTE1_SIZE)) {
- pte1p = kern_pte1(va);
- pte1_store(pte1p, PTE1_KERN(pa, l1_prot, l1_attr));
- va += PTE1_SIZE;
- pa += PTE1_SIZE;
- num -= PTE1_SIZE;
- } else {
- pte2p = pmap_preboot_vtopte2(va);
- pte2_store(pte2p, PTE2_KERN(pa, prot, attr));
- va += PAGE_SIZE;
- pa += PAGE_SIZE;
- num -= PAGE_SIZE;
- }
- }
-
-}
-
-/*
- * Extract from the kernel page table the physical address
- * that is mapped by the given virtual address "va".
- */
-vm_paddr_t
-pmap_kextract(vm_offset_t va)
-{
- vm_paddr_t pa;
- pt1_entry_t pte1;
- pt2_entry_t pte2;
-
- pte1 = pte1_load(kern_pte1(va));
- if (pte1_is_section(pte1)) {
- pa = pte1_pa(pte1) | (va & PTE1_OFFSET);
- } else if (pte1_is_link(pte1)) {
- /*
- * We should beware of concurrent promotion that changes
- * pte1 at this point. However, it's not a problem as PT2
- * page is preserved by promotion in PT2TAB. So even if
- * it happens, using of PT2MAP is still safe.
- *
- * QQQ: However, concurrent removing is a problem which
- * ends in abort on PT2MAP space. Locking must be used
- * to deal with this.
- */
- pte2 = pte2_load(pt2map_entry(va));
- pa = pte2_pa(pte2) | (va & PTE2_OFFSET);
- }
- else {
- panic("%s: va %#x pte1 %#x", __func__, va, pte1);
- }
- return (pa);
-}
-
-/*
- * Extract from the kernel page table the physical address
- * that is mapped by the given virtual address "va". Also
- * return L2 page table entry which maps the address.
- *
- * This is only intended to be used for panic dumps.
- */
-vm_paddr_t
-pmap_dump_kextract(vm_offset_t va, pt2_entry_t *pte2p)
-{
- vm_paddr_t pa;
- pt1_entry_t pte1;
- pt2_entry_t pte2;
-
- pte1 = pte1_load(kern_pte1(va));
- if (pte1_is_section(pte1)) {
- pa = pte1_pa(pte1) | (va & PTE1_OFFSET);
- pte2 = pa | ATTR_TO_L2(pte1) | PTE2_V;
- } else if (pte1_is_link(pte1)) {
- pte2 = pte2_load(pt2map_entry(va));
- pa = pte2_pa(pte2);
- } else {
- pte2 = 0;
- pa = 0;
- }
- if (pte2p != NULL)
- *pte2p = pte2;
- return (pa);
-}
-
-/*****************************************************************************
- *
- * PMAP second stage initialization and utility functions
- * for bootstrap epoch.
- *
- * After pmap_bootstrap() is called, the following functions for
- * mappings can be used:
- *
- * void pmap_kenter(vm_offset_t va, vm_paddr_t pa);
- * void pmap_kremove(vm_offset_t va);
- * vm_offset_t pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end,
- * int prot);
- *
- * NOTE: This is not SMP coherent stage. And physical page allocation is not
- * allowed during this stage.
- *
- *****************************************************************************/
-
-/*
- * Initialize kernel PMAP locks and lists, kernel_pmap itself, and
- * reserve various virtual spaces for temporary mappings.
- */
-void
-pmap_bootstrap(vm_offset_t firstaddr)
-{
- pt2_entry_t *unused __unused;
- struct sysmaps *sysmaps;
- u_int i;
-
- /*
- * Initialize the kernel pmap (which is statically allocated).
- */
- PMAP_LOCK_INIT(kernel_pmap);
- kernel_l1pa = (vm_paddr_t)kern_pt1; /* for libkvm */
- kernel_pmap->pm_pt1 = kern_pt1;
- kernel_pmap->pm_pt2tab = kern_pt2tab;
- CPU_FILL(&kernel_pmap->pm_active); /* don't allow deactivation */
- TAILQ_INIT(&kernel_pmap->pm_pvchunk);
-
- /*
- * Initialize the global pv list lock.
- */
- rw_init(&pvh_global_lock, "pmap pv global");
-
- LIST_INIT(&allpmaps);
-
- /*
- * Request a spin mutex so that changes to allpmaps cannot be
- * preempted by smp_rendezvous_cpus().
- */
- mtx_init(&allpmaps_lock, "allpmaps", NULL, MTX_SPIN);
- mtx_lock_spin(&allpmaps_lock);
- LIST_INSERT_HEAD(&allpmaps, kernel_pmap, pm_list);
- mtx_unlock_spin(&allpmaps_lock);
-
- /*
- * Reserve some special page table entries/VA space for temporary
- * mapping of pages.
- */
-#define SYSMAP(c, p, v, n) do { \
- v = (c)pmap_preboot_reserve_pages(n); \
- p = pt2map_entry((vm_offset_t)v); \
- } while (0)
-
- /*
- * Local CMAP1/CMAP2 are used for zeroing and copying pages.
- * Local CMAP3 is used for data cache cleaning.
- * Global CMAP3 is used for the idle process page zeroing.
- */
- for (i = 0; i < MAXCPU; i++) {
- sysmaps = &sysmaps_pcpu[i];
- mtx_init(&sysmaps->lock, "SYSMAPS", NULL, MTX_DEF);
- SYSMAP(caddr_t, sysmaps->CMAP1, sysmaps->CADDR1, 1);
- SYSMAP(caddr_t, sysmaps->CMAP2, sysmaps->CADDR2, 1);
- SYSMAP(caddr_t, sysmaps->CMAP3, sysmaps->CADDR3, 1);
- }
- SYSMAP(caddr_t, CMAP3, CADDR3, 1);
-
- /*
- * Crashdump maps.
- */
- SYSMAP(caddr_t, unused, crashdumpmap, MAXDUMPPGS);
-
- /*
- * _tmppt is used for reading arbitrary physical pages via /dev/mem.
- */
- SYSMAP(caddr_t, unused, _tmppt, 1);
-
- /*
- * PADDR1 and PADDR2 are used by pmap_pte2_quick() and pmap_pte2(),
- * respectively. PADDR3 is used by pmap_pte2_ddb().
- */
- SYSMAP(pt2_entry_t *, PMAP1, PADDR1, 1);
- SYSMAP(pt2_entry_t *, PMAP2, PADDR2, 1);
-#ifdef DDB
- SYSMAP(pt2_entry_t *, PMAP3, PADDR3, 1);
-#endif
- mtx_init(&PMAP2mutex, "PMAP2", NULL, MTX_DEF);
-
- /*
- * Note that in very short time in initarm(), we are going to
- * initialize phys_avail[] array and no futher page allocation
- * can happen after that until vm subsystem will be initialized.
- */
- kernel_vm_end_new = kernel_vm_end;
- virtual_end = vm_max_kernel_address;
-}
-
-static void
-pmap_init_qpages(void)
-{
- struct pcpu *pc;
- int i;
-
- CPU_FOREACH(i) {
- pc = pcpu_find(i);
- pc->pc_qmap_addr = kva_alloc(PAGE_SIZE);
- if (pc->pc_qmap_addr == 0)
- panic("%s: unable to allocate KVA", __func__);
- }
-}
-SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, pmap_init_qpages, NULL);
-
-/*
- * The function can already be use in second initialization stage.
- * As such, the function DOES NOT call pmap_growkernel() where PT2
- * allocation can happen. So if used, be sure that PT2 for given
- * virtual address is allocated already!
- *
- * Add a wired page to the kva.
- * Note: not SMP coherent.
- */
-static __inline void
-pmap_kenter_prot_attr(vm_offset_t va, vm_paddr_t pa, uint32_t prot,
- uint32_t attr)
-{
- pt1_entry_t *pte1p;
- pt2_entry_t *pte2p;
-
- pte1p = kern_pte1(va);
- if (!pte1_is_valid(pte1_load(pte1p))) { /* XXX - sections ?! */
- /*
- * This is a very low level function, so PT2 and particularly
- * PT2PG associated with given virtual address must be already
- * allocated. It's a pain mainly during pmap initialization
- * stage. However, called after pmap initialization with
- * virtual address not under kernel_vm_end will lead to
- * the same misery.
- */
- if (!pte2_is_valid(pte2_load(kern_pt2tab_entry(va))))
- panic("%s: kernel PT2 not allocated!", __func__);
- }
-
- pte2p = pt2map_entry(va);
- pte2_store(pte2p, PTE2_KERN(pa, prot, attr));
-}
-
-static __inline void
-pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int attr)
-{
-
- pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, attr);
-}
-
-PMAP_INLINE void
-pmap_kenter(vm_offset_t va, vm_paddr_t pa)
-{
-
- pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, PTE2_ATTR_NORMAL);
-}
-
-/*
- * Remove a page from the kernel pagetables.
- * Note: not SMP coherent.
- */
-PMAP_INLINE void
-pmap_kremove(vm_offset_t va)
-{
- pt2_entry_t *pte2p;
-
- pte2p = pt2map_entry(va);
- pte2_clear(pte2p);
-}
-
-/*
- * Share new kernel PT2PG with all pmaps.
- * The caller is responsible for maintaining TLB consistency.
- */
-static void
-pmap_kenter_pt2tab(vm_offset_t va, pt2_entry_t npte2)
-{
- pmap_t pmap;
- pt2_entry_t *pte2p;
-
- mtx_lock_spin(&allpmaps_lock);
- LIST_FOREACH(pmap, &allpmaps, pm_list) {
- pte2p = pmap_pt2tab_entry(pmap, va);
- pt2tab_store(pte2p, npte2);
- }
- mtx_unlock_spin(&allpmaps_lock);
-}
-
-/*
- * Share new kernel PTE1 with all pmaps.
- * The caller is responsible for maintaining TLB consistency.
- */
-static void
-pmap_kenter_pte1(vm_offset_t va, pt1_entry_t npte1)
-{
- pmap_t pmap;
- pt1_entry_t *pte1p;
-
- mtx_lock_spin(&allpmaps_lock);
- LIST_FOREACH(pmap, &allpmaps, pm_list) {
- pte1p = pmap_pte1(pmap, va);
- pte1_store(pte1p, npte1);
- }
- mtx_unlock_spin(&allpmaps_lock);
-}
-
-/*
- * Used to map a range of physical addresses into kernel
- * virtual address space.
- *
- * The value passed in '*virt' is a suggested virtual address for
- * the mapping. Architectures which can support a direct-mapped
- * physical to virtual region can return the appropriate address
- * within that region, leaving '*virt' unchanged. Other
- * architectures should map the pages starting at '*virt' and
- * update '*virt' with the first usable address after the mapped
- * region.
- *
- * NOTE: Read the comments above pmap_kenter_prot_attr() as
- * the function is used herein!
- */
-vm_offset_t
-pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot)
-{
- vm_offset_t va, sva;
- vm_paddr_t pte1_offset;
- pt1_entry_t npte1;
- u_int l1prot,l2prot;
-
- PDEBUG(1, printf("%s: virt = %#x, start = %#x, end = %#x (size = %#x),"
- " prot = %d\n", __func__, *virt, start, end, end - start, prot));
-
- l2prot = (prot & VM_PROT_WRITE) ? PTE2_AP_KRW : PTE1_AP_KR;
- l2prot |= (prot & VM_PROT_EXECUTE) ? PTE2_X : PTE2_NX;
- l1prot = ATTR_TO_L1(l2prot);
-
- va = *virt;
- /*
- * Does the physical address range's size and alignment permit at
- * least one section mapping to be created?
- */
- pte1_offset = start & PTE1_OFFSET;
- if ((end - start) - ((PTE1_SIZE - pte1_offset) & PTE1_OFFSET) >=
- PTE1_SIZE) {
- /*
- * Increase the starting virtual address so that its alignment
- * does not preclude the use of section mappings.
- */
- if ((va & PTE1_OFFSET) < pte1_offset)
- va = pte1_trunc(va) + pte1_offset;
- else if ((va & PTE1_OFFSET) > pte1_offset)
- va = pte1_roundup(va) + pte1_offset;
- }
- sva = va;
- while (start < end) {
- if ((start & PTE1_OFFSET) == 0 && end - start >= PTE1_SIZE) {
- KASSERT((va & PTE1_OFFSET) == 0,
- ("%s: misaligned va %#x", __func__, va));
- npte1 = PTE1_KERN(start, l1prot, PTE1_ATTR_NORMAL);
- pmap_kenter_pte1(va, npte1);
- va += PTE1_SIZE;
- start += PTE1_SIZE;
- } else {
- pmap_kenter_prot_attr(va, start, l2prot,
- PTE2_ATTR_NORMAL);
- va += PAGE_SIZE;
- start += PAGE_SIZE;
- }
- }
- tlb_flush_range(sva, va - sva);
- *virt = va;
- return (sva);
-}
-
-/*
- * Make a temporary mapping for a physical address.
- * This is only intended to be used for panic dumps.
- */
-void *
-pmap_kenter_temporary(vm_paddr_t pa, int i)
-{
- vm_offset_t va;
-
- /* QQQ: 'i' should be less or equal to MAXDUMPPGS. */
-
- va = (vm_offset_t)crashdumpmap + (i * PAGE_SIZE);
- pmap_kenter(va, pa);
- tlb_flush_local(va);
- return ((void *)crashdumpmap);
-}
-
-
-/*************************************
- *
- * TLB & cache maintenance routines.
- *
- *************************************/
-
-/*
- * We inline these within pmap.c for speed.
- */
-PMAP_INLINE void
-pmap_tlb_flush(pmap_t pmap, vm_offset_t va)
-{
-
- if (pmap == kernel_pmap || !CPU_EMPTY(&pmap->pm_active))
- tlb_flush(va);
-}
-
-PMAP_INLINE void
-pmap_tlb_flush_range(pmap_t pmap, vm_offset_t sva, vm_size_t size)
-{
-
- if (pmap == kernel_pmap || !CPU_EMPTY(&pmap->pm_active))
- tlb_flush_range(sva, size);
-}
-
-/*
- * Abuse the pte2 nodes for unmapped kva to thread a kva freelist through.
- * Requirements:
- * - Must deal with pages in order to ensure that none of the PTE2_* bits
- * are ever set, PTE2_V in particular.
- * - Assumes we can write to pte2s without pte2_store() atomic ops.
- * - Assumes nothing will ever test these addresses for 0 to indicate
- * no mapping instead of correctly checking PTE2_V.
- * - Assumes a vm_offset_t will fit in a pte2 (true for arm).
- * Because PTE2_V is never set, there can be no mappings to invalidate.
- */
-static vm_offset_t
-pmap_pte2list_alloc(vm_offset_t *head)
-{
- pt2_entry_t *pte2p;
- vm_offset_t va;
-
- va = *head;
- if (va == 0)
- panic("pmap_ptelist_alloc: exhausted ptelist KVA");
- pte2p = pt2map_entry(va);
- *head = *pte2p;
- if (*head & PTE2_V)
- panic("%s: va with PTE2_V set!", __func__);
- *pte2p = 0;
- return (va);
-}
-
-static void
-pmap_pte2list_free(vm_offset_t *head, vm_offset_t va)
-{
- pt2_entry_t *pte2p;
-
- if (va & PTE2_V)
- panic("%s: freeing va with PTE2_V set!", __func__);
- pte2p = pt2map_entry(va);
- *pte2p = *head; /* virtual! PTE2_V is 0 though */
- *head = va;
-}
-
-static void
-pmap_pte2list_init(vm_offset_t *head, void *base, int npages)
-{
- int i;
- vm_offset_t va;
-
- *head = 0;
- for (i = npages - 1; i >= 0; i--) {
- va = (vm_offset_t)base + i * PAGE_SIZE;
- pmap_pte2list_free(head, va);
- }
-}
-
-/*****************************************************************************
- *
- * PMAP third and final stage initialization.
- *
- * After pmap_init() is called, PMAP subsystem is fully initialized.
- *
- *****************************************************************************/
-
-SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
-
-SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_max, CTLFLAG_RD, &pv_entry_max, 0,
- "Max number of PV entries");
-SYSCTL_INT(_vm_pmap, OID_AUTO, shpgperproc, CTLFLAG_RD, &shpgperproc, 0,
- "Page share factor per proc");
-
-static u_long nkpt2pg = NKPT2PG;
-SYSCTL_ULONG(_vm_pmap, OID_AUTO, nkpt2pg, CTLFLAG_RD,
- &nkpt2pg, 0, "Pre-allocated pages for kernel PT2s");
-
-static int sp_enabled = 1;
-SYSCTL_INT(_vm_pmap, OID_AUTO, sp_enabled, CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
- &sp_enabled, 0, "Are large page mappings enabled?");
-
-static SYSCTL_NODE(_vm_pmap, OID_AUTO, pte1, CTLFLAG_RD, 0,
- "1MB page mapping counters");
-
-static u_long pmap_pte1_demotions;
-SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, demotions, CTLFLAG_RD,
- &pmap_pte1_demotions, 0, "1MB page demotions");
-
-static u_long pmap_pte1_mappings;
-SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, mappings, CTLFLAG_RD,
- &pmap_pte1_mappings, 0, "1MB page mappings");
-
-static u_long pmap_pte1_p_failures;
-SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, p_failures, CTLFLAG_RD,
- &pmap_pte1_p_failures, 0, "1MB page promotion failures");
-
-static u_long pmap_pte1_promotions;
-SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, promotions, CTLFLAG_RD,
- &pmap_pte1_promotions, 0, "1MB page promotions");
-
-static __inline ttb_entry_t
-pmap_ttb_get(pmap_t pmap)
-{
-
- return (vtophys(pmap->pm_pt1) | ttb_flags);
-}
-
-/*
- * Initialize a vm_page's machine-dependent fields.
- *
- * Variations:
- * 1. Pages for L2 page tables are always not managed. So, pv_list and
- * pt2_wirecount can share same physical space. However, proper
- * initialization on a page alloc for page tables and reinitialization
- * on the page free must be ensured.
- */
-void
-pmap_page_init(vm_page_t m)
-{
-
- TAILQ_INIT(&m->md.pv_list);
- pt2_wirecount_init(m);
- m->md.pat_mode = PTE2_ATTR_NORMAL;
-}
-
-/*
- * Virtualization for faster way how to zero whole page.
- */
-static __inline void
-pagezero(void *page)
-{
-
- bzero(page, PAGE_SIZE);
-}
-
-/*
- * Zero L2 page table page.
- * Use same KVA as in pmap_zero_page().
- */
-static __inline vm_paddr_t
-pmap_pt2pg_zero(vm_page_t m)
-{
- vm_paddr_t pa;
- struct sysmaps *sysmaps;
-
- pa = VM_PAGE_TO_PHYS(m);
-
- /*
- * XXX: For now, we map whole page even if it's already zero,
- * to sync it even if the sync is only DSB.
- */
- sched_pin();
- sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
- mtx_lock(&sysmaps->lock);
- if (pte2_load(sysmaps->CMAP2) != 0)
- panic("%s: CMAP2 busy", __func__);
- pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW,
- m->md.pat_mode));
- /* Even VM_ALLOC_ZERO request is only advisory. */
- if ((m->flags & PG_ZERO) == 0)
- pagezero(sysmaps->CADDR2);
- pte2_sync_range((pt2_entry_t *)sysmaps->CADDR2, PAGE_SIZE);
- pte2_clear(sysmaps->CMAP2);
- tlb_flush((vm_offset_t)sysmaps->CADDR2);
- sched_unpin();
- mtx_unlock(&sysmaps->lock);
-
- return (pa);
-}
-
-/*
- * Init just allocated page as L2 page table(s) holder
- * and return its physical address.
- */
-static __inline vm_paddr_t
-pmap_pt2pg_init(pmap_t pmap, vm_offset_t va, vm_page_t m)
-{
- vm_paddr_t pa;
- pt2_entry_t *pte2p;
-
- /* Check page attributes. */
- if (pmap_page_get_memattr(m) != pt_memattr)
- pmap_page_set_memattr(m, pt_memattr);
-
- /* Zero page and init wire counts. */
- pa = pmap_pt2pg_zero(m);
- pt2_wirecount_init(m);
-
- /*
- * Map page to PT2MAP address space for given pmap.
- * Note that PT2MAP space is shared with all pmaps.
- */
- if (pmap == kernel_pmap)
- pmap_kenter_pt2tab(va, PTE2_KPT(pa));
- else {
- pte2p = pmap_pt2tab_entry(pmap, va);
- pt2tab_store(pte2p, PTE2_KPT_NG(pa));
- }
-
- return (pa);
-}
-
-/*
- * Initialize the pmap module.
- * Called by vm_init, to initialize any structures that the pmap
- * system needs to map virtual memory.
- */
-void
-pmap_init(void)
-{
- vm_size_t s;
- pt2_entry_t *pte2p, pte2;
- u_int i, pte1_idx, pv_npg;
-
- PDEBUG(1, printf("%s: phys_start = %#x\n", __func__, PHYSADDR));
-
- /*
- * Initialize the vm page array entries for kernel pmap's
- * L2 page table pages allocated in advance.
- */
- pte1_idx = pte1_index(KERNBASE - PT2MAP_SIZE);
- pte2p = kern_pt2tab_entry(KERNBASE - PT2MAP_SIZE);
- for (i = 0; i < nkpt2pg + NPG_IN_PT2TAB; i++, pte2p++) {
- vm_paddr_t pa;
- vm_page_t m;
-
- pte2 = pte2_load(pte2p);
- KASSERT(pte2_is_valid(pte2), ("%s: no valid entry", __func__));
-
- pa = pte2_pa(pte2);
- m = PHYS_TO_VM_PAGE(pa);
- KASSERT(m >= vm_page_array &&
- m < &vm_page_array[vm_page_array_size],
- ("%s: L2 page table page is out of range", __func__));
-
- m->pindex = pte1_idx;
- m->phys_addr = pa;
- pte1_idx += NPT2_IN_PG;
- }
-
- /*
- * Initialize the address space (zone) for the pv entries. Set a
- * high water mark so that the system can recover from excessive
- * numbers of pv entries.
- */
- TUNABLE_INT_FETCH("vm.pmap.shpgperproc", &shpgperproc);
- pv_entry_max = shpgperproc * maxproc + vm_cnt.v_page_count;
- TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max);
- pv_entry_max = roundup(pv_entry_max, _NPCPV);
- pv_entry_high_water = 9 * (pv_entry_max / 10);
-
- /*
- * Are large page mappings enabled?
- */
- TUNABLE_INT_FETCH("vm.pmap.sp_enabled", &sp_enabled);
- if (sp_enabled) {
- KASSERT(MAXPAGESIZES > 1 && pagesizes[1] == 0,
- ("%s: can't assign to pagesizes[1]", __func__));
- pagesizes[1] = PTE1_SIZE;
- }
-
- /*
- * Calculate the size of the pv head table for sections.
- * Handle the possibility that "vm_phys_segs[...].end" is zero.
- * Note that the table is only for sections which could be promoted.
- */
- first_managed_pa = pte1_trunc(vm_phys_segs[0].start);
- pv_npg = (pte1_trunc(vm_phys_segs[vm_phys_nsegs - 1].end - PAGE_SIZE)
- - first_managed_pa) / PTE1_SIZE + 1;
-
- /*
- * Allocate memory for the pv head table for sections.
- */
- s = (vm_size_t)(pv_npg * sizeof(struct md_page));
- s = round_page(s);
- pv_table = (struct md_page *)kmem_malloc(kernel_arena, s,
- M_WAITOK | M_ZERO);
- for (i = 0; i < pv_npg; i++)
- TAILQ_INIT(&pv_table[i].pv_list);
-
- pv_maxchunks = MAX(pv_entry_max / _NPCPV, maxproc);
- pv_chunkbase = (struct pv_chunk *)kva_alloc(PAGE_SIZE * pv_maxchunks);
- if (pv_chunkbase == NULL)
- panic("%s: not enough kvm for pv chunks", __func__);
- pmap_pte2list_init(&pv_vafree, pv_chunkbase, pv_maxchunks);
-}
-
-/*
- * Add a list of wired pages to the kva
- * this routine is only used for temporary
- * kernel mappings that do not need to have
- * page modification or references recorded.
- * Note that old mappings are simply written
- * over. The page *must* be wired.
- * Note: SMP coherent. Uses a ranged shootdown IPI.
- */
-void
-pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count)
-{
- u_int anychanged;
- pt2_entry_t *epte2p, *pte2p, pte2;
- vm_page_t m;
- vm_paddr_t pa;
-
- anychanged = 0;
- pte2p = pt2map_entry(sva);
- epte2p = pte2p + count;
- while (pte2p < epte2p) {
- m = *ma++;
- pa = VM_PAGE_TO_PHYS(m);
- pte2 = pte2_load(pte2p);
- if ((pte2_pa(pte2) != pa) ||
- (pte2_attr(pte2) != m->md.pat_mode)) {
- anychanged++;
- pte2_store(pte2p, PTE2_KERN(pa, PTE2_AP_KRW,
- m->md.pat_mode));
- }
- pte2p++;
- }
- if (__predict_false(anychanged))
- tlb_flush_range(sva, count * PAGE_SIZE);
-}
-
-/*
- * This routine tears out page mappings from the
- * kernel -- it is meant only for temporary mappings.
- * Note: SMP coherent. Uses a ranged shootdown IPI.
- */
-void
-pmap_qremove(vm_offset_t sva, int count)
-{
- vm_offset_t va;
-
- va = sva;
- while (count-- > 0) {
- pmap_kremove(va);
- va += PAGE_SIZE;
- }
- tlb_flush_range(sva, va - sva);
-}
-
-/*
- * Are we current address space or kernel?
- */
-static __inline int
-pmap_is_current(pmap_t pmap)
-{
-
- return (pmap == kernel_pmap ||
- (pmap == vmspace_pmap(curthread->td_proc->p_vmspace)));
-}
-
-/*
- * If the given pmap is not the current or kernel pmap, the returned
- * pte2 must be released by passing it to pmap_pte2_release().
- */
-static pt2_entry_t *
-pmap_pte2(pmap_t pmap, vm_offset_t va)
-{
- pt1_entry_t pte1;
- vm_paddr_t pt2pg_pa;
-
- pte1 = pte1_load(pmap_pte1(pmap, va));
- if (pte1_is_section(pte1))
- panic("%s: attempt to map PTE1", __func__);
- if (pte1_is_link(pte1)) {
- /* Are we current address space or kernel? */
- if (pmap_is_current(pmap))
- return (pt2map_entry(va));
- /* Note that L2 page table size is not equal to PAGE_SIZE. */
- pt2pg_pa = trunc_page(pte1_link_pa(pte1));
- mtx_lock(&PMAP2mutex);
- if (pte2_pa(pte2_load(PMAP2)) != pt2pg_pa) {
- pte2_store(PMAP2, PTE2_KPT(pt2pg_pa));
- tlb_flush((vm_offset_t)PADDR2);
- }
- return (PADDR2 + (arm32_btop(va) & (NPTE2_IN_PG - 1)));
- }
- return (NULL);
-}
-
-/*
- * Releases a pte2 that was obtained from pmap_pte2().
- * Be prepared for the pte2p being NULL.
- */
-static __inline void
-pmap_pte2_release(pt2_entry_t *pte2p)
-{
-
- if ((pt2_entry_t *)(trunc_page((vm_offset_t)pte2p)) == PADDR2) {
- mtx_unlock(&PMAP2mutex);
- }
-}
-
-/*
- * Super fast pmap_pte2 routine best used when scanning
- * the pv lists. This eliminates many coarse-grained
- * invltlb calls. Note that many of the pv list
- * scans are across different pmaps. It is very wasteful
- * to do an entire tlb flush for checking a single mapping.
- *
- * If the given pmap is not the current pmap, pvh_global_lock
- * must be held and curthread pinned to a CPU.
- */
-static pt2_entry_t *
-pmap_pte2_quick(pmap_t pmap, vm_offset_t va)
-{
- pt1_entry_t pte1;
- vm_paddr_t pt2pg_pa;
-
- pte1 = pte1_load(pmap_pte1(pmap, va));
- if (pte1_is_section(pte1))
- panic("%s: attempt to map PTE1", __func__);
- if (pte1_is_link(pte1)) {
- /* Are we current address space or kernel? */
- if (pmap_is_current(pmap))
- return (pt2map_entry(va));
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- KASSERT(curthread->td_pinned > 0,
- ("%s: curthread not pinned", __func__));
- /* Note that L2 page table size is not equal to PAGE_SIZE. */
- pt2pg_pa = trunc_page(pte1_link_pa(pte1));
- if (pte2_pa(pte2_load(PMAP1)) != pt2pg_pa) {
- pte2_store(PMAP1, PTE2_KPT(pt2pg_pa));
-#ifdef SMP
- PMAP1cpu = PCPU_GET(cpuid);
-#endif
- tlb_flush_local((vm_offset_t)PADDR1);
- PMAP1changed++;
- } else
-#ifdef SMP
- if (PMAP1cpu != PCPU_GET(cpuid)) {
- PMAP1cpu = PCPU_GET(cpuid);
- tlb_flush_local((vm_offset_t)PADDR1);
- PMAP1changedcpu++;
- } else
-#endif
- PMAP1unchanged++;
- return (PADDR1 + (arm32_btop(va) & (NPTE2_IN_PG - 1)));
- }
- return (NULL);
-}
-
-/*
- * Routine: pmap_extract
- * Function:
- * Extract the physical page address associated
- * with the given map/virtual_address pair.
- */
-vm_paddr_t
-pmap_extract(pmap_t pmap, vm_offset_t va)
-{
- vm_paddr_t pa;
- pt1_entry_t pte1;
- pt2_entry_t *pte2p;
-
- PMAP_LOCK(pmap);
- pte1 = pte1_load(pmap_pte1(pmap, va));
- if (pte1_is_section(pte1))
- pa = pte1_pa(pte1) | (va & PTE1_OFFSET);
- else if (pte1_is_link(pte1)) {
- pte2p = pmap_pte2(pmap, va);
- pa = pte2_pa(pte2_load(pte2p)) | (va & PTE2_OFFSET);
- pmap_pte2_release(pte2p);
- } else
- pa = 0;
- PMAP_UNLOCK(pmap);
- return (pa);
-}
-
-/*
- * Routine: pmap_extract_and_hold
- * Function:
- * Atomically extract and hold the physical page
- * with the given pmap and virtual address pair
- * if that mapping permits the given protection.
- */
-vm_page_t
-pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
-{
- vm_paddr_t pa, lockpa;
- pt1_entry_t pte1;
- pt2_entry_t pte2, *pte2p;
- vm_page_t m;
-
- lockpa = 0;
- m = NULL;
- PMAP_LOCK(pmap);
-retry:
- pte1 = pte1_load(pmap_pte1(pmap, va));
- if (pte1_is_section(pte1)) {
- if (!(pte1 & PTE1_RO) || !(prot & VM_PROT_WRITE)) {
- pa = pte1_pa(pte1) | (va & PTE1_OFFSET);
- if (vm_page_pa_tryrelock(pmap, pa, &lockpa))
- goto retry;
- m = PHYS_TO_VM_PAGE(pa);
- vm_page_hold(m);
- }
- } else if (pte1_is_link(pte1)) {
- pte2p = pmap_pte2(pmap, va);
- pte2 = pte2_load(pte2p);
- pmap_pte2_release(pte2p);
- if (pte2_is_valid(pte2) &&
- (!(pte2 & PTE2_RO) || !(prot & VM_PROT_WRITE))) {
- pa = pte2_pa(pte2);
- if (vm_page_pa_tryrelock(pmap, pa, &lockpa))
- goto retry;
- m = PHYS_TO_VM_PAGE(pa);
- vm_page_hold(m);
- }
- }
- PA_UNLOCK_COND(lockpa);
- PMAP_UNLOCK(pmap);
- return (m);
-}
-
-/*
- * Grow the number of kernel L2 page table entries, if needed.
- */
-void
-pmap_growkernel(vm_offset_t addr)
-{
- vm_page_t m;
- vm_paddr_t pt2pg_pa, pt2_pa;
- pt1_entry_t pte1;
- pt2_entry_t pte2;
-
- PDEBUG(1, printf("%s: addr = %#x\n", __func__, addr));
- /*
- * All the time kernel_vm_end is first KVA for which underlying
- * L2 page table is either not allocated or linked from L1 page table
- * (not considering sections). Except for two possible cases:
- *
- * (1) in the very beginning as long as pmap_growkernel() was
- * not called, it could be first unused KVA (which is not
- * rounded up to PTE1_SIZE),
- *
- * (2) when all KVA space is mapped and kernel_map->max_offset
- * address is not rounded up to PTE1_SIZE. (For example,
- * it could be 0xFFFFFFFF.)
- */
- kernel_vm_end = pte1_roundup(kernel_vm_end);
- mtx_assert(&kernel_map->system_mtx, MA_OWNED);
- addr = roundup2(addr, PTE1_SIZE);
- if (addr - 1 >= kernel_map->max_offset)
- addr = kernel_map->max_offset;
- while (kernel_vm_end < addr) {
- pte1 = pte1_load(kern_pte1(kernel_vm_end));
- if (pte1_is_valid(pte1)) {
- kernel_vm_end += PTE1_SIZE;
- if (kernel_vm_end - 1 >= kernel_map->max_offset) {
- kernel_vm_end = kernel_map->max_offset;
- break;
- }
- continue;
- }
-
- /*
- * kernel_vm_end_new is used in pmap_pinit() when kernel
- * mappings are entered to new pmap all at once to avoid race
- * between pmap_kenter_pte1() and kernel_vm_end increase.
- * The same aplies to pmap_kenter_pt2tab().
- */
- kernel_vm_end_new = kernel_vm_end + PTE1_SIZE;
-
- pte2 = pt2tab_load(kern_pt2tab_entry(kernel_vm_end));
- if (!pte2_is_valid(pte2)) {
- /*
- * Install new PT2s page into kernel PT2TAB.
- */
- m = vm_page_alloc(NULL,
- pte1_index(kernel_vm_end) & ~PT2PG_MASK,
- VM_ALLOC_INTERRUPT | VM_ALLOC_NOOBJ |
- VM_ALLOC_WIRED | VM_ALLOC_ZERO);
- if (m == NULL)
- panic("%s: no memory to grow kernel", __func__);
- /*
- * QQQ: To link all new L2 page tables from L1 page
- * table now and so pmap_kenter_pte1() them
- * at once together with pmap_kenter_pt2tab()
- * could be nice speed up. However,
- * pmap_growkernel() does not happen so often...
- * QQQ: The other TTBR is another option.
- */
- pt2pg_pa = pmap_pt2pg_init(kernel_pmap, kernel_vm_end,
- m);
- } else
- pt2pg_pa = pte2_pa(pte2);
-
- pt2_pa = page_pt2pa(pt2pg_pa, pte1_index(kernel_vm_end));
- pmap_kenter_pte1(kernel_vm_end, PTE1_LINK(pt2_pa));
-
- kernel_vm_end = kernel_vm_end_new;
- if (kernel_vm_end - 1 >= kernel_map->max_offset) {
- kernel_vm_end = kernel_map->max_offset;
- break;
- }
- }
-}
-
-static int
-kvm_size(SYSCTL_HANDLER_ARGS)
-{
- unsigned long ksize = vm_max_kernel_address - KERNBASE;
-
- return (sysctl_handle_long(oidp, &ksize, 0, req));
-}
-SYSCTL_PROC(_vm, OID_AUTO, kvm_size, CTLTYPE_LONG|CTLFLAG_RD,
- 0, 0, kvm_size, "IU", "Size of KVM");
-
-static int
-kvm_free(SYSCTL_HANDLER_ARGS)
-{
- unsigned long kfree = vm_max_kernel_address - kernel_vm_end;
-
- return (sysctl_handle_long(oidp, &kfree, 0, req));
-}
-SYSCTL_PROC(_vm, OID_AUTO, kvm_free, CTLTYPE_LONG|CTLFLAG_RD,
- 0, 0, kvm_free, "IU", "Amount of KVM free");
-
-/***********************************************
- *
- * Pmap allocation/deallocation routines.
- *
- ***********************************************/
-
-/*
- * Initialize the pmap for the swapper process.
- */
-void
-pmap_pinit0(pmap_t pmap)
-{
- PDEBUG(1, printf("%s: pmap = %p\n", __func__, pmap));
-
- PMAP_LOCK_INIT(pmap);
-
- /*
- * Kernel page table directory and pmap stuff around is already
- * initialized, we are using it right now and here. So, finish
- * only PMAP structures initialization for process0 ...
- *
- * Since the L1 page table and PT2TAB is shared with the kernel pmap,
- * which is already included in the list "allpmaps", this pmap does
- * not need to be inserted into that list.
- */
- pmap->pm_pt1 = kern_pt1;
- pmap->pm_pt2tab = kern_pt2tab;
- CPU_ZERO(&pmap->pm_active);
- PCPU_SET(curpmap, pmap);
- TAILQ_INIT(&pmap->pm_pvchunk);
- bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
- CPU_SET(0, &pmap->pm_active);
-}
-
-static __inline void
-pte1_copy_nosync(pt1_entry_t *spte1p, pt1_entry_t *dpte1p, vm_offset_t sva,
- vm_offset_t eva)
-{
- u_int idx, count;
-
- idx = pte1_index(sva);
- count = (pte1_index(eva) - idx + 1) * sizeof(pt1_entry_t);
- bcopy(spte1p + idx, dpte1p + idx, count);
-}
-
-static __inline void
-pt2tab_copy_nosync(pt2_entry_t *spte2p, pt2_entry_t *dpte2p, vm_offset_t sva,
- vm_offset_t eva)
-{
- u_int idx, count;
-
- idx = pt2tab_index(sva);
- count = (pt2tab_index(eva) - idx + 1) * sizeof(pt2_entry_t);
- bcopy(spte2p + idx, dpte2p + idx, count);
-}
-
-/*
- * Initialize a preallocated and zeroed pmap structure,
- * such as one in a vmspace structure.
- */
-int
-pmap_pinit(pmap_t pmap)
-{
- pt1_entry_t *pte1p;
- pt2_entry_t *pte2p;
- vm_paddr_t pa, pt2tab_pa;
- u_int i;
-
- PDEBUG(6, printf("%s: pmap = %p, pm_pt1 = %p\n", __func__, pmap,
- pmap->pm_pt1));
-
- /*
- * No need to allocate L2 page table space yet but we do need
- * a valid L1 page table and PT2TAB table.
- *
- * Install shared kernel mappings to these tables. It's a little
- * tricky as some parts of KVA are reserved for vectors, devices,
- * and whatever else. These parts are supposed to be above
- * vm_max_kernel_address. Thus two regions should be installed:
- *
- * (1) <KERNBASE, kernel_vm_end),
- * (2) <vm_max_kernel_address, 0xFFFFFFFF>.
- *
- * QQQ: The second region should be stable enough to be installed
- * only once in time when the tables are allocated.
- * QQQ: Maybe copy of both regions at once could be faster ...
- * QQQ: Maybe the other TTBR is an option.
- *
- * Finally, install own PT2TAB table to these tables.
- */
-
- if (pmap->pm_pt1 == NULL) {
- pmap->pm_pt1 = (pt1_entry_t *)kmem_alloc_contig(kernel_arena,
- NB_IN_PT1, M_NOWAIT | M_ZERO, 0, -1UL, NB_IN_PT1, 0,
- pt_memattr);
- if (pmap->pm_pt1 == NULL)
- return (0);
- }
- if (pmap->pm_pt2tab == NULL) {
- /*
- * QQQ: (1) PT2TAB must be contiguous. If PT2TAB is one page
- * only, what should be the only size for 32 bit systems,
- * then we could allocate it with vm_page_alloc() and all
- * the stuff needed as other L2 page table pages.
- * (2) Note that a process PT2TAB is special L2 page table
- * page. Its mapping in kernel_arena is permanent and can
- * be used no matter which process is current. Its mapping
- * in PT2MAP can be used only for current process.
- */
- pmap->pm_pt2tab = (pt2_entry_t *)kmem_alloc_attr(kernel_arena,
- NB_IN_PT2TAB, M_NOWAIT | M_ZERO, 0, -1UL, pt_memattr);
- if (pmap->pm_pt2tab == NULL) {
- /*
- * QQQ: As struct pmap is allocated from UMA with
- * UMA_ZONE_NOFREE flag, it's important to leave
- * no allocation in pmap if initialization failed.
- */
- kmem_free(kernel_arena, (vm_offset_t)pmap->pm_pt1,
- NB_IN_PT1);
- pmap->pm_pt1 = NULL;
- return (0);
- }
- /*
- * QQQ: Each L2 page table page vm_page_t has pindex set to
- * pte1 index of virtual address mapped by this page.
- * It's not valid for non kernel PT2TABs themselves.
- * The pindex of these pages can not be altered because
- * of the way how they are allocated now. However, it
- * should not be a problem.
- */
- }
-
- mtx_lock_spin(&allpmaps_lock);
- /*
- * To avoid race with pmap_kenter_pte1() and pmap_kenter_pt2tab(),
- * kernel_vm_end_new is used here instead of kernel_vm_end.
- */
- pte1_copy_nosync(kern_pt1, pmap->pm_pt1, KERNBASE,
- kernel_vm_end_new - 1);
- pte1_copy_nosync(kern_pt1, pmap->pm_pt1, vm_max_kernel_address,
- 0xFFFFFFFF);
- pt2tab_copy_nosync(kern_pt2tab, pmap->pm_pt2tab, KERNBASE,
- kernel_vm_end_new - 1);
- pt2tab_copy_nosync(kern_pt2tab, pmap->pm_pt2tab, vm_max_kernel_address,
- 0xFFFFFFFF);
- LIST_INSERT_HEAD(&allpmaps, pmap, pm_list);
- mtx_unlock_spin(&allpmaps_lock);
-
- /*
- * Store PT2MAP PT2 pages (a.k.a. PT2TAB) in PT2TAB itself.
- * I.e. self reference mapping. The PT2TAB is private, however mapped
- * into shared PT2MAP space, so the mapping should be not global.
- */
- pt2tab_pa = vtophys(pmap->pm_pt2tab);
- pte2p = pmap_pt2tab_entry(pmap, (vm_offset_t)PT2MAP);
- for (pa = pt2tab_pa, i = 0; i < NPG_IN_PT2TAB; i++, pa += PTE2_SIZE) {
- pt2tab_store(pte2p++, PTE2_KPT_NG(pa));
- }
-
- /* Insert PT2MAP PT2s into pmap PT1. */
- pte1p = pmap_pte1(pmap, (vm_offset_t)PT2MAP);
- for (pa = pt2tab_pa, i = 0; i < NPT2_IN_PT2TAB; i++, pa += NB_IN_PT2) {
- pte1_store(pte1p++, PTE1_LINK(pa));
- }
-
- /*
- * Now synchronize new mapping which was made above.
- */
- pte1_sync_range(pmap->pm_pt1, NB_IN_PT1);
- pte2_sync_range(pmap->pm_pt2tab, NB_IN_PT2TAB);
-
- CPU_ZERO(&pmap->pm_active);
- TAILQ_INIT(&pmap->pm_pvchunk);
- bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
-
- return (1);
-}
-
-#ifdef INVARIANTS
-static boolean_t
-pt2tab_user_is_empty(pt2_entry_t *tab)
-{
- u_int i, end;
-
- end = pt2tab_index(VM_MAXUSER_ADDRESS);
- for (i = 0; i < end; i++)
- if (tab[i] != 0) return (FALSE);
- return (TRUE);
-}
-#endif
-/*
- * Release any resources held by the given physical map.
- * Called when a pmap initialized by pmap_pinit is being released.
- * Should only be called if the map contains no valid mappings.
- */
-void
-pmap_release(pmap_t pmap)
-{
-#ifdef INVARIANTS
- vm_offset_t start, end;
-#endif
- KASSERT(pmap->pm_stats.resident_count == 0,
- ("%s: pmap resident count %ld != 0", __func__,
- pmap->pm_stats.resident_count));
- KASSERT(pt2tab_user_is_empty(pmap->pm_pt2tab),
- ("%s: has allocated user PT2(s)", __func__));
- KASSERT(CPU_EMPTY(&pmap->pm_active),
- ("%s: pmap %p is active on some CPU(s)", __func__, pmap));
-
- mtx_lock_spin(&allpmaps_lock);
- LIST_REMOVE(pmap, pm_list);
- mtx_unlock_spin(&allpmaps_lock);
-
-#ifdef INVARIANTS
- start = pte1_index(KERNBASE) * sizeof(pt1_entry_t);
- end = (pte1_index(0xFFFFFFFF) + 1) * sizeof(pt1_entry_t);
- bzero((char *)pmap->pm_pt1 + start, end - start);
-
- start = pt2tab_index(KERNBASE) * sizeof(pt2_entry_t);
- end = (pt2tab_index(0xFFFFFFFF) + 1) * sizeof(pt2_entry_t);
- bzero((char *)pmap->pm_pt2tab + start, end - start);
-#endif
- /*
- * We are leaving PT1 and PT2TAB allocated on released pmap,
- * so hopefully UMA vmspace_zone will always be inited with
- * UMA_ZONE_NOFREE flag.
- */
-}
-
-/*********************************************************
- *
- * L2 table pages and their pages management routines.
- *
- *********************************************************/
-
-/*
- * Virtual interface for L2 page table wire counting.
- *
- * Each L2 page table in a page has own counter which counts a number of
- * valid mappings in a table. Global page counter counts mappings in all
- * tables in a page plus a single itself mapping in PT2TAB.
- *
- * During a promotion we leave the associated L2 page table counter
- * untouched, so the table (strictly speaking a page which holds it)
- * is never freed if promoted.
- *
- * If a page m->wire_count == 1 then no valid mappings exist in any L2 page
- * table in the page and the page itself is only mapped in PT2TAB.
- */
-
-static __inline void
-pt2_wirecount_init(vm_page_t m)
-{
- u_int i;
-
- /*
- * Note: A page m is allocated with VM_ALLOC_WIRED flag and
- * m->wire_count should be already set correctly.
- * So, there is no need to set it again herein.
- */
- for (i = 0; i < NPT2_IN_PG; i++)
- m->md.pt2_wirecount[i] = 0;
-}
-
-static __inline void
-pt2_wirecount_inc(vm_page_t m, uint32_t pte1_idx)
-{
-
- /*
- * Note: A just modificated pte2 (i.e. already allocated)
- * is acquiring one extra reference which must be
- * explicitly cleared. It influences the KASSERTs herein.
- * All L2 page tables in a page always belong to the same
- * pmap, so we allow only one extra reference for the page.
- */
- KASSERT(m->md.pt2_wirecount[pte1_idx & PT2PG_MASK] < (NPTE2_IN_PT2 + 1),
- ("%s: PT2 is overflowing ...", __func__));
- KASSERT(m->wire_count <= (NPTE2_IN_PG + 1),
- ("%s: PT2PG is overflowing ...", __func__));
-
- m->wire_count++;
- m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]++;
-}
-
-static __inline void
-pt2_wirecount_dec(vm_page_t m, uint32_t pte1_idx)
-{
-
- KASSERT(m->md.pt2_wirecount[pte1_idx & PT2PG_MASK] != 0,
- ("%s: PT2 is underflowing ...", __func__));
- KASSERT(m->wire_count > 1,
- ("%s: PT2PG is underflowing ...", __func__));
-
- m->wire_count--;
- m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]--;
-}
-
-static __inline void
-pt2_wirecount_set(vm_page_t m, uint32_t pte1_idx, uint16_t count)
-{
-
- KASSERT(count <= NPTE2_IN_PT2,
- ("%s: invalid count %u", __func__, count));
- KASSERT(m->wire_count > m->md.pt2_wirecount[pte1_idx & PT2PG_MASK],
- ("%s: PT2PG corrupting (%u, %u) ...", __func__, m->wire_count,
- m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]));
-
- m->wire_count -= m->md.pt2_wirecount[pte1_idx & PT2PG_MASK];
- m->wire_count += count;
- m->md.pt2_wirecount[pte1_idx & PT2PG_MASK] = count;
-
- KASSERT(m->wire_count <= (NPTE2_IN_PG + 1),
- ("%s: PT2PG is overflowed (%u) ...", __func__, m->wire_count));
-}
-
-static __inline uint32_t
-pt2_wirecount_get(vm_page_t m, uint32_t pte1_idx)
-{
-
- return (m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]);
-}
-
-static __inline boolean_t
-pt2_is_empty(vm_page_t m, vm_offset_t va)
-{
-
- return (m->md.pt2_wirecount[pte1_index(va) & PT2PG_MASK] == 0);
-}
-
-static __inline boolean_t
-pt2_is_full(vm_page_t m, vm_offset_t va)
-{
-
- return (m->md.pt2_wirecount[pte1_index(va) & PT2PG_MASK] ==
- NPTE2_IN_PT2);
-}
-
-static __inline boolean_t
-pt2pg_is_empty(vm_page_t m)
-{
-
- return (m->wire_count == 1);
-}
-
-/*
- * This routine is called if the L2 page table
- * is not mapped correctly.
- */
-static vm_page_t
-_pmap_allocpte2(pmap_t pmap, vm_offset_t va, u_int flags)
-{
- uint32_t pte1_idx;
- pt1_entry_t *pte1p;
- pt2_entry_t pte2;
- vm_page_t m;
- vm_paddr_t pt2pg_pa, pt2_pa;
-
- pte1_idx = pte1_index(va);
- pte1p = pmap->pm_pt1 + pte1_idx;
-
- KASSERT(pte1_load(pte1p) == 0,
- ("%s: pm_pt1[%#x] is not zero: %#x", __func__, pte1_idx,
- pte1_load(pte1p)));
-
- pte2 = pt2tab_load(pmap_pt2tab_entry(pmap, va));
- if (!pte2_is_valid(pte2)) {
- /*
- * Install new PT2s page into pmap PT2TAB.
- */
- m = vm_page_alloc(NULL, pte1_idx & ~PT2PG_MASK,
- VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
- if (m == NULL) {
- if ((flags & PMAP_ENTER_NOSLEEP) == 0) {
- PMAP_UNLOCK(pmap);
- rw_wunlock(&pvh_global_lock);
- VM_WAIT;
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
- }
-
- /*
- * Indicate the need to retry. While waiting,
- * the L2 page table page may have been allocated.
- */
- return (NULL);
- }
- pmap->pm_stats.resident_count++;
- pt2pg_pa = pmap_pt2pg_init(pmap, va, m);
- } else {
- pt2pg_pa = pte2_pa(pte2);
- m = PHYS_TO_VM_PAGE(pt2pg_pa);
- }
-
- pt2_wirecount_inc(m, pte1_idx);
- pt2_pa = page_pt2pa(pt2pg_pa, pte1_idx);
- pte1_store(pte1p, PTE1_LINK(pt2_pa));
-
- return (m);
-}
-
-static vm_page_t
-pmap_allocpte2(pmap_t pmap, vm_offset_t va, u_int flags)
-{
- u_int pte1_idx;
- pt1_entry_t *pte1p, pte1;
- vm_page_t m;
-
- pte1_idx = pte1_index(va);
-retry:
- pte1p = pmap->pm_pt1 + pte1_idx;
- pte1 = pte1_load(pte1p);
-
- /*
- * This supports switching from a 1MB page to a
- * normal 4K page.
- */
- if (pte1_is_section(pte1)) {
- (void)pmap_demote_pte1(pmap, pte1p, va);
- /*
- * Reload pte1 after demotion.
- *
- * Note: Demotion can even fail as either PT2 is not find for
- * the virtual address or PT2PG can not be allocated.
- */
- pte1 = pte1_load(pte1p);
- }
-
- /*
- * If the L2 page table page is mapped, we just increment the
- * hold count, and activate it.
- */
- if (pte1_is_link(pte1)) {
- m = PHYS_TO_VM_PAGE(pte1_link_pa(pte1));
- pt2_wirecount_inc(m, pte1_idx);
- } else {
- /*
- * Here if the PT2 isn't mapped, or if it has
- * been deallocated.
- */
- m = _pmap_allocpte2(pmap, va, flags);
- if (m == NULL && (flags & PMAP_ENTER_NOSLEEP) == 0)
- goto retry;
- }
-
- return (m);
-}
-
-static __inline void
-pmap_free_zero_pages(struct spglist *free)
-{
- vm_page_t m;
-
- while ((m = SLIST_FIRST(free)) != NULL) {
- SLIST_REMOVE_HEAD(free, plinks.s.ss);
- /* Preserve the page's PG_ZERO setting. */
- vm_page_free_toq(m);
- }
-}
-
-/*
- * Schedule the specified unused L2 page table page to be freed. Specifically,
- * add the page to the specified list of pages that will be released to the
- * physical memory manager after the TLB has been updated.
- */
-static __inline void
-pmap_add_delayed_free_list(vm_page_t m, struct spglist *free)
-{
-
- /*
- * Put page on a list so that it is released after
- * *ALL* TLB shootdown is done
- */
-#ifdef PMAP_DEBUG
- pmap_zero_page_check(m);
-#endif
- m->flags |= PG_ZERO;
- SLIST_INSERT_HEAD(free, m, plinks.s.ss);
-}
-
-/*
- * Unwire L2 page tables page.
- */
-static void
-pmap_unwire_pt2pg(pmap_t pmap, vm_offset_t va, vm_page_t m)
-{
- pt1_entry_t *pte1p, opte1 __unused;
- pt2_entry_t *pte2p;
- uint32_t i;
-
- KASSERT(pt2pg_is_empty(m),
- ("%s: pmap %p PT2PG %p wired", __func__, pmap, m));
-
- /*
- * Unmap all L2 page tables in the page from L1 page table.
- *
- * QQQ: Individual L2 page tables (except the last one) can be unmapped
- * earlier. However, we are doing that this way.
- */
- KASSERT(m->pindex == (pte1_index(va) & ~PT2PG_MASK),
- ("%s: pmap %p va %#x PT2PG %p bad index", __func__, pmap, va, m));
- pte1p = pmap->pm_pt1 + m->pindex;
- for (i = 0; i < NPT2_IN_PG; i++, pte1p++) {
- KASSERT(m->md.pt2_wirecount[i] == 0,
- ("%s: pmap %p PT2 %u (PG %p) wired", __func__, pmap, i, m));
- opte1 = pte1_load(pte1p);
- if (pte1_is_link(opte1)) {
- pte1_clear(pte1p);
- /*
- * Flush intermediate TLB cache.
- */
- pmap_tlb_flush(pmap, (m->pindex + i) << PTE1_SHIFT);
- }
-#ifdef INVARIANTS
- else
- KASSERT((opte1 == 0) || pte1_is_section(opte1),
- ("%s: pmap %p va %#x bad pte1 %x at %u", __func__,
- pmap, va, opte1, i));
-#endif
- }
-
- /*
- * Unmap the page from PT2TAB.
- */
- pte2p = pmap_pt2tab_entry(pmap, va);
- (void)pt2tab_load_clear(pte2p);
- pmap_tlb_flush(pmap, pt2map_pt2pg(va));
-
- m->wire_count = 0;
- pmap->pm_stats.resident_count--;
-
- /*
- * This is a release store so that the ordinary store unmapping
- * the L2 page table page is globally performed before TLB shoot-
- * down is begun.
- */
- atomic_subtract_rel_int(&vm_cnt.v_wire_count, 1);
-}
-
-/*
- * Decrements a L2 page table page's wire count, which is used to record the
- * number of valid page table entries within the page. If the wire count
- * drops to zero, then the page table page is unmapped. Returns TRUE if the
- * page table page was unmapped and FALSE otherwise.
- */
-static __inline boolean_t
-pmap_unwire_pt2(pmap_t pmap, vm_offset_t va, vm_page_t m, struct spglist *free)
-{
- pt2_wirecount_dec(m, pte1_index(va));
- if (pt2pg_is_empty(m)) {
- /*
- * QQQ: Wire count is zero, so whole page should be zero and
- * we can set PG_ZERO flag to it.
- * Note that when promotion is enabled, it takes some
- * more efforts. See pmap_unwire_pt2_all() below.
- */
- pmap_unwire_pt2pg(pmap, va, m);
- pmap_add_delayed_free_list(m, free);
- return (TRUE);
- } else
- return (FALSE);
-}
-
-/*
- * Drop a L2 page table page's wire count at once, which is used to record
- * the number of valid L2 page table entries within the page. If the wire
- * count drops to zero, then the L2 page table page is unmapped.
- */
-static __inline void
-pmap_unwire_pt2_all(pmap_t pmap, vm_offset_t va, vm_page_t m,
- struct spglist *free)
-{
- u_int pte1_idx = pte1_index(va);
-
- KASSERT(m->pindex == (pte1_idx & ~PT2PG_MASK),
- ("%s: PT2 page's pindex is wrong", __func__));
- KASSERT(m->wire_count > pt2_wirecount_get(m, pte1_idx),
- ("%s: bad pt2 wire count %u > %u", __func__, m->wire_count,
- pt2_wirecount_get(m, pte1_idx)));
-
- /*
- * It's possible that the L2 page table was never used.
- * It happened in case that a section was created without promotion.
- */
- if (pt2_is_full(m, va)) {
- pt2_wirecount_set(m, pte1_idx, 0);
-
- /*
- * QQQ: We clear L2 page table now, so when L2 page table page
- * is going to be freed, we can set it PG_ZERO flag ...
- * This function is called only on section mappings, so
- * hopefully it's not to big overload.
- *
- * XXX: If pmap is current, existing PT2MAP mapping could be
- * used for zeroing.
- */
- pmap_zero_page_area(m, page_pt2off(pte1_idx), NB_IN_PT2);
- }
-#ifdef INVARIANTS
- else
- KASSERT(pt2_is_empty(m, va), ("%s: PT2 is not empty (%u)",
- __func__, pt2_wirecount_get(m, pte1_idx)));
-#endif
- if (pt2pg_is_empty(m)) {
- pmap_unwire_pt2pg(pmap, va, m);
- pmap_add_delayed_free_list(m, free);
- }
-}
-
-/*
- * After removing a L2 page table entry, this routine is used to
- * conditionally free the page, and manage the hold/wire counts.
- */
-static boolean_t
-pmap_unuse_pt2(pmap_t pmap, vm_offset_t va, struct spglist *free)
-{
- pt1_entry_t pte1;
- vm_page_t mpte;
-
- if (va >= VM_MAXUSER_ADDRESS)
- return (FALSE);
- pte1 = pte1_load(pmap_pte1(pmap, va));
- mpte = PHYS_TO_VM_PAGE(pte1_link_pa(pte1));
- return (pmap_unwire_pt2(pmap, va, mpte, free));
-}
-
-/*************************************
- *
- * Page management routines.
- *
- *************************************/
-
-CTASSERT(sizeof(struct pv_chunk) == PAGE_SIZE);
-CTASSERT(_NPCM == 11);
-CTASSERT(_NPCPV == 336);
-
-static __inline struct pv_chunk *
-pv_to_chunk(pv_entry_t pv)
-{
-
- return ((struct pv_chunk *)((uintptr_t)pv & ~(uintptr_t)PAGE_MASK));
-}
-
-#define PV_PMAP(pv) (pv_to_chunk(pv)->pc_pmap)
-
-#define PC_FREE0_9 0xfffffffful /* Free values for index 0 through 9 */
-#define PC_FREE10 0x0000fffful /* Free values for index 10 */
-
-static const uint32_t pc_freemask[_NPCM] = {
- PC_FREE0_9, PC_FREE0_9, PC_FREE0_9,
- PC_FREE0_9, PC_FREE0_9, PC_FREE0_9,
- PC_FREE0_9, PC_FREE0_9, PC_FREE0_9,
- PC_FREE0_9, PC_FREE10
-};
-
-SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_count, CTLFLAG_RD, &pv_entry_count, 0,
- "Current number of pv entries");
-
-#ifdef PV_STATS
-static int pc_chunk_count, pc_chunk_allocs, pc_chunk_frees, pc_chunk_tryfail;
-
-SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_count, CTLFLAG_RD, &pc_chunk_count, 0,
- "Current number of pv entry chunks");
-SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_allocs, CTLFLAG_RD, &pc_chunk_allocs, 0,
- "Current number of pv entry chunks allocated");
-SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_frees, CTLFLAG_RD, &pc_chunk_frees, 0,
- "Current number of pv entry chunks frees");
-SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_tryfail, CTLFLAG_RD, &pc_chunk_tryfail,
- 0, "Number of times tried to get a chunk page but failed.");
-
-static long pv_entry_frees, pv_entry_allocs;
-static int pv_entry_spare;
-
-SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_frees, CTLFLAG_RD, &pv_entry_frees, 0,
- "Current number of pv entry frees");
-SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_allocs, CTLFLAG_RD, &pv_entry_allocs,
- 0, "Current number of pv entry allocs");
-SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_spare, CTLFLAG_RD, &pv_entry_spare, 0,
- "Current number of spare pv entries");
-#endif
-
-/*
- * Is given page managed?
- */
-static __inline boolean_t
-is_managed(vm_paddr_t pa)
-{
- vm_offset_t pgnum;
- vm_page_t m;
-
- pgnum = atop(pa);
- if (pgnum >= first_page) {
- m = PHYS_TO_VM_PAGE(pa);
- if (m == NULL)
- return (FALSE);
- if ((m->oflags & VPO_UNMANAGED) == 0)
- return (TRUE);
- }
- return (FALSE);
-}
-
-static __inline boolean_t
-pte1_is_managed(pt1_entry_t pte1)
-{
-
- return (is_managed(pte1_pa(pte1)));
-}
-
-static __inline boolean_t
-pte2_is_managed(pt2_entry_t pte2)
-{
-
- return (is_managed(pte2_pa(pte2)));
-}
-
-/*
- * We are in a serious low memory condition. Resort to
- * drastic measures to free some pages so we can allocate
- * another pv entry chunk.
- */
-static vm_page_t
-pmap_pv_reclaim(pmap_t locked_pmap)
-{
- struct pch newtail;
- struct pv_chunk *pc;
- struct md_page *pvh;
- pt1_entry_t *pte1p;
- pmap_t pmap;
- pt2_entry_t *pte2p, tpte2;
- pv_entry_t pv;
- vm_offset_t va;
- vm_page_t m, m_pc;
- struct spglist free;
- uint32_t inuse;
- int bit, field, freed;
-
- PMAP_LOCK_ASSERT(locked_pmap, MA_OWNED);
- pmap = NULL;
- m_pc = NULL;
- SLIST_INIT(&free);
- TAILQ_INIT(&newtail);
- while ((pc = TAILQ_FIRST(&pv_chunks)) != NULL && (pv_vafree == 0 ||
- SLIST_EMPTY(&free))) {
- TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
- if (pmap != pc->pc_pmap) {
- if (pmap != NULL) {
- if (pmap != locked_pmap)
- PMAP_UNLOCK(pmap);
- }
- pmap = pc->pc_pmap;
- /* Avoid deadlock and lock recursion. */
- if (pmap > locked_pmap)
- PMAP_LOCK(pmap);
- else if (pmap != locked_pmap && !PMAP_TRYLOCK(pmap)) {
- pmap = NULL;
- TAILQ_INSERT_TAIL(&newtail, pc, pc_lru);
- continue;
- }
- }
-
- /*
- * Destroy every non-wired, 4 KB page mapping in the chunk.
- */
- freed = 0;
- for (field = 0; field < _NPCM; field++) {
- for (inuse = ~pc->pc_map[field] & pc_freemask[field];
- inuse != 0; inuse &= ~(1UL << bit)) {
- bit = ffs(inuse) - 1;
- pv = &pc->pc_pventry[field * 32 + bit];
- va = pv->pv_va;
- pte1p = pmap_pte1(pmap, va);
- if (pte1_is_section(pte1_load(pte1p)))
- continue;
- pte2p = pmap_pte2(pmap, va);
- tpte2 = pte2_load(pte2p);
- if ((tpte2 & PTE2_W) == 0)
- tpte2 = pte2_load_clear(pte2p);
- pmap_pte2_release(pte2p);
- if ((tpte2 & PTE2_W) != 0)
- continue;
- KASSERT(tpte2 != 0,
- ("pmap_pv_reclaim: pmap %p va %#x zero pte",
- pmap, va));
- pmap_tlb_flush(pmap, va);
- m = PHYS_TO_VM_PAGE(pte2_pa(tpte2));
- if (pte2_is_dirty(tpte2))
- vm_page_dirty(m);
- if ((tpte2 & PTE2_A) != 0)
- vm_page_aflag_set(m, PGA_REFERENCED);
- TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
- if (TAILQ_EMPTY(&m->md.pv_list) &&
- (m->flags & PG_FICTITIOUS) == 0) {
- pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
- if (TAILQ_EMPTY(&pvh->pv_list)) {
- vm_page_aflag_clear(m,
- PGA_WRITEABLE);
- }
- }
- pc->pc_map[field] |= 1UL << bit;
- pmap_unuse_pt2(pmap, va, &free);
- freed++;
- }
- }
- if (freed == 0) {
- TAILQ_INSERT_TAIL(&newtail, pc, pc_lru);
- continue;
- }
- /* Every freed mapping is for a 4 KB page. */
- pmap->pm_stats.resident_count -= freed;
- PV_STAT(pv_entry_frees += freed);
- PV_STAT(pv_entry_spare += freed);
- pv_entry_count -= freed;
- TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
- for (field = 0; field < _NPCM; field++)
- if (pc->pc_map[field] != pc_freemask[field]) {
- TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc,
- pc_list);
- TAILQ_INSERT_TAIL(&newtail, pc, pc_lru);
-
- /*
- * One freed pv entry in locked_pmap is
- * sufficient.
- */
- if (pmap == locked_pmap)
- goto out;
- break;
- }
- if (field == _NPCM) {
- PV_STAT(pv_entry_spare -= _NPCPV);
- PV_STAT(pc_chunk_count--);
- PV_STAT(pc_chunk_frees++);
- /* Entire chunk is free; return it. */
- m_pc = PHYS_TO_VM_PAGE(pmap_kextract((vm_offset_t)pc));
- pmap_qremove((vm_offset_t)pc, 1);
- pmap_pte2list_free(&pv_vafree, (vm_offset_t)pc);
- break;
- }
- }
-out:
- TAILQ_CONCAT(&pv_chunks, &newtail, pc_lru);
- if (pmap != NULL) {
- if (pmap != locked_pmap)
- PMAP_UNLOCK(pmap);
- }
- if (m_pc == NULL && pv_vafree != 0 && SLIST_EMPTY(&free)) {
- m_pc = SLIST_FIRST(&free);
- SLIST_REMOVE_HEAD(&free, plinks.s.ss);
- /* Recycle a freed page table page. */
- m_pc->wire_count = 1;
- atomic_add_int(&vm_cnt.v_wire_count, 1);
- }
- pmap_free_zero_pages(&free);
- return (m_pc);
-}
-
-static void
-free_pv_chunk(struct pv_chunk *pc)
-{
- vm_page_t m;
-
- TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
- PV_STAT(pv_entry_spare -= _NPCPV);
- PV_STAT(pc_chunk_count--);
- PV_STAT(pc_chunk_frees++);
- /* entire chunk is free, return it */
- m = PHYS_TO_VM_PAGE(pmap_kextract((vm_offset_t)pc));
- pmap_qremove((vm_offset_t)pc, 1);
- vm_page_unwire(m, PQ_NONE);
- vm_page_free(m);
- pmap_pte2list_free(&pv_vafree, (vm_offset_t)pc);
-}
-
-/*
- * Free the pv_entry back to the free list.
- */
-static void
-free_pv_entry(pmap_t pmap, pv_entry_t pv)
-{
- struct pv_chunk *pc;
- int idx, field, bit;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- PMAP_LOCK_ASSERT(pmap, MA_OWNED);
- PV_STAT(pv_entry_frees++);
- PV_STAT(pv_entry_spare++);
- pv_entry_count--;
- pc = pv_to_chunk(pv);
- idx = pv - &pc->pc_pventry[0];
- field = idx / 32;
- bit = idx % 32;
- pc->pc_map[field] |= 1ul << bit;
- for (idx = 0; idx < _NPCM; idx++)
- if (pc->pc_map[idx] != pc_freemask[idx]) {
- /*
- * 98% of the time, pc is already at the head of the
- * list. If it isn't already, move it to the head.
- */
- if (__predict_false(TAILQ_FIRST(&pmap->pm_pvchunk) !=
- pc)) {
- TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
- TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc,
- pc_list);
- }
- return;
- }
- TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
- free_pv_chunk(pc);
-}
-
-/*
- * Get a new pv_entry, allocating a block from the system
- * when needed.
- */
-static pv_entry_t
-get_pv_entry(pmap_t pmap, boolean_t try)
-{
- static const struct timeval printinterval = { 60, 0 };
- static struct timeval lastprint;
- int bit, field;
- pv_entry_t pv;
- struct pv_chunk *pc;
- vm_page_t m;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- PMAP_LOCK_ASSERT(pmap, MA_OWNED);
- PV_STAT(pv_entry_allocs++);
- pv_entry_count++;
- if (pv_entry_count > pv_entry_high_water)
- if (ratecheck(&lastprint, &printinterval))
- printf("Approaching the limit on PV entries, consider "
- "increasing either the vm.pmap.shpgperproc or the "
- "vm.pmap.pv_entry_max tunable.\n");
-retry:
- pc = TAILQ_FIRST(&pmap->pm_pvchunk);
- if (pc != NULL) {
- for (field = 0; field < _NPCM; field++) {
- if (pc->pc_map[field]) {
- bit = ffs(pc->pc_map[field]) - 1;
- break;
- }
- }
- if (field < _NPCM) {
- pv = &pc->pc_pventry[field * 32 + bit];
- pc->pc_map[field] &= ~(1ul << bit);
- /* If this was the last item, move it to tail */
- for (field = 0; field < _NPCM; field++)
- if (pc->pc_map[field] != 0) {
- PV_STAT(pv_entry_spare--);
- return (pv); /* not full, return */
- }
- TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
- TAILQ_INSERT_TAIL(&pmap->pm_pvchunk, pc, pc_list);
- PV_STAT(pv_entry_spare--);
- return (pv);
- }
- }
- /*
- * Access to the pte2list "pv_vafree" is synchronized by the pvh
- * global lock. If "pv_vafree" is currently non-empty, it will
- * remain non-empty until pmap_pte2list_alloc() completes.
- */
- if (pv_vafree == 0 || (m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL |
- VM_ALLOC_NOOBJ | VM_ALLOC_WIRED)) == NULL) {
- if (try) {
- pv_entry_count--;
- PV_STAT(pc_chunk_tryfail++);
- return (NULL);
- }
- m = pmap_pv_reclaim(pmap);
- if (m == NULL)
- goto retry;
- }
- PV_STAT(pc_chunk_count++);
- PV_STAT(pc_chunk_allocs++);
- pc = (struct pv_chunk *)pmap_pte2list_alloc(&pv_vafree);
- pmap_qenter((vm_offset_t)pc, &m, 1);
- pc->pc_pmap = pmap;
- pc->pc_map[0] = pc_freemask[0] & ~1ul; /* preallocated bit 0 */
- for (field = 1; field < _NPCM; field++)
- pc->pc_map[field] = pc_freemask[field];
- TAILQ_INSERT_TAIL(&pv_chunks, pc, pc_lru);
- pv = &pc->pc_pventry[0];
- TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list);
- PV_STAT(pv_entry_spare += _NPCPV - 1);
- return (pv);
-}
-
-/*
- * Create a pv entry for page at pa for
- * (pmap, va).
- */
-static void
-pmap_insert_entry(pmap_t pmap, vm_offset_t va, vm_page_t m)
-{
- pv_entry_t pv;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- PMAP_LOCK_ASSERT(pmap, MA_OWNED);
- pv = get_pv_entry(pmap, FALSE);
- pv->pv_va = va;
- TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
-}
-
-static __inline pv_entry_t
-pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va)
-{
- pv_entry_t pv;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
- if (pmap == PV_PMAP(pv) && va == pv->pv_va) {
- TAILQ_REMOVE(&pvh->pv_list, pv, pv_next);
- break;
- }
- }
- return (pv);
-}
-
-static void
-pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va)
-{
- pv_entry_t pv;
-
- pv = pmap_pvh_remove(pvh, pmap, va);
- KASSERT(pv != NULL, ("pmap_pvh_free: pv not found"));
- free_pv_entry(pmap, pv);
-}
-
-static void
-pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va)
-{
- struct md_page *pvh;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- pmap_pvh_free(&m->md, pmap, va);
- if (TAILQ_EMPTY(&m->md.pv_list) && (m->flags & PG_FICTITIOUS) == 0) {
- pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
- if (TAILQ_EMPTY(&pvh->pv_list))
- vm_page_aflag_clear(m, PGA_WRITEABLE);
- }
-}
-
-static void
-pmap_pv_demote_pte1(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
-{
- struct md_page *pvh;
- pv_entry_t pv;
- vm_offset_t va_last;
- vm_page_t m;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- KASSERT((pa & PTE1_OFFSET) == 0,
- ("pmap_pv_demote_pte1: pa is not 1mpage aligned"));
-
- /*
- * Transfer the 1mpage's pv entry for this mapping to the first
- * page's pv list.
- */
- pvh = pa_to_pvh(pa);
- va = pte1_trunc(va);
- pv = pmap_pvh_remove(pvh, pmap, va);
- KASSERT(pv != NULL, ("pmap_pv_demote_pte1: pv not found"));
- m = PHYS_TO_VM_PAGE(pa);
- TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
- /* Instantiate the remaining NPTE2_IN_PT2 - 1 pv entries. */
- va_last = va + PTE1_SIZE - PAGE_SIZE;
- do {
- m++;
- KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("pmap_pv_demote_pte1: page %p is not managed", m));
- va += PAGE_SIZE;
- pmap_insert_entry(pmap, va, m);
- } while (va < va_last);
-}
-
-static void
-pmap_pv_promote_pte1(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
-{
- struct md_page *pvh;
- pv_entry_t pv;
- vm_offset_t va_last;
- vm_page_t m;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- KASSERT((pa & PTE1_OFFSET) == 0,
- ("pmap_pv_promote_pte1: pa is not 1mpage aligned"));
-
- /*
- * Transfer the first page's pv entry for this mapping to the
- * 1mpage's pv list. Aside from avoiding the cost of a call
- * to get_pv_entry(), a transfer avoids the possibility that
- * get_pv_entry() calls pmap_pv_reclaim() and that pmap_pv_reclaim()
- * removes one of the mappings that is being promoted.
- */
- m = PHYS_TO_VM_PAGE(pa);
- va = pte1_trunc(va);
- pv = pmap_pvh_remove(&m->md, pmap, va);
- KASSERT(pv != NULL, ("pmap_pv_promote_pte1: pv not found"));
- pvh = pa_to_pvh(pa);
- TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next);
- /* Free the remaining NPTE2_IN_PT2 - 1 pv entries. */
- va_last = va + PTE1_SIZE - PAGE_SIZE;
- do {
- m++;
- va += PAGE_SIZE;
- pmap_pvh_free(&m->md, pmap, va);
- } while (va < va_last);
-}
-
-/*
- * Conditionally create a pv entry.
- */
-static boolean_t
-pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m)
-{
- pv_entry_t pv;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- PMAP_LOCK_ASSERT(pmap, MA_OWNED);
- if (pv_entry_count < pv_entry_high_water &&
- (pv = get_pv_entry(pmap, TRUE)) != NULL) {
- pv->pv_va = va;
- TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
- return (TRUE);
- } else
- return (FALSE);
-}
-
-/*
- * Create the pv entries for each of the pages within a section.
- */
-static boolean_t
-pmap_pv_insert_pte1(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
-{
- struct md_page *pvh;
- pv_entry_t pv;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- if (pv_entry_count < pv_entry_high_water &&
- (pv = get_pv_entry(pmap, TRUE)) != NULL) {
- pv->pv_va = va;
- pvh = pa_to_pvh(pa);
- TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next);
- return (TRUE);
- } else
- return (FALSE);
-}
-
-/*
- * Tries to promote the NPTE2_IN_PT2, contiguous 4KB page mappings that are
- * within a single page table page (PT2) to a single 1MB page mapping.
- * For promotion to occur, two conditions must be met: (1) the 4KB page
- * mappings must map aligned, contiguous physical memory and (2) the 4KB page
- * mappings must have identical characteristics.
- *
- * Managed (PG_MANAGED) mappings within the kernel address space are not
- * promoted. The reason is that kernel PTE1s are replicated in each pmap but
- * pmap_remove_write(), pmap_clear_modify(), and pmap_clear_reference() only
- * read the PTE1 from the kernel pmap.
- */
-static void
-pmap_promote_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t va)
-{
- pt1_entry_t npte1;
- pt2_entry_t *fpte2p, fpte2, fpte2_fav;
- pt2_entry_t *pte2p, pte2;
- vm_offset_t pteva __unused;
- vm_page_t m __unused;
-
- PDEBUG(6, printf("%s(%p): try for va %#x pte1 %#x at %p\n", __func__,
- pmap, va, pte1_load(pte1p), pte1p));
-
- PMAP_LOCK_ASSERT(pmap, MA_OWNED);
-
- /*
- * Examine the first PTE2 in the specified PT2. Abort if this PTE2 is
- * either invalid, unused, or does not map the first 4KB physical page
- * within a 1MB page.
- */
- fpte2p = pmap_pte2_quick(pmap, pte1_trunc(va));
-setpte1:
- fpte2 = pte2_load(fpte2p);
- if ((fpte2 & ((PTE2_FRAME & PTE1_OFFSET) | PTE2_A | PTE2_V)) !=
- (PTE2_A | PTE2_V)) {
- pmap_pte1_p_failures++;
- CTR3(KTR_PMAP, "%s: failure(1) for va %#x in pmap %p",
- __func__, va, pmap);
- return;
- }
- if (pte2_is_managed(fpte2) && pmap == kernel_pmap) {
- pmap_pte1_p_failures++;
- CTR3(KTR_PMAP, "%s: failure(2) for va %#x in pmap %p",
- __func__, va, pmap);
- return;
- }
- if ((fpte2 & (PTE2_NM | PTE2_RO)) == PTE2_NM) {
- /*
- * When page is not modified, PTE2_RO can be set without
- * a TLB invalidation.
- *
- * Note: When modified bit is being set, then in hardware case,
- * the TLB entry is re-read (updated) from PT2, and in
- * software case (abort), the PTE2 is read from PT2 and
- * TLB flushed if changed. The following cmpset() solves
- * any race with setting this bit in both cases.
- */
- if (!pte2_cmpset(fpte2p, fpte2, fpte2 | PTE2_RO))
- goto setpte1;
- fpte2 |= PTE2_RO;
- }
-
- /*
- * Examine each of the other PTE2s in the specified PT2. Abort if this
- * PTE2 maps an unexpected 4KB physical page or does not have identical
- * characteristics to the first PTE2.
- */
- fpte2_fav = (fpte2 & (PTE2_FRAME | PTE2_A | PTE2_V));
- fpte2_fav += PTE1_SIZE - PTE2_SIZE; /* examine from the end */
- for (pte2p = fpte2p + NPTE2_IN_PT2 - 1; pte2p > fpte2p; pte2p--) {
-setpte2:
- pte2 = pte2_load(pte2p);
- if ((pte2 & (PTE2_FRAME | PTE2_A | PTE2_V)) != fpte2_fav) {
- pmap_pte1_p_failures++;
- CTR3(KTR_PMAP, "%s: failure(3) for va %#x in pmap %p",
- __func__, va, pmap);
- return;
- }
- if ((pte2 & (PTE2_NM | PTE2_RO)) == PTE2_NM) {
- /*
- * When page is not modified, PTE2_RO can be set
- * without a TLB invalidation. See note above.
- */
- if (!pte2_cmpset(pte2p, pte2, pte2 | PTE2_RO))
- goto setpte2;
- pte2 |= PTE2_RO;
- pteva = pte1_trunc(va) | (pte2 & PTE1_OFFSET &
- PTE2_FRAME);
- CTR3(KTR_PMAP, "%s: protect for va %#x in pmap %p",
- __func__, pteva, pmap);
- }
- if ((pte2 & PTE2_PROMOTE) != (fpte2 & PTE2_PROMOTE)) {
- pmap_pte1_p_failures++;
- CTR3(KTR_PMAP, "%s: failure(4) for va %#x in pmap %p",
- __func__, va, pmap);
- return;
- }
-
- fpte2_fav -= PTE2_SIZE;
- }
- /*
- * The page table page in its current state will stay in PT2TAB
- * until the PTE1 mapping the section is demoted by pmap_demote_pte1()
- * or destroyed by pmap_remove_pte1().
- *
- * Note that L2 page table size is not equal to PAGE_SIZE.
- */
- m = PHYS_TO_VM_PAGE(trunc_page(pte1_link_pa(pte1_load(pte1p))));
- KASSERT(m >= vm_page_array && m < &vm_page_array[vm_page_array_size],
- ("%s: PT2 page is out of range", __func__));
- KASSERT(m->pindex == (pte1_index(va) & ~PT2PG_MASK),
- ("%s: PT2 page's pindex is wrong", __func__));
-
- /*
- * Get pte1 from pte2 format.
- */
- npte1 = (fpte2 & PTE1_FRAME) | ATTR_TO_L1(fpte2) | PTE1_V;
-
- /*
- * Promote the pv entries.
- */
- if (pte2_is_managed(fpte2))
- pmap_pv_promote_pte1(pmap, va, pte1_pa(npte1));
-
- /*
- * Map the section.
- */
- if (pmap == kernel_pmap)
- pmap_kenter_pte1(va, npte1);
- else
- pte1_store(pte1p, npte1);
- /*
- * Flush old small mappings. We call single pmap_tlb_flush() in
- * pmap_demote_pte1() and pmap_remove_pte1(), so we must be sure that
- * no small mappings survive. We assume that given pmap is current and
- * don't play game with PTE2_NG.
- */
- pmap_tlb_flush_range(pmap, pte1_trunc(va), PTE1_SIZE);
-
- pmap_pte1_promotions++;
- CTR3(KTR_PMAP, "%s: success for va %#x in pmap %p",
- __func__, va, pmap);
-
- PDEBUG(6, printf("%s(%p): success for va %#x pte1 %#x(%#x) at %p\n",
- __func__, pmap, va, npte1, pte1_load(pte1p), pte1p));
-}
-
-/*
- * Zero L2 page table page.
- */
-static __inline void
-pmap_clear_pt2(pt2_entry_t *fpte2p)
-{
- pt2_entry_t *pte2p;
-
- for (pte2p = fpte2p; pte2p < fpte2p + NPTE2_IN_PT2; pte2p++)
- pte2_clear(pte2p);
-
-}
-
-/*
- * Removes a 1MB page mapping from the kernel pmap.
- */
-static void
-pmap_remove_kernel_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t va)
-{
- vm_page_t m;
- uint32_t pte1_idx;
- pt2_entry_t *fpte2p;
- vm_paddr_t pt2_pa;
-
- PMAP_LOCK_ASSERT(pmap, MA_OWNED);
- m = pmap_pt2_page(pmap, va);
- if (m == NULL)
- /*
- * QQQ: Is this function called only on promoted pte1?
- * We certainly do section mappings directly
- * (without promotion) in kernel !!!
- */
- panic("%s: missing pt2 page", __func__);
-
- pte1_idx = pte1_index(va);
-
- /*
- * Initialize the L2 page table.
- */
- fpte2p = page_pt2(pt2map_pt2pg(va), pte1_idx);
- pmap_clear_pt2(fpte2p);
-
- /*
- * Remove the mapping.
- */
- pt2_pa = page_pt2pa(VM_PAGE_TO_PHYS(m), pte1_idx);
- pmap_kenter_pte1(va, PTE1_LINK(pt2_pa));
-
- /*
- * QQQ: We do not need to invalidate PT2MAP mapping
- * as we did not change it. I.e. the L2 page table page
- * was and still is mapped the same way.
- */
-}
-
-/*
- * Do the things to unmap a section in a process
- */
-static void
-pmap_remove_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t sva,
- struct spglist *free)
-{
- pt1_entry_t opte1;
- struct md_page *pvh;
- vm_offset_t eva, va;
- vm_page_t m;
-
- PDEBUG(6, printf("%s(%p): va %#x pte1 %#x at %p\n", __func__, pmap, sva,
- pte1_load(pte1p), pte1p));
-
- PMAP_LOCK_ASSERT(pmap, MA_OWNED);
- KASSERT((sva & PTE1_OFFSET) == 0,
- ("%s: sva is not 1mpage aligned", __func__));
-
- /*
- * Clear and invalidate the mapping. It should occupy one and only TLB
- * entry. So, pmap_tlb_flush() called with aligned address should be
- * sufficient.
- */
- opte1 = pte1_load_clear(pte1p);
- pmap_tlb_flush(pmap, sva);
-
- if (pte1_is_wired(opte1))
- pmap->pm_stats.wired_count -= PTE1_SIZE / PAGE_SIZE;
- pmap->pm_stats.resident_count -= PTE1_SIZE / PAGE_SIZE;
- if (pte1_is_managed(opte1)) {
- pvh = pa_to_pvh(pte1_pa(opte1));
- pmap_pvh_free(pvh, pmap, sva);
- eva = sva + PTE1_SIZE;
- for (va = sva, m = PHYS_TO_VM_PAGE(pte1_pa(opte1));
- va < eva; va += PAGE_SIZE, m++) {
- if (pte1_is_dirty(opte1))
- vm_page_dirty(m);
- if (opte1 & PTE1_A)
- vm_page_aflag_set(m, PGA_REFERENCED);
- if (TAILQ_EMPTY(&m->md.pv_list) &&
- TAILQ_EMPTY(&pvh->pv_list))
- vm_page_aflag_clear(m, PGA_WRITEABLE);
- }
- }
- if (pmap == kernel_pmap) {
- /*
- * L2 page table(s) can't be removed from kernel map as
- * kernel counts on it (stuff around pmap_growkernel()).
- */
- pmap_remove_kernel_pte1(pmap, pte1p, sva);
- } else {
- /*
- * Get associated L2 page table page.
- * It's possible that the page was never allocated.
- */
- m = pmap_pt2_page(pmap, sva);
- if (m != NULL)
- pmap_unwire_pt2_all(pmap, sva, m, free);
- }
-}
-
-/*
- * Fills L2 page table page with mappings to consecutive physical pages.
- */
-static __inline void
-pmap_fill_pt2(pt2_entry_t *fpte2p, pt2_entry_t npte2)
-{
- pt2_entry_t *pte2p;
-
- for (pte2p = fpte2p; pte2p < fpte2p + NPTE2_IN_PT2; pte2p++) {
- pte2_store(pte2p, npte2);
- npte2 += PTE2_SIZE;
- }
-}
-
-/*
- * Tries to demote a 1MB page mapping. If demotion fails, the
- * 1MB page mapping is invalidated.
- */
-static boolean_t
-pmap_demote_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t va)
-{
- pt1_entry_t opte1, npte1;
- pt2_entry_t *fpte2p, npte2;
- vm_paddr_t pt2pg_pa, pt2_pa;
- vm_page_t m;
- struct spglist free;
- uint32_t pte1_idx, isnew = 0;
-
- PDEBUG(6, printf("%s(%p): try for va %#x pte1 %#x at %p\n", __func__,
- pmap, va, pte1_load(pte1p), pte1p));
-
- PMAP_LOCK_ASSERT(pmap, MA_OWNED);
-
- opte1 = pte1_load(pte1p);
- KASSERT(pte1_is_section(opte1), ("%s: opte1 not a section", __func__));
-
- if ((opte1 & PTE1_A) == 0 || (m = pmap_pt2_page(pmap, va)) == NULL) {
- KASSERT(!pte1_is_wired(opte1),
- ("%s: PT2 page for a wired mapping is missing", __func__));
-
- /*
- * Invalidate the 1MB page mapping and return
- * "failure" if the mapping was never accessed or the
- * allocation of the new page table page fails.
- */
- if ((opte1 & PTE1_A) == 0 || (m = vm_page_alloc(NULL,
- pte1_index(va) & ~PT2PG_MASK, VM_ALLOC_NOOBJ |
- VM_ALLOC_NORMAL | VM_ALLOC_WIRED)) == NULL) {
- SLIST_INIT(&free);
- pmap_remove_pte1(pmap, pte1p, pte1_trunc(va), &free);
- pmap_free_zero_pages(&free);
- CTR3(KTR_PMAP, "%s: failure for va %#x in pmap %p",
- __func__, va, pmap);
- return (FALSE);
- }
- if (va < VM_MAXUSER_ADDRESS)
- pmap->pm_stats.resident_count++;
-
- isnew = 1;
-
- /*
- * We init all L2 page tables in the page even if
- * we are going to change everything for one L2 page
- * table in a while.
- */
- pt2pg_pa = pmap_pt2pg_init(pmap, va, m);
- } else {
- if (va < VM_MAXUSER_ADDRESS) {
- if (pt2_is_empty(m, va))
- isnew = 1; /* Demoting section w/o promotion. */
-#ifdef INVARIANTS
- else
- KASSERT(pt2_is_full(m, va), ("%s: bad PT2 wire"
- " count %u", __func__,
- pt2_wirecount_get(m, pte1_index(va))));
-#endif
- }
- }
-
- pt2pg_pa = VM_PAGE_TO_PHYS(m);
- pte1_idx = pte1_index(va);
- /*
- * If the pmap is current, then the PT2MAP can provide access to
- * the page table page (promoted L2 page tables are not unmapped).
- * Otherwise, temporarily map the L2 page table page (m) into
- * the kernel's address space at either PADDR1 or PADDR2.
- *
- * Note that L2 page table size is not equal to PAGE_SIZE.
- */
- if (pmap_is_current(pmap))
- fpte2p = page_pt2(pt2map_pt2pg(va), pte1_idx);
- else if (curthread->td_pinned > 0 && rw_wowned(&pvh_global_lock)) {
- if (pte2_pa(pte2_load(PMAP1)) != pt2pg_pa) {
- pte2_store(PMAP1, PTE2_KPT(pt2pg_pa));
-#ifdef SMP
- PMAP1cpu = PCPU_GET(cpuid);
-#endif
- tlb_flush_local((vm_offset_t)PADDR1);
- PMAP1changed++;
- } else
-#ifdef SMP
- if (PMAP1cpu != PCPU_GET(cpuid)) {
- PMAP1cpu = PCPU_GET(cpuid);
- tlb_flush_local((vm_offset_t)PADDR1);
- PMAP1changedcpu++;
- } else
-#endif
- PMAP1unchanged++;
- fpte2p = page_pt2((vm_offset_t)PADDR1, pte1_idx);
- } else {
- mtx_lock(&PMAP2mutex);
- if (pte2_pa(pte2_load(PMAP2)) != pt2pg_pa) {
- pte2_store(PMAP2, PTE2_KPT(pt2pg_pa));
- tlb_flush((vm_offset_t)PADDR2);
- }
- fpte2p = page_pt2((vm_offset_t)PADDR2, pte1_idx);
- }
- pt2_pa = page_pt2pa(pt2pg_pa, pte1_idx);
- npte1 = PTE1_LINK(pt2_pa);
-
- KASSERT((opte1 & PTE1_A) != 0,
- ("%s: opte1 is missing PTE1_A", __func__));
- KASSERT((opte1 & (PTE1_NM | PTE1_RO)) != PTE1_NM,
- ("%s: opte1 has PTE1_NM", __func__));
-
- /*
- * Get pte2 from pte1 format.
- */
- npte2 = pte1_pa(opte1) | ATTR_TO_L2(opte1) | PTE2_V;
-
- /*
- * If the L2 page table page is new, initialize it. If the mapping
- * has changed attributes, update the page table entries.
- */
- if (isnew != 0) {
- pt2_wirecount_set(m, pte1_idx, NPTE2_IN_PT2);
- pmap_fill_pt2(fpte2p, npte2);
- } else if ((pte2_load(fpte2p) & PTE2_PROMOTE) !=
- (npte2 & PTE2_PROMOTE))
- pmap_fill_pt2(fpte2p, npte2);
-
- KASSERT(pte2_pa(pte2_load(fpte2p)) == pte2_pa(npte2),
- ("%s: fpte2p and npte2 map different physical addresses",
- __func__));
-
- if (fpte2p == PADDR2)
- mtx_unlock(&PMAP2mutex);
-
- /*
- * Demote the mapping. This pmap is locked. The old PTE1 has
- * PTE1_A set. If the old PTE1 has not PTE1_RO set, it also
- * has not PTE1_NM set. Thus, there is no danger of a race with
- * another processor changing the setting of PTE1_A and/or PTE1_NM
- * between the read above and the store below.
- */
- if (pmap == kernel_pmap)
- pmap_kenter_pte1(va, npte1);
- else
- pte1_store(pte1p, npte1);
-
- /*
- * Flush old big mapping. The mapping should occupy one and only
- * TLB entry. So, pmap_tlb_flush() called with aligned address
- * should be sufficient.
- */
- pmap_tlb_flush(pmap, pte1_trunc(va));
-
- /*
- * Demote the pv entry. This depends on the earlier demotion
- * of the mapping. Specifically, the (re)creation of a per-
- * page pv entry might trigger the execution of pmap_pv_reclaim(),
- * which might reclaim a newly (re)created per-page pv entry
- * and destroy the associated mapping. In order to destroy
- * the mapping, the PTE1 must have already changed from mapping
- * the 1mpage to referencing the page table page.
- */
- if (pte1_is_managed(opte1))
- pmap_pv_demote_pte1(pmap, va, pte1_pa(opte1));
-
- pmap_pte1_demotions++;
- CTR3(KTR_PMAP, "%s: success for va %#x in pmap %p",
- __func__, va, pmap);
-
- PDEBUG(6, printf("%s(%p): success for va %#x pte1 %#x(%#x) at %p\n",
- __func__, pmap, va, npte1, pte1_load(pte1p), pte1p));
- return (TRUE);
-}
-
-/*
- * Insert the given physical page (p) at
- * the specified virtual address (v) in the
- * target physical map with the protection requested.
- *
- * If specified, the page will be wired down, meaning
- * that the related pte can not be reclaimed.
- *
- * NB: This is the only routine which MAY NOT lazy-evaluate
- * or lose information. That is, this routine must actually
- * insert this page into the given map NOW.
- */
-int
-pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
- u_int flags, int8_t psind)
-{
- pt1_entry_t *pte1p;
- pt2_entry_t *pte2p;
- pt2_entry_t npte2, opte2;
- pv_entry_t pv;
- vm_paddr_t opa, pa;
- vm_page_t mpte2, om;
- boolean_t wired;
-
- va = trunc_page(va);
- mpte2 = NULL;
- wired = (flags & PMAP_ENTER_WIRED) != 0;
-
- KASSERT(va <= vm_max_kernel_address, ("%s: toobig", __func__));
- KASSERT(va < UPT2V_MIN_ADDRESS || va >= UPT2V_MAX_ADDRESS,
- ("%s: invalid to pmap_enter page table pages (va: 0x%x)", __func__,
- va));
- if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m))
- VM_OBJECT_ASSERT_LOCKED(m->object);
-
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
- sched_pin();
-
- /*
- * In the case that a page table page is not
- * resident, we are creating it here.
- */
- if (va < VM_MAXUSER_ADDRESS) {
- mpte2 = pmap_allocpte2(pmap, va, flags);
- if (mpte2 == NULL) {
- KASSERT((flags & PMAP_ENTER_NOSLEEP) != 0,
- ("pmap_allocpte2 failed with sleep allowed"));
- sched_unpin();
- rw_wunlock(&pvh_global_lock);
- PMAP_UNLOCK(pmap);
- return (KERN_RESOURCE_SHORTAGE);
- }
- }
- pte1p = pmap_pte1(pmap, va);
- if (pte1_is_section(pte1_load(pte1p)))
- panic("%s: attempted on 1MB page", __func__);
- pte2p = pmap_pte2_quick(pmap, va);
- if (pte2p == NULL)
- panic("%s: invalid L1 page table entry va=%#x", __func__, va);
-
- om = NULL;
- pa = VM_PAGE_TO_PHYS(m);
- opte2 = pte2_load(pte2p);
- opa = pte2_pa(opte2);
- /*
- * Mapping has not changed, must be protection or wiring change.
- */
- if (pte2_is_valid(opte2) && (opa == pa)) {
- /*
- * Wiring change, just update stats. We don't worry about
- * wiring PT2 pages as they remain resident as long as there
- * are valid mappings in them. Hence, if a user page is wired,
- * the PT2 page will be also.
- */
- if (wired && !pte2_is_wired(opte2))
- pmap->pm_stats.wired_count++;
- else if (!wired && pte2_is_wired(opte2))
- pmap->pm_stats.wired_count--;
-
- /*
- * Remove extra pte2 reference
- */
- if (mpte2)
- pt2_wirecount_dec(mpte2, pte1_index(va));
- if (pte2_is_managed(opte2))
- om = m;
- goto validate;
- }
-
- /*
- * QQQ: We think that changing physical address on writeable mapping
- * is not safe. Well, maybe on kernel address space with correct
- * locking, it can make a sense. However, we have no idea why
- * anyone should do that on user address space. Are we wrong?
- */
- KASSERT((opa == 0) || (opa == pa) ||
- !pte2_is_valid(opte2) || ((opte2 & PTE2_RO) != 0),
- ("%s: pmap %p va %#x(%#x) opa %#x pa %#x - gotcha %#x %#x!",
- __func__, pmap, va, opte2, opa, pa, flags, prot));
-
- pv = NULL;
-
- /*
- * Mapping has changed, invalidate old range and fall through to
- * handle validating new mapping.
- */
- if (opa) {
- if (pte2_is_wired(opte2))
- pmap->pm_stats.wired_count--;
- if (pte2_is_managed(opte2)) {
- om = PHYS_TO_VM_PAGE(opa);
- pv = pmap_pvh_remove(&om->md, pmap, va);
- }
- /*
- * Remove extra pte2 reference
- */
- if (mpte2 != NULL)
- pt2_wirecount_dec(mpte2, va >> PTE1_SHIFT);
- } else
- pmap->pm_stats.resident_count++;
-
- /*
- * Enter on the PV list if part of our managed memory.
- */
- if ((m->oflags & VPO_UNMANAGED) == 0) {
- KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
- ("%s: managed mapping within the clean submap", __func__));
- if (pv == NULL)
- pv = get_pv_entry(pmap, FALSE);
- pv->pv_va = va;
- TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
- } else if (pv != NULL)
- free_pv_entry(pmap, pv);
-
- /*
- * Increment counters
- */
- if (wired)
- pmap->pm_stats.wired_count++;
-
-validate:
- /*
- * Now validate mapping with desired protection/wiring.
- */
- npte2 = PTE2(pa, PTE2_NM, m->md.pat_mode);
- if (prot & VM_PROT_WRITE) {
- if (pte2_is_managed(npte2))
- vm_page_aflag_set(m, PGA_WRITEABLE);
- }
- else
- npte2 |= PTE2_RO;
- if ((prot & VM_PROT_EXECUTE) == 0)
- npte2 |= PTE2_NX;
- if (wired)
- npte2 |= PTE2_W;
- if (va < VM_MAXUSER_ADDRESS)
- npte2 |= PTE2_U;
- if (pmap != kernel_pmap)
- npte2 |= PTE2_NG;
-
- /*
- * If the mapping or permission bits are different, we need
- * to update the pte2.
- *
- * QQQ: Think again and again what to do
- * if the mapping is going to be changed!
- */
- if ((opte2 & ~(PTE2_NM | PTE2_A)) != (npte2 & ~(PTE2_NM | PTE2_A))) {
- /*
- * Sync icache if exec permission and attribute PTE2_ATTR_WB_WA
- * is set. Do it now, before the mapping is stored and made
- * valid for hardware table walk. If done later, there is a race
- * for other threads of current process in lazy loading case.
- * Don't do it for kernel memory which is mapped with exec
- * permission even if the memory isn't going to hold executable
- * code. The only time when icache sync is needed is after
- * kernel module is loaded and the relocation info is processed.
- * And it's done in elf_cpu_load_file().
- *
- * QQQ: (1) Does it exist any better way where
- * or how to sync icache?
- * (2) Now, we do it on a page basis.
- */
- if ((prot & VM_PROT_EXECUTE) && pmap != kernel_pmap &&
- m->md.pat_mode == PTE2_ATTR_WB_WA &&
- (opa != pa || (opte2 & PTE2_NX)))
- cache_icache_sync_fresh(va, pa, PAGE_SIZE);
-
- npte2 |= PTE2_A;
- if (flags & VM_PROT_WRITE)
- npte2 &= ~PTE2_NM;
- if (opte2 & PTE2_V) {
- /* Change mapping with break-before-make approach. */
- opte2 = pte2_load_clear(pte2p);
- pmap_tlb_flush(pmap, va);
- pte2_store(pte2p, npte2);
- if (opte2 & PTE2_A) {
- if (pte2_is_managed(opte2))
- vm_page_aflag_set(om, PGA_REFERENCED);
- }
- if (pte2_is_dirty(opte2)) {
- if (pte2_is_managed(opte2))
- vm_page_dirty(om);
- }
- if (pte2_is_managed(opte2) &&
- TAILQ_EMPTY(&om->md.pv_list) &&
- ((om->flags & PG_FICTITIOUS) != 0 ||
- TAILQ_EMPTY(&pa_to_pvh(opa)->pv_list)))
- vm_page_aflag_clear(om, PGA_WRITEABLE);
- } else
- pte2_store(pte2p, npte2);
- }
-#if 0
- else {
- /*
- * QQQ: In time when both access and not mofified bits are
- * emulated by software, this should not happen. Some
- * analysis is need, if this really happen. Missing
- * tlb flush somewhere could be the reason.
- */
- panic("%s: pmap %p va %#x opte2 %x npte2 %x !!", __func__, pmap,
- va, opte2, npte2);
- }
-#endif
- /*
- * If both the L2 page table page and the reservation are fully
- * populated, then attempt promotion.
- */
- if ((mpte2 == NULL || pt2_is_full(mpte2, va)) &&
- sp_enabled && (m->flags & PG_FICTITIOUS) == 0 &&
- vm_reserv_level_iffullpop(m) == 0)
- pmap_promote_pte1(pmap, pte1p, va);
- sched_unpin();
- rw_wunlock(&pvh_global_lock);
- PMAP_UNLOCK(pmap);
- return (KERN_SUCCESS);
-}
-
-/*
- * Do the things to unmap a page in a process.
- */
-static int
-pmap_remove_pte2(pmap_t pmap, pt2_entry_t *pte2p, vm_offset_t va,
- struct spglist *free)
-{
- pt2_entry_t opte2;
- vm_page_t m;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- PMAP_LOCK_ASSERT(pmap, MA_OWNED);
-
- /* Clear and invalidate the mapping. */
- opte2 = pte2_load_clear(pte2p);
- pmap_tlb_flush(pmap, va);
-
- KASSERT(pte2_is_valid(opte2), ("%s: pmap %p va %#x not link pte2 %#x",
- __func__, pmap, va, opte2));
-
- if (opte2 & PTE2_W)
- pmap->pm_stats.wired_count -= 1;
- pmap->pm_stats.resident_count -= 1;
- if (pte2_is_managed(opte2)) {
- m = PHYS_TO_VM_PAGE(pte2_pa(opte2));
- if (pte2_is_dirty(opte2))
- vm_page_dirty(m);
- if (opte2 & PTE2_A)
- vm_page_aflag_set(m, PGA_REFERENCED);
- pmap_remove_entry(pmap, m, va);
- }
- return (pmap_unuse_pt2(pmap, va, free));
-}
-
-/*
- * Remove a single page from a process address space.
- */
-static void
-pmap_remove_page(pmap_t pmap, vm_offset_t va, struct spglist *free)
-{
- pt2_entry_t *pte2p;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- KASSERT(curthread->td_pinned > 0,
- ("%s: curthread not pinned", __func__));
- PMAP_LOCK_ASSERT(pmap, MA_OWNED);
- if ((pte2p = pmap_pte2_quick(pmap, va)) == NULL ||
- !pte2_is_valid(pte2_load(pte2p)))
- return;
- pmap_remove_pte2(pmap, pte2p, va, free);
-}
-
-/*
- * Remove the given range of addresses from the specified map.
- *
- * It is assumed that the start and end are properly
- * rounded to the page size.
- */
-void
-pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
-{
- vm_offset_t nextva;
- pt1_entry_t *pte1p, pte1;
- pt2_entry_t *pte2p, pte2;
- struct spglist free;
-
- /*
- * Perform an unsynchronized read. This is, however, safe.
- */
- if (pmap->pm_stats.resident_count == 0)
- return;
-
- SLIST_INIT(&free);
-
- rw_wlock(&pvh_global_lock);
- sched_pin();
- PMAP_LOCK(pmap);
-
- /*
- * Special handling of removing one page. A very common
- * operation and easy to short circuit some code.
- */
- if (sva + PAGE_SIZE == eva) {
- pte1 = pte1_load(pmap_pte1(pmap, sva));
- if (pte1_is_link(pte1)) {
- pmap_remove_page(pmap, sva, &free);
- goto out;
- }
- }
-
- for (; sva < eva; sva = nextva) {
- /*
- * Calculate address for next L2 page table.
- */
- nextva = pte1_trunc(sva + PTE1_SIZE);
- if (nextva < sva)
- nextva = eva;
- if (pmap->pm_stats.resident_count == 0)
- break;
-
- pte1p = pmap_pte1(pmap, sva);
- pte1 = pte1_load(pte1p);
-
- /*
- * Weed out invalid mappings. Note: we assume that the L1 page
- * table is always allocated, and in kernel virtual.
- */
- if (pte1 == 0)
- continue;
-
- if (pte1_is_section(pte1)) {
- /*
- * Are we removing the entire large page? If not,
- * demote the mapping and fall through.
- */
- if (sva + PTE1_SIZE == nextva && eva >= nextva) {
- pmap_remove_pte1(pmap, pte1p, sva, &free);
- continue;
- } else if (!pmap_demote_pte1(pmap, pte1p, sva)) {
- /* The large page mapping was destroyed. */
- continue;
- }
-#ifdef INVARIANTS
- else {
- /* Update pte1 after demotion. */
- pte1 = pte1_load(pte1p);
- }
-#endif
- }
-
- KASSERT(pte1_is_link(pte1), ("%s: pmap %p va %#x pte1 %#x at %p"
- " is not link", __func__, pmap, sva, pte1, pte1p));
-
- /*
- * Limit our scan to either the end of the va represented
- * by the current L2 page table page, or to the end of the
- * range being removed.
- */
- if (nextva > eva)
- nextva = eva;
-
- for (pte2p = pmap_pte2_quick(pmap, sva); sva != nextva;
- pte2p++, sva += PAGE_SIZE) {
- pte2 = pte2_load(pte2p);
- if (!pte2_is_valid(pte2))
- continue;
- if (pmap_remove_pte2(pmap, pte2p, sva, &free))
- break;
- }
- }
-out:
- sched_unpin();
- rw_wunlock(&pvh_global_lock);
- PMAP_UNLOCK(pmap);
- pmap_free_zero_pages(&free);
-}
-
-/*
- * Routine: pmap_remove_all
- * Function:
- * Removes this physical page from
- * all physical maps in which it resides.
- * Reflects back modify bits to the pager.
- *
- * Notes:
- * Original versions of this routine were very
- * inefficient because they iteratively called
- * pmap_remove (slow...)
- */
-
-void
-pmap_remove_all(vm_page_t m)
-{
- struct md_page *pvh;
- pv_entry_t pv;
- pmap_t pmap;
- pt2_entry_t *pte2p, opte2;
- pt1_entry_t *pte1p;
- vm_offset_t va;
- struct spglist free;
-
- KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("%s: page %p is not managed", __func__, m));
- SLIST_INIT(&free);
- rw_wlock(&pvh_global_lock);
- sched_pin();
- if ((m->flags & PG_FICTITIOUS) != 0)
- goto small_mappings;
- pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
- while ((pv = TAILQ_FIRST(&pvh->pv_list)) != NULL) {
- va = pv->pv_va;
- pmap = PV_PMAP(pv);
- PMAP_LOCK(pmap);
- pte1p = pmap_pte1(pmap, va);
- (void)pmap_demote_pte1(pmap, pte1p, va);
- PMAP_UNLOCK(pmap);
- }
-small_mappings:
- while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
- pmap = PV_PMAP(pv);
- PMAP_LOCK(pmap);
- pmap->pm_stats.resident_count--;
- pte1p = pmap_pte1(pmap, pv->pv_va);
- KASSERT(!pte1_is_section(pte1_load(pte1p)), ("%s: found "
- "a 1mpage in page %p's pv list", __func__, m));
- pte2p = pmap_pte2_quick(pmap, pv->pv_va);
- opte2 = pte2_load_clear(pte2p);
- pmap_tlb_flush(pmap, pv->pv_va);
- KASSERT(pte2_is_valid(opte2), ("%s: pmap %p va %x zero pte2",
- __func__, pmap, pv->pv_va));
- if (pte2_is_wired(opte2))
- pmap->pm_stats.wired_count--;
- if (opte2 & PTE2_A)
- vm_page_aflag_set(m, PGA_REFERENCED);
-
- /*
- * Update the vm_page_t clean and reference bits.
- */
- if (pte2_is_dirty(opte2))
- vm_page_dirty(m);
- pmap_unuse_pt2(pmap, pv->pv_va, &free);
- TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
- free_pv_entry(pmap, pv);
- PMAP_UNLOCK(pmap);
- }
- vm_page_aflag_clear(m, PGA_WRITEABLE);
- sched_unpin();
- rw_wunlock(&pvh_global_lock);
- pmap_free_zero_pages(&free);
-}
-
-/*
- * Just subroutine for pmap_remove_pages() to reasonably satisfy
- * good coding style, a.k.a. 80 character line width limit hell.
- */
-static __inline void
-pmap_remove_pte1_quick(pmap_t pmap, pt1_entry_t pte1, pv_entry_t pv,
- struct spglist *free)
-{
- vm_paddr_t pa;
- vm_page_t m, mt, mpt2pg;
- struct md_page *pvh;
-
- pa = pte1_pa(pte1);
- m = PHYS_TO_VM_PAGE(pa);
-
- KASSERT(m->phys_addr == pa, ("%s: vm_page_t %p addr mismatch %#x %#x",
- __func__, m, m->phys_addr, pa));
- KASSERT((m->flags & PG_FICTITIOUS) != 0 ||
- m < &vm_page_array[vm_page_array_size],
- ("%s: bad pte1 %#x", __func__, pte1));
-
- if (pte1_is_dirty(pte1)) {
- for (mt = m; mt < &m[PTE1_SIZE / PAGE_SIZE]; mt++)
- vm_page_dirty(mt);
- }
-
- pmap->pm_stats.resident_count -= PTE1_SIZE / PAGE_SIZE;
- pvh = pa_to_pvh(pa);
- TAILQ_REMOVE(&pvh->pv_list, pv, pv_next);
- if (TAILQ_EMPTY(&pvh->pv_list)) {
- for (mt = m; mt < &m[PTE1_SIZE / PAGE_SIZE]; mt++)
- if (TAILQ_EMPTY(&mt->md.pv_list))
- vm_page_aflag_clear(mt, PGA_WRITEABLE);
- }
- mpt2pg = pmap_pt2_page(pmap, pv->pv_va);
- if (mpt2pg != NULL)
- pmap_unwire_pt2_all(pmap, pv->pv_va, mpt2pg, free);
-}
-
-/*
- * Just subroutine for pmap_remove_pages() to reasonably satisfy
- * good coding style, a.k.a. 80 character line width limit hell.
- */
-static __inline void
-pmap_remove_pte2_quick(pmap_t pmap, pt2_entry_t pte2, pv_entry_t pv,
- struct spglist *free)
-{
- vm_paddr_t pa;
- vm_page_t m;
- struct md_page *pvh;
-
- pa = pte2_pa(pte2);
- m = PHYS_TO_VM_PAGE(pa);
-
- KASSERT(m->phys_addr == pa, ("%s: vm_page_t %p addr mismatch %#x %#x",
- __func__, m, m->phys_addr, pa));
- KASSERT((m->flags & PG_FICTITIOUS) != 0 ||
- m < &vm_page_array[vm_page_array_size],
- ("%s: bad pte2 %#x", __func__, pte2));
-
- if (pte2_is_dirty(pte2))
- vm_page_dirty(m);
-
- pmap->pm_stats.resident_count--;
- TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
- if (TAILQ_EMPTY(&m->md.pv_list) && (m->flags & PG_FICTITIOUS) == 0) {
- pvh = pa_to_pvh(pa);
- if (TAILQ_EMPTY(&pvh->pv_list))
- vm_page_aflag_clear(m, PGA_WRITEABLE);
- }
- pmap_unuse_pt2(pmap, pv->pv_va, free);
-}
-
-/*
- * Remove all pages from specified address space this aids process
- * exit speeds. Also, this code is special cased for current process
- * only, but can have the more generic (and slightly slower) mode enabled.
- * This is much faster than pmap_remove in the case of running down
- * an entire address space.
- */
-void
-pmap_remove_pages(pmap_t pmap)
-{
- pt1_entry_t *pte1p, pte1;
- pt2_entry_t *pte2p, pte2;
- pv_entry_t pv;
- struct pv_chunk *pc, *npc;
- struct spglist free;
- int field, idx;
- int32_t bit;
- uint32_t inuse, bitmask;
- boolean_t allfree;
-
- /*
- * Assert that the given pmap is only active on the current
- * CPU. Unfortunately, we cannot block another CPU from
- * activating the pmap while this function is executing.
- */
- KASSERT(pmap == vmspace_pmap(curthread->td_proc->p_vmspace),
- ("%s: non-current pmap %p", __func__, pmap));
-#if defined(SMP) && defined(INVARIANTS)
- {
- cpuset_t other_cpus;
-
- sched_pin();
- other_cpus = pmap->pm_active;
- CPU_CLR(PCPU_GET(cpuid), &other_cpus);
- sched_unpin();
- KASSERT(CPU_EMPTY(&other_cpus),
- ("%s: pmap %p active on other cpus", __func__, pmap));
- }
-#endif
- SLIST_INIT(&free);
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
- sched_pin();
- TAILQ_FOREACH_SAFE(pc, &pmap->pm_pvchunk, pc_list, npc) {
- KASSERT(pc->pc_pmap == pmap, ("%s: wrong pmap %p %p",
- __func__, pmap, pc->pc_pmap));
- allfree = TRUE;
- for (field = 0; field < _NPCM; field++) {
- inuse = (~(pc->pc_map[field])) & pc_freemask[field];
- while (inuse != 0) {
- bit = ffs(inuse) - 1;
- bitmask = 1UL << bit;
- idx = field * 32 + bit;
- pv = &pc->pc_pventry[idx];
- inuse &= ~bitmask;
-
- /*
- * Note that we cannot remove wired pages
- * from a process' mapping at this time
- */
- pte1p = pmap_pte1(pmap, pv->pv_va);
- pte1 = pte1_load(pte1p);
- if (pte1_is_section(pte1)) {
- if (pte1_is_wired(pte1)) {
- allfree = FALSE;
- continue;
- }
- pte1_clear(pte1p);
- pmap_remove_pte1_quick(pmap, pte1, pv,
- &free);
- }
- else if (pte1_is_link(pte1)) {
- pte2p = pt2map_entry(pv->pv_va);
- pte2 = pte2_load(pte2p);
-
- if (!pte2_is_valid(pte2)) {
- printf("%s: pmap %p va %#x "
- "pte2 %#x\n", __func__,
- pmap, pv->pv_va, pte2);
- panic("bad pte2");
- }
-
- if (pte2_is_wired(pte2)) {
- allfree = FALSE;
- continue;
- }
- pte2_clear(pte2p);
- pmap_remove_pte2_quick(pmap, pte2, pv,
- &free);
- } else {
- printf("%s: pmap %p va %#x pte1 %#x\n",
- __func__, pmap, pv->pv_va, pte1);
- panic("bad pte1");
- }
-
- /* Mark free */
- PV_STAT(pv_entry_frees++);
- PV_STAT(pv_entry_spare++);
- pv_entry_count--;
- pc->pc_map[field] |= bitmask;
- }
- }
- if (allfree) {
- TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
- free_pv_chunk(pc);
- }
- }
- tlb_flush_all_ng_local();
- sched_unpin();
- rw_wunlock(&pvh_global_lock);
- PMAP_UNLOCK(pmap);
- pmap_free_zero_pages(&free);
-}
-
-/*
- * This code makes some *MAJOR* assumptions:
- * 1. Current pmap & pmap exists.
- * 2. Not wired.
- * 3. Read access.
- * 4. No L2 page table pages.
- * but is *MUCH* faster than pmap_enter...
- */
-static vm_page_t
-pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
- vm_prot_t prot, vm_page_t mpt2pg)
-{
- pt2_entry_t *pte2p, pte2;
- vm_paddr_t pa;
- struct spglist free;
- uint32_t l2prot;
-
- KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva ||
- (m->oflags & VPO_UNMANAGED) != 0,
- ("%s: managed mapping within the clean submap", __func__));
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- PMAP_LOCK_ASSERT(pmap, MA_OWNED);
-
- /*
- * In the case that a L2 page table page is not
- * resident, we are creating it here.
- */
- if (va < VM_MAXUSER_ADDRESS) {
- u_int pte1_idx;
- pt1_entry_t pte1, *pte1p;
- vm_paddr_t pt2_pa;
-
- /*
- * Get L1 page table things.
- */
- pte1_idx = pte1_index(va);
- pte1p = pmap_pte1(pmap, va);
- pte1 = pte1_load(pte1p);
-
- if (mpt2pg && (mpt2pg->pindex == (pte1_idx & ~PT2PG_MASK))) {
- /*
- * Each of NPT2_IN_PG L2 page tables on the page can
- * come here. Make sure that associated L1 page table
- * link is established.
- *
- * QQQ: It comes that we don't establish all links to
- * L2 page tables for newly allocated L2 page
- * tables page.
- */
- KASSERT(!pte1_is_section(pte1),
- ("%s: pte1 %#x is section", __func__, pte1));
- if (!pte1_is_link(pte1)) {
- pt2_pa = page_pt2pa(VM_PAGE_TO_PHYS(mpt2pg),
- pte1_idx);
- pte1_store(pte1p, PTE1_LINK(pt2_pa));
- }
- pt2_wirecount_inc(mpt2pg, pte1_idx);
- } else {
- /*
- * If the L2 page table page is mapped, we just
- * increment the hold count, and activate it.
- */
- if (pte1_is_section(pte1)) {
- return (NULL);
- } else if (pte1_is_link(pte1)) {
- mpt2pg = PHYS_TO_VM_PAGE(pte1_link_pa(pte1));
- pt2_wirecount_inc(mpt2pg, pte1_idx);
- } else {
- mpt2pg = _pmap_allocpte2(pmap, va,
- PMAP_ENTER_NOSLEEP);
- if (mpt2pg == NULL)
- return (NULL);
- }
- }
- } else {
- mpt2pg = NULL;
- }
-
- /*
- * This call to pt2map_entry() makes the assumption that we are
- * entering the page into the current pmap. In order to support
- * quick entry into any pmap, one would likely use pmap_pte2_quick().
- * But that isn't as quick as pt2map_entry().
- */
- pte2p = pt2map_entry(va);
- pte2 = pte2_load(pte2p);
- if (pte2_is_valid(pte2)) {
- if (mpt2pg != NULL) {
- /*
- * Remove extra pte2 reference
- */
- pt2_wirecount_dec(mpt2pg, pte1_index(va));
- mpt2pg = NULL;
- }
- return (NULL);
- }
-
- /*
- * Enter on the PV list if part of our managed memory.
- */
- if ((m->oflags & VPO_UNMANAGED) == 0 &&
- !pmap_try_insert_pv_entry(pmap, va, m)) {
- if (mpt2pg != NULL) {
- SLIST_INIT(&free);
- if (pmap_unwire_pt2(pmap, va, mpt2pg, &free)) {
- pmap_tlb_flush(pmap, va);
- pmap_free_zero_pages(&free);
- }
-
- mpt2pg = NULL;
- }
- return (NULL);
- }
-
- /*
- * Increment counters
- */
- pmap->pm_stats.resident_count++;
-
- /*
- * Now validate mapping with RO protection
- */
- pa = VM_PAGE_TO_PHYS(m);
- l2prot = PTE2_RO | PTE2_NM;
- if (va < VM_MAXUSER_ADDRESS)
- l2prot |= PTE2_U | PTE2_NG;
- if ((prot & VM_PROT_EXECUTE) == 0)
- l2prot |= PTE2_NX;
- else if (m->md.pat_mode == PTE2_ATTR_WB_WA && pmap != kernel_pmap) {
- /*
- * Sync icache if exec permission and attribute PTE2_ATTR_WB_WA
- * is set. QQQ: For more info, see comments in pmap_enter().
- */
- cache_icache_sync_fresh(va, pa, PAGE_SIZE);
- }
- pte2_store(pte2p, PTE2(pa, l2prot, m->md.pat_mode));
-
- return (mpt2pg);
-}
-
-void
-pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
-{
-
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
- (void)pmap_enter_quick_locked(pmap, va, m, prot, NULL);
- rw_wunlock(&pvh_global_lock);
- PMAP_UNLOCK(pmap);
-}
-
-/*
- * Tries to create 1MB page mapping. Returns TRUE if successful and
- * FALSE otherwise. Fails if (1) a page table page cannot be allocated without
- * blocking, (2) a mapping already exists at the specified virtual address, or
- * (3) a pv entry cannot be allocated without reclaiming another pv entry.
- */
-static boolean_t
-pmap_enter_pte1(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
-{
- pt1_entry_t *pte1p;
- vm_paddr_t pa;
- uint32_t l1prot;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- PMAP_LOCK_ASSERT(pmap, MA_OWNED);
- pte1p = pmap_pte1(pmap, va);
- if (pte1_is_valid(pte1_load(pte1p))) {
- CTR3(KTR_PMAP, "%s: failure for va %#lx in pmap %p", __func__,
- va, pmap);
- return (FALSE);
- }
- if ((m->oflags & VPO_UNMANAGED) == 0) {
- /*
- * Abort this mapping if its PV entry could not be created.
- */
- if (!pmap_pv_insert_pte1(pmap, va, VM_PAGE_TO_PHYS(m))) {
- CTR3(KTR_PMAP, "%s: failure for va %#lx in pmap %p",
- __func__, va, pmap);
- return (FALSE);
- }
- }
- /*
- * Increment counters.
- */
- pmap->pm_stats.resident_count += PTE1_SIZE / PAGE_SIZE;
-
- /*
- * Map the section.
- *
- * QQQ: Why VM_PROT_WRITE is not evaluated and the mapping is
- * made readonly?
- */
- pa = VM_PAGE_TO_PHYS(m);
- l1prot = PTE1_RO | PTE1_NM;
- if (va < VM_MAXUSER_ADDRESS)
- l1prot |= PTE1_U | PTE1_NG;
- if ((prot & VM_PROT_EXECUTE) == 0)
- l1prot |= PTE1_NX;
- else if (m->md.pat_mode == PTE2_ATTR_WB_WA && pmap != kernel_pmap) {
- /*
- * Sync icache if exec permission and attribute PTE2_ATTR_WB_WA
- * is set. QQQ: For more info, see comments in pmap_enter().
- */
- cache_icache_sync_fresh(va, pa, PTE1_SIZE);
- }
- pte1_store(pte1p, PTE1(pa, l1prot, ATTR_TO_L1(m->md.pat_mode)));
-
- pmap_pte1_mappings++;
- CTR3(KTR_PMAP, "%s: success for va %#lx in pmap %p", __func__, va,
- pmap);
- return (TRUE);
-}
-
-/*
- * Maps a sequence of resident pages belonging to the same object.
- * The sequence begins with the given page m_start. This page is
- * mapped at the given virtual address start. Each subsequent page is
- * mapped at a virtual address that is offset from start by the same
- * amount as the page is offset from m_start within the object. The
- * last page in the sequence is the page with the largest offset from
- * m_start that can be mapped at a virtual address less than the given
- * virtual address end. Not every virtual page between start and end
- * is mapped; only those for which a resident page exists with the
- * corresponding offset from m_start are mapped.
- */
-void
-pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
- vm_page_t m_start, vm_prot_t prot)
-{
- vm_offset_t va;
- vm_page_t m, mpt2pg;
- vm_pindex_t diff, psize;
-
- PDEBUG(6, printf("%s: pmap %p start %#x end %#x m %p prot %#x\n",
- __func__, pmap, start, end, m_start, prot));
-
- VM_OBJECT_ASSERT_LOCKED(m_start->object);
- psize = atop(end - start);
- mpt2pg = NULL;
- m = m_start;
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
- while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
- va = start + ptoa(diff);
- if ((va & PTE1_OFFSET) == 0 && va + PTE1_SIZE <= end &&
- m->psind == 1 && sp_enabled &&
- pmap_enter_pte1(pmap, va, m, prot))
- m = &m[PTE1_SIZE / PAGE_SIZE - 1];
- else
- mpt2pg = pmap_enter_quick_locked(pmap, va, m, prot,
- mpt2pg);
- m = TAILQ_NEXT(m, listq);
- }
- rw_wunlock(&pvh_global_lock);
- PMAP_UNLOCK(pmap);
-}
-
-/*
- * This code maps large physical mmap regions into the
- * processor address space. Note that some shortcuts
- * are taken, but the code works.
- */
-void
-pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object,
- vm_pindex_t pindex, vm_size_t size)
-{
- pt1_entry_t *pte1p;
- vm_paddr_t pa, pte2_pa;
- vm_page_t p;
- int pat_mode;
- u_int l1attr, l1prot;
-
- VM_OBJECT_ASSERT_WLOCKED(object);
- KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG,
- ("%s: non-device object", __func__));
- if ((addr & PTE1_OFFSET) == 0 && (size & PTE1_OFFSET) == 0) {
- if (!vm_object_populate(object, pindex, pindex + atop(size)))
- return;
- p = vm_page_lookup(object, pindex);
- KASSERT(p->valid == VM_PAGE_BITS_ALL,
- ("%s: invalid page %p", __func__, p));
- pat_mode = p->md.pat_mode;
-
- /*
- * Abort the mapping if the first page is not physically
- * aligned to a 1MB page boundary.
- */
- pte2_pa = VM_PAGE_TO_PHYS(p);
- if (pte2_pa & PTE1_OFFSET)
- return;
-
- /*
- * Skip the first page. Abort the mapping if the rest of
- * the pages are not physically contiguous or have differing
- * memory attributes.
- */
- p = TAILQ_NEXT(p, listq);
- for (pa = pte2_pa + PAGE_SIZE; pa < pte2_pa + size;
- pa += PAGE_SIZE) {
- KASSERT(p->valid == VM_PAGE_BITS_ALL,
- ("%s: invalid page %p", __func__, p));
- if (pa != VM_PAGE_TO_PHYS(p) ||
- pat_mode != p->md.pat_mode)
- return;
- p = TAILQ_NEXT(p, listq);
- }
-
- /*
- * Map using 1MB pages.
- *
- * QQQ: Well, we are mapping a section, so same condition must
- * be hold like during promotion. It looks that only RW mapping
- * is done here, so readonly mapping must be done elsewhere.
- */
- l1prot = PTE1_U | PTE1_NG | PTE1_RW | PTE1_M | PTE1_A;
- l1attr = ATTR_TO_L1(pat_mode);
- PMAP_LOCK(pmap);
- for (pa = pte2_pa; pa < pte2_pa + size; pa += PTE1_SIZE) {
- pte1p = pmap_pte1(pmap, addr);
- if (!pte1_is_valid(pte1_load(pte1p))) {
- pte1_store(pte1p, PTE1(pa, l1prot, l1attr));
- pmap->pm_stats.resident_count += PTE1_SIZE /
- PAGE_SIZE;
- pmap_pte1_mappings++;
- }
- /* Else continue on if the PTE1 is already valid. */
- addr += PTE1_SIZE;
- }
- PMAP_UNLOCK(pmap);
- }
-}
-
-/*
- * Do the things to protect a 1mpage in a process.
- */
-static void
-pmap_protect_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t sva,
- vm_prot_t prot)
-{
- pt1_entry_t npte1, opte1;
- vm_offset_t eva, va;
- vm_page_t m;
-
- PMAP_LOCK_ASSERT(pmap, MA_OWNED);
- KASSERT((sva & PTE1_OFFSET) == 0,
- ("%s: sva is not 1mpage aligned", __func__));
-retry:
- opte1 = npte1 = pte1_load(pte1p);
- if (pte1_is_managed(opte1)) {
- eva = sva + PTE1_SIZE;
- for (va = sva, m = PHYS_TO_VM_PAGE(pte1_pa(opte1));
- va < eva; va += PAGE_SIZE, m++)
- if (pte1_is_dirty(opte1))
- vm_page_dirty(m);
- }
- if ((prot & VM_PROT_WRITE) == 0)
- npte1 |= PTE1_RO | PTE1_NM;
- if ((prot & VM_PROT_EXECUTE) == 0)
- npte1 |= PTE1_NX;
-
- /*
- * QQQ: Herein, execute permission is never set.
- * It only can be cleared. So, no icache
- * syncing is needed.
- */
-
- if (npte1 != opte1) {
- if (!pte1_cmpset(pte1p, opte1, npte1))
- goto retry;
- pmap_tlb_flush(pmap, sva);
- }
-}
-
-/*
- * Set the physical protection on the
- * specified range of this map as requested.
- */
-void
-pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
-{
- boolean_t pv_lists_locked;
- vm_offset_t nextva;
- pt1_entry_t *pte1p, pte1;
- pt2_entry_t *pte2p, opte2, npte2;
-
- KASSERT((prot & ~VM_PROT_ALL) == 0, ("invalid prot %x", prot));
- if (prot == VM_PROT_NONE) {
- pmap_remove(pmap, sva, eva);
- return;
- }
-
- if ((prot & (VM_PROT_WRITE | VM_PROT_EXECUTE)) ==
- (VM_PROT_WRITE | VM_PROT_EXECUTE))
- return;
-
- if (pmap_is_current(pmap))
- pv_lists_locked = FALSE;
- else {
- pv_lists_locked = TRUE;
-resume:
- rw_wlock(&pvh_global_lock);
- sched_pin();
- }
-
- PMAP_LOCK(pmap);
- for (; sva < eva; sva = nextva) {
- /*
- * Calculate address for next L2 page table.
- */
- nextva = pte1_trunc(sva + PTE1_SIZE);
- if (nextva < sva)
- nextva = eva;
-
- pte1p = pmap_pte1(pmap, sva);
- pte1 = pte1_load(pte1p);
-
- /*
- * Weed out invalid mappings. Note: we assume that L1 page
- * page table is always allocated, and in kernel virtual.
- */
- if (pte1 == 0)
- continue;
-
- if (pte1_is_section(pte1)) {
- /*
- * Are we protecting the entire large page? If not,
- * demote the mapping and fall through.
- */
- if (sva + PTE1_SIZE == nextva && eva >= nextva) {
- pmap_protect_pte1(pmap, pte1p, sva, prot);
- continue;
- } else {
- if (!pv_lists_locked) {
- pv_lists_locked = TRUE;
- if (!rw_try_wlock(&pvh_global_lock)) {
- PMAP_UNLOCK(pmap);
- goto resume;
- }
- sched_pin();
- }
- if (!pmap_demote_pte1(pmap, pte1p, sva)) {
- /*
- * The large page mapping
- * was destroyed.
- */
- continue;
- }
-#ifdef INVARIANTS
- else {
- /* Update pte1 after demotion */
- pte1 = pte1_load(pte1p);
- }
-#endif
- }
- }
-
- KASSERT(pte1_is_link(pte1), ("%s: pmap %p va %#x pte1 %#x at %p"
- " is not link", __func__, pmap, sva, pte1, pte1p));
-
- /*
- * Limit our scan to either the end of the va represented
- * by the current L2 page table page, or to the end of the
- * range being protected.
- */
- if (nextva > eva)
- nextva = eva;
-
- for (pte2p = pmap_pte2_quick(pmap, sva); sva != nextva; pte2p++,
- sva += PAGE_SIZE) {
- vm_page_t m;
-retry:
- opte2 = npte2 = pte2_load(pte2p);
- if (!pte2_is_valid(opte2))
- continue;
-
- if ((prot & VM_PROT_WRITE) == 0) {
- if (pte2_is_managed(opte2) &&
- pte2_is_dirty(opte2)) {
- m = PHYS_TO_VM_PAGE(pte2_pa(opte2));
- vm_page_dirty(m);
- }
- npte2 |= PTE2_RO | PTE2_NM;
- }
-
- if ((prot & VM_PROT_EXECUTE) == 0)
- npte2 |= PTE2_NX;
-
- /*
- * QQQ: Herein, execute permission is never set.
- * It only can be cleared. So, no icache
- * syncing is needed.
- */
-
- if (npte2 != opte2) {
-
- if (!pte2_cmpset(pte2p, opte2, npte2))
- goto retry;
- pmap_tlb_flush(pmap, sva);
- }
- }
- }
- if (pv_lists_locked) {
- sched_unpin();
- rw_wunlock(&pvh_global_lock);
- }
- PMAP_UNLOCK(pmap);
-}
-
-/*
- * pmap_pvh_wired_mappings:
- *
- * Return the updated number "count" of managed mappings that are wired.
- */
-static int
-pmap_pvh_wired_mappings(struct md_page *pvh, int count)
-{
- pmap_t pmap;
- pt1_entry_t pte1;
- pt2_entry_t pte2;
- pv_entry_t pv;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- sched_pin();
- TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
- pmap = PV_PMAP(pv);
- PMAP_LOCK(pmap);
- pte1 = pte1_load(pmap_pte1(pmap, pv->pv_va));
- if (pte1_is_section(pte1)) {
- if (pte1_is_wired(pte1))
- count++;
- } else {
- KASSERT(pte1_is_link(pte1),
- ("%s: pte1 %#x is not link", __func__, pte1));
- pte2 = pte2_load(pmap_pte2_quick(pmap, pv->pv_va));
- if (pte2_is_wired(pte2))
- count++;
- }
- PMAP_UNLOCK(pmap);
- }
- sched_unpin();
- return (count);
-}
-
-/*
- * pmap_page_wired_mappings:
- *
- * Return the number of managed mappings to the given physical page
- * that are wired.
- */
-int
-pmap_page_wired_mappings(vm_page_t m)
-{
- int count;
-
- count = 0;
- if ((m->oflags & VPO_UNMANAGED) != 0)
- return (count);
- rw_wlock(&pvh_global_lock);
- count = pmap_pvh_wired_mappings(&m->md, count);
- if ((m->flags & PG_FICTITIOUS) == 0) {
- count = pmap_pvh_wired_mappings(pa_to_pvh(VM_PAGE_TO_PHYS(m)),
- count);
- }
- rw_wunlock(&pvh_global_lock);
- return (count);
-}
-
-/*
- * Returns TRUE if any of the given mappings were used to modify
- * physical memory. Otherwise, returns FALSE. Both page and 1mpage
- * mappings are supported.
- */
-static boolean_t
-pmap_is_modified_pvh(struct md_page *pvh)
-{
- pv_entry_t pv;
- pt1_entry_t pte1;
- pt2_entry_t pte2;
- pmap_t pmap;
- boolean_t rv;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- rv = FALSE;
- sched_pin();
- TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
- pmap = PV_PMAP(pv);
- PMAP_LOCK(pmap);
- pte1 = pte1_load(pmap_pte1(pmap, pv->pv_va));
- if (pte1_is_section(pte1)) {
- rv = pte1_is_dirty(pte1);
- } else {
- KASSERT(pte1_is_link(pte1),
- ("%s: pte1 %#x is not link", __func__, pte1));
- pte2 = pte2_load(pmap_pte2_quick(pmap, pv->pv_va));
- rv = pte2_is_dirty(pte2);
- }
- PMAP_UNLOCK(pmap);
- if (rv)
- break;
- }
- sched_unpin();
- return (rv);
-}
-
-/*
- * pmap_is_modified:
- *
- * Return whether or not the specified physical page was modified
- * in any physical maps.
- */
-boolean_t
-pmap_is_modified(vm_page_t m)
-{
- boolean_t rv;
-
- KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("%s: page %p is not managed", __func__, m));
-
- /*
- * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
- * concurrently set while the object is locked. Thus, if PGA_WRITEABLE
- * is clear, no PTE2s can have PG_M set.
- */
- VM_OBJECT_ASSERT_WLOCKED(m->object);
- if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
- return (FALSE);
- rw_wlock(&pvh_global_lock);
- rv = pmap_is_modified_pvh(&m->md) ||
- ((m->flags & PG_FICTITIOUS) == 0 &&
- pmap_is_modified_pvh(pa_to_pvh(VM_PAGE_TO_PHYS(m))));
- rw_wunlock(&pvh_global_lock);
- return (rv);
-}
-
-/*
- * pmap_is_prefaultable:
- *
- * Return whether or not the specified virtual address is eligible
- * for prefault.
- */
-boolean_t
-pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr)
-{
- pt1_entry_t pte1;
- pt2_entry_t pte2;
- boolean_t rv;
-
- rv = FALSE;
- PMAP_LOCK(pmap);
- pte1 = pte1_load(pmap_pte1(pmap, addr));
- if (pte1_is_link(pte1)) {
- pte2 = pte2_load(pt2map_entry(addr));
- rv = !pte2_is_valid(pte2) ;
- }
- PMAP_UNLOCK(pmap);
- return (rv);
-}
-
-/*
- * Returns TRUE if any of the given mappings were referenced and FALSE
- * otherwise. Both page and 1mpage mappings are supported.
- */
-static boolean_t
-pmap_is_referenced_pvh(struct md_page *pvh)
-{
-
- pv_entry_t pv;
- pt1_entry_t pte1;
- pt2_entry_t pte2;
- pmap_t pmap;
- boolean_t rv;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- rv = FALSE;
- sched_pin();
- TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
- pmap = PV_PMAP(pv);
- PMAP_LOCK(pmap);
- pte1 = pte1_load(pmap_pte1(pmap, pv->pv_va));
- if (pte1_is_section(pte1)) {
- rv = (pte1 & (PTE1_A | PTE1_V)) == (PTE1_A | PTE1_V);
- } else {
- pte2 = pte2_load(pmap_pte2_quick(pmap, pv->pv_va));
- rv = (pte2 & (PTE2_A | PTE2_V)) == (PTE2_A | PTE2_V);
- }
- PMAP_UNLOCK(pmap);
- if (rv)
- break;
- }
- sched_unpin();
- return (rv);
-}
-
-/*
- * pmap_is_referenced:
- *
- * Return whether or not the specified physical page was referenced
- * in any physical maps.
- */
-boolean_t
-pmap_is_referenced(vm_page_t m)
-{
- boolean_t rv;
-
- KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("%s: page %p is not managed", __func__, m));
- rw_wlock(&pvh_global_lock);
- rv = pmap_is_referenced_pvh(&m->md) ||
- ((m->flags & PG_FICTITIOUS) == 0 &&
- pmap_is_referenced_pvh(pa_to_pvh(VM_PAGE_TO_PHYS(m))));
- rw_wunlock(&pvh_global_lock);
- return (rv);
-}
-
-#define PMAP_TS_REFERENCED_MAX 5
-
-/*
- * pmap_ts_referenced:
- *
- * Return a count of reference bits for a page, clearing those bits.
- * It is not necessary for every reference bit to be cleared, but it
- * is necessary that 0 only be returned when there are truly no
- * reference bits set.
- *
- * XXX: The exact number of bits to check and clear is a matter that
- * should be tested and standardized at some point in the future for
- * optimal aging of shared pages.
- */
-int
-pmap_ts_referenced(vm_page_t m)
-{
- struct md_page *pvh;
- pv_entry_t pv, pvf;
- pmap_t pmap;
- pt1_entry_t *pte1p, opte1;
- pt2_entry_t *pte2p;
- vm_paddr_t pa;
- int rtval = 0;
-
- KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("%s: page %p is not managed", __func__, m));
- pa = VM_PAGE_TO_PHYS(m);
- pvh = pa_to_pvh(pa);
- rw_wlock(&pvh_global_lock);
- sched_pin();
- if ((m->flags & PG_FICTITIOUS) != 0 ||
- (pvf = TAILQ_FIRST(&pvh->pv_list)) == NULL)
- goto small_mappings;
- pv = pvf;
- do {
- pmap = PV_PMAP(pv);
- PMAP_LOCK(pmap);
- pte1p = pmap_pte1(pmap, pv->pv_va);
- opte1 = pte1_load(pte1p);
- if ((opte1 & PTE1_A) != 0) {
- /*
- * Since this reference bit is shared by 256 4KB pages,
- * it should not be cleared every time it is tested.
- * Apply a simple "hash" function on the physical page
- * number, the virtual section number, and the pmap
- * address to select one 4KB page out of the 256
- * on which testing the reference bit will result
- * in clearing that bit. This function is designed
- * to avoid the selection of the same 4KB page
- * for every 1MB page mapping.
- *
- * On demotion, a mapping that hasn't been referenced
- * is simply destroyed. To avoid the possibility of a
- * subsequent page fault on a demoted wired mapping,
- * always leave its reference bit set. Moreover,
- * since the section is wired, the current state of
- * its reference bit won't affect page replacement.
- */
- if ((((pa >> PAGE_SHIFT) ^ (pv->pv_va >> PTE1_SHIFT) ^
- (uintptr_t)pmap) & (NPTE2_IN_PG - 1)) == 0 &&
- !pte1_is_wired(opte1)) {
- pte1_clear_bit(pte1p, PTE1_A);
- pmap_tlb_flush(pmap, pv->pv_va);
- }
- rtval++;
- }
- PMAP_UNLOCK(pmap);
- /* Rotate the PV list if it has more than one entry. */
- if (TAILQ_NEXT(pv, pv_next) != NULL) {
- TAILQ_REMOVE(&pvh->pv_list, pv, pv_next);
- TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next);
- }
- if (rtval >= PMAP_TS_REFERENCED_MAX)
- goto out;
- } while ((pv = TAILQ_FIRST(&pvh->pv_list)) != pvf);
-small_mappings:
- if ((pvf = TAILQ_FIRST(&m->md.pv_list)) == NULL)
- goto out;
- pv = pvf;
- do {
- pmap = PV_PMAP(pv);
- PMAP_LOCK(pmap);
- pte1p = pmap_pte1(pmap, pv->pv_va);
- KASSERT(pte1_is_link(pte1_load(pte1p)),
- ("%s: not found a link in page %p's pv list", __func__, m));
-
- pte2p = pmap_pte2_quick(pmap, pv->pv_va);
- if ((pte2_load(pte2p) & PTE2_A) != 0) {
- pte2_clear_bit(pte2p, PTE2_A);
- pmap_tlb_flush(pmap, pv->pv_va);
- rtval++;
- }
- PMAP_UNLOCK(pmap);
- /* Rotate the PV list if it has more than one entry. */
- if (TAILQ_NEXT(pv, pv_next) != NULL) {
- TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
- TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
- }
- } while ((pv = TAILQ_FIRST(&m->md.pv_list)) != pvf && rtval <
- PMAP_TS_REFERENCED_MAX);
-out:
- sched_unpin();
- rw_wunlock(&pvh_global_lock);
- return (rtval);
-}
-
-/*
- * Clear the wired attribute from the mappings for the specified range of
- * addresses in the given pmap. Every valid mapping within that range
- * must have the wired attribute set. In contrast, invalid mappings
- * cannot have the wired attribute set, so they are ignored.
- *
- * The wired attribute of the page table entry is not a hardware feature,
- * so there is no need to invalidate any TLB entries.
- */
-void
-pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
-{
- vm_offset_t nextva;
- pt1_entry_t *pte1p, pte1;
- pt2_entry_t *pte2p, pte2;
- boolean_t pv_lists_locked;
-
- if (pmap_is_current(pmap))
- pv_lists_locked = FALSE;
- else {
- pv_lists_locked = TRUE;
-resume:
- rw_wlock(&pvh_global_lock);
- sched_pin();
- }
- PMAP_LOCK(pmap);
- for (; sva < eva; sva = nextva) {
- nextva = pte1_trunc(sva + PTE1_SIZE);
- if (nextva < sva)
- nextva = eva;
-
- pte1p = pmap_pte1(pmap, sva);
- pte1 = pte1_load(pte1p);
-
- /*
- * Weed out invalid mappings. Note: we assume that L1 page
- * page table is always allocated, and in kernel virtual.
- */
- if (pte1 == 0)
- continue;
-
- if (pte1_is_section(pte1)) {
- if (!pte1_is_wired(pte1))
- panic("%s: pte1 %#x not wired", __func__, pte1);
-
- /*
- * Are we unwiring the entire large page? If not,
- * demote the mapping and fall through.
- */
- if (sva + PTE1_SIZE == nextva && eva >= nextva) {
- pte1_clear_bit(pte1p, PTE1_W);
- pmap->pm_stats.wired_count -= PTE1_SIZE /
- PAGE_SIZE;
- continue;
- } else {
- if (!pv_lists_locked) {
- pv_lists_locked = TRUE;
- if (!rw_try_wlock(&pvh_global_lock)) {
- PMAP_UNLOCK(pmap);
- /* Repeat sva. */
- goto resume;
- }
- sched_pin();
- }
- if (!pmap_demote_pte1(pmap, pte1p, sva))
- panic("%s: demotion failed", __func__);
-#ifdef INVARIANTS
- else {
- /* Update pte1 after demotion */
- pte1 = pte1_load(pte1p);
- }
-#endif
- }
- }
-
- KASSERT(pte1_is_link(pte1), ("%s: pmap %p va %#x pte1 %#x at %p"
- " is not link", __func__, pmap, sva, pte1, pte1p));
-
- /*
- * Limit our scan to either the end of the va represented
- * by the current L2 page table page, or to the end of the
- * range being protected.
- */
- if (nextva > eva)
- nextva = eva;
-
- for (pte2p = pmap_pte2_quick(pmap, sva); sva != nextva; pte2p++,
- sva += PAGE_SIZE) {
- pte2 = pte2_load(pte2p);
- if (!pte2_is_valid(pte2))
- continue;
- if (!pte2_is_wired(pte2))
- panic("%s: pte2 %#x is missing PTE2_W",
- __func__, pte2);
-
- /*
- * PTE2_W must be cleared atomically. Although the pmap
- * lock synchronizes access to PTE2_W, another processor
- * could be changing PTE2_NM and/or PTE2_A concurrently.
- */
- pte2_clear_bit(pte2p, PTE2_W);
- pmap->pm_stats.wired_count--;
- }
- }
- if (pv_lists_locked) {
- sched_unpin();
- rw_wunlock(&pvh_global_lock);
- }
- PMAP_UNLOCK(pmap);
-}
-
-/*
- * Clear the write and modified bits in each of the given page's mappings.
- */
-void
-pmap_remove_write(vm_page_t m)
-{
- struct md_page *pvh;
- pv_entry_t next_pv, pv;
- pmap_t pmap;
- pt1_entry_t *pte1p;
- pt2_entry_t *pte2p, opte2;
- vm_offset_t va;
-
- KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("%s: page %p is not managed", __func__, m));
-
- /*
- * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
- * set by another thread while the object is locked. Thus,
- * if PGA_WRITEABLE is clear, no page table entries need updating.
- */
- VM_OBJECT_ASSERT_WLOCKED(m->object);
- if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
- return;
- rw_wlock(&pvh_global_lock);
- sched_pin();
- if ((m->flags & PG_FICTITIOUS) != 0)
- goto small_mappings;
- pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
- TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) {
- va = pv->pv_va;
- pmap = PV_PMAP(pv);
- PMAP_LOCK(pmap);
- pte1p = pmap_pte1(pmap, va);
- if (!(pte1_load(pte1p) & PTE1_RO))
- (void)pmap_demote_pte1(pmap, pte1p, va);
- PMAP_UNLOCK(pmap);
- }
-small_mappings:
- TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
- pmap = PV_PMAP(pv);
- PMAP_LOCK(pmap);
- pte1p = pmap_pte1(pmap, pv->pv_va);
- KASSERT(!pte1_is_section(pte1_load(pte1p)), ("%s: found"
- " a section in page %p's pv list", __func__, m));
- pte2p = pmap_pte2_quick(pmap, pv->pv_va);
-retry:
- opte2 = pte2_load(pte2p);
- if (!(opte2 & PTE2_RO)) {
- if (!pte2_cmpset(pte2p, opte2,
- opte2 | (PTE2_RO | PTE2_NM)))
- goto retry;
- if (pte2_is_dirty(opte2))
- vm_page_dirty(m);
- pmap_tlb_flush(pmap, pv->pv_va);
- }
- PMAP_UNLOCK(pmap);
- }
- vm_page_aflag_clear(m, PGA_WRITEABLE);
- sched_unpin();
- rw_wunlock(&pvh_global_lock);
-}
-
-/*
- * Apply the given advice to the specified range of addresses within the
- * given pmap. Depending on the advice, clear the referenced and/or
- * modified flags in each mapping and set the mapped page's dirty field.
- */
-void
-pmap_advise(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, int advice)
-{
- pt1_entry_t *pte1p, opte1;
- pt2_entry_t *pte2p, pte2;
- vm_offset_t pdnxt;
- vm_page_t m;
- boolean_t pv_lists_locked;
-
- if (advice != MADV_DONTNEED && advice != MADV_FREE)
- return;
- if (pmap_is_current(pmap))
- pv_lists_locked = FALSE;
- else {
- pv_lists_locked = TRUE;
-resume:
- rw_wlock(&pvh_global_lock);
- sched_pin();
- }
- PMAP_LOCK(pmap);
- for (; sva < eva; sva = pdnxt) {
- pdnxt = pte1_trunc(sva + PTE1_SIZE);
- if (pdnxt < sva)
- pdnxt = eva;
- pte1p = pmap_pte1(pmap, sva);
- opte1 = pte1_load(pte1p);
- if (!pte1_is_valid(opte1)) /* XXX */
- continue;
- else if (pte1_is_section(opte1)) {
- if (!pte1_is_managed(opte1))
- continue;
- if (!pv_lists_locked) {
- pv_lists_locked = TRUE;
- if (!rw_try_wlock(&pvh_global_lock)) {
- PMAP_UNLOCK(pmap);
- goto resume;
- }
- sched_pin();
- }
- if (!pmap_demote_pte1(pmap, pte1p, sva)) {
- /*
- * The large page mapping was destroyed.
- */
- continue;
- }
-
- /*
- * Unless the page mappings are wired, remove the
- * mapping to a single page so that a subsequent
- * access may repromote. Since the underlying L2 page
- * table is fully populated, this removal never
- * frees a L2 page table page.
- */
- if (!pte1_is_wired(opte1)) {
- pte2p = pmap_pte2_quick(pmap, sva);
- KASSERT(pte2_is_valid(pte2_load(pte2p)),
- ("%s: invalid PTE2", __func__));
- pmap_remove_pte2(pmap, pte2p, sva, NULL);
- }
- }
- if (pdnxt > eva)
- pdnxt = eva;
- for (pte2p = pmap_pte2_quick(pmap, sva); sva != pdnxt; pte2p++,
- sva += PAGE_SIZE) {
- pte2 = pte2_load(pte2p);
- if (!pte2_is_valid(pte2) || !pte2_is_managed(pte2))
- continue;
- else if (pte2_is_dirty(pte2)) {
- if (advice == MADV_DONTNEED) {
- /*
- * Future calls to pmap_is_modified()
- * can be avoided by making the page
- * dirty now.
- */
- m = PHYS_TO_VM_PAGE(pte2_pa(pte2));
- vm_page_dirty(m);
- }
- pte2_set_bit(pte2p, PTE2_NM);
- pte2_clear_bit(pte2p, PTE2_A);
- } else if ((pte2 & PTE2_A) != 0)
- pte2_clear_bit(pte2p, PTE2_A);
- else
- continue;
- pmap_tlb_flush(pmap, sva);
- }
- }
- if (pv_lists_locked) {
- sched_unpin();
- rw_wunlock(&pvh_global_lock);
- }
- PMAP_UNLOCK(pmap);
-}
-
-/*
- * Clear the modify bits on the specified physical page.
- */
-void
-pmap_clear_modify(vm_page_t m)
-{
- struct md_page *pvh;
- pv_entry_t next_pv, pv;
- pmap_t pmap;
- pt1_entry_t *pte1p, opte1;
- pt2_entry_t *pte2p, opte2;
- vm_offset_t va;
-
- KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("%s: page %p is not managed", __func__, m));
- VM_OBJECT_ASSERT_WLOCKED(m->object);
- KASSERT(!vm_page_xbusied(m),
- ("%s: page %p is exclusive busy", __func__, m));
-
- /*
- * If the page is not PGA_WRITEABLE, then no PTE2s can have PTE2_NM
- * cleared. If the object containing the page is locked and the page
- * is not exclusive busied, then PGA_WRITEABLE cannot be concurrently
- * set.
- */
- if ((m->flags & PGA_WRITEABLE) == 0)
- return;
- rw_wlock(&pvh_global_lock);
- sched_pin();
- if ((m->flags & PG_FICTITIOUS) != 0)
- goto small_mappings;
- pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
- TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) {
- va = pv->pv_va;
- pmap = PV_PMAP(pv);
- PMAP_LOCK(pmap);
- pte1p = pmap_pte1(pmap, va);
- opte1 = pte1_load(pte1p);
- if (!(opte1 & PTE1_RO)) {
- if (pmap_demote_pte1(pmap, pte1p, va) &&
- !pte1_is_wired(opte1)) {
- /*
- * Write protect the mapping to a
- * single page so that a subsequent
- * write access may repromote.
- */
- va += VM_PAGE_TO_PHYS(m) - pte1_pa(opte1);
- pte2p = pmap_pte2_quick(pmap, va);
- opte2 = pte2_load(pte2p);
- if ((opte2 & PTE2_V)) {
- pte2_set_bit(pte2p, PTE2_NM | PTE2_RO);
- vm_page_dirty(m);
- pmap_tlb_flush(pmap, va);
- }
- }
- }
- PMAP_UNLOCK(pmap);
- }
-small_mappings:
- TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
- pmap = PV_PMAP(pv);
- PMAP_LOCK(pmap);
- pte1p = pmap_pte1(pmap, pv->pv_va);
- KASSERT(!pte1_is_section(pte1_load(pte1p)), ("%s: found"
- " a section in page %p's pv list", __func__, m));
- pte2p = pmap_pte2_quick(pmap, pv->pv_va);
- if (pte2_is_dirty(pte2_load(pte2p))) {
- pte2_set_bit(pte2p, PTE2_NM);
- pmap_tlb_flush(pmap, pv->pv_va);
- }
- PMAP_UNLOCK(pmap);
- }
- sched_unpin();
- rw_wunlock(&pvh_global_lock);
-}
-
-
-/*
- * Sets the memory attribute for the specified page.
- */
-void
-pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma)
-{
- struct sysmaps *sysmaps;
- vm_memattr_t oma;
- vm_paddr_t pa;
-
- oma = m->md.pat_mode;
- m->md.pat_mode = ma;
-
- CTR5(KTR_PMAP, "%s: page %p - 0x%08X oma: %d, ma: %d", __func__, m,
- VM_PAGE_TO_PHYS(m), oma, ma);
- if ((m->flags & PG_FICTITIOUS) != 0)
- return;
-#if 0
- /*
- * If "m" is a normal page, flush it from the cache.
- *
- * First, try to find an existing mapping of the page by sf
- * buffer. sf_buf_invalidate_cache() modifies mapping and
- * flushes the cache.
- */
- if (sf_buf_invalidate_cache(m, oma))
- return;
-#endif
- /*
- * If page is not mapped by sf buffer, map the page
- * transient and do invalidation.
- */
- if (ma != oma) {
- pa = VM_PAGE_TO_PHYS(m);
- sched_pin();
- sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
- mtx_lock(&sysmaps->lock);
- if (*sysmaps->CMAP2)
- panic("%s: CMAP2 busy", __func__);
- pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW, ma));
- dcache_wbinv_poc((vm_offset_t)sysmaps->CADDR2, pa, PAGE_SIZE);
- pte2_clear(sysmaps->CMAP2);
- tlb_flush((vm_offset_t)sysmaps->CADDR2);
- sched_unpin();
- mtx_unlock(&sysmaps->lock);
- }
-}
-
-/*
- * Miscellaneous support routines follow
- */
-
-/*
- * Returns TRUE if the given page is mapped individually or as part of
- * a 1mpage. Otherwise, returns FALSE.
- */
-boolean_t
-pmap_page_is_mapped(vm_page_t m)
-{
- boolean_t rv;
-
- if ((m->oflags & VPO_UNMANAGED) != 0)
- return (FALSE);
- rw_wlock(&pvh_global_lock);
- rv = !TAILQ_EMPTY(&m->md.pv_list) ||
- ((m->flags & PG_FICTITIOUS) == 0 &&
- !TAILQ_EMPTY(&pa_to_pvh(VM_PAGE_TO_PHYS(m))->pv_list));
- rw_wunlock(&pvh_global_lock);
- return (rv);
-}
-
-/*
- * Returns true if the pmap's pv is one of the first
- * 16 pvs linked to from this page. This count may
- * be changed upwards or downwards in the future; it
- * is only necessary that true be returned for a small
- * subset of pmaps for proper page aging.
- */
-boolean_t
-pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
-{
- struct md_page *pvh;
- pv_entry_t pv;
- int loops = 0;
- boolean_t rv;
-
- KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("%s: page %p is not managed", __func__, m));
- rv = FALSE;
- rw_wlock(&pvh_global_lock);
- TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
- if (PV_PMAP(pv) == pmap) {
- rv = TRUE;
- break;
- }
- loops++;
- if (loops >= 16)
- break;
- }
- if (!rv && loops < 16 && (m->flags & PG_FICTITIOUS) == 0) {
- pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
- TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
- if (PV_PMAP(pv) == pmap) {
- rv = TRUE;
- break;
- }
- loops++;
- if (loops >= 16)
- break;
- }
- }
- rw_wunlock(&pvh_global_lock);
- return (rv);
-}
-
-/*
- * pmap_zero_page zeros the specified hardware page by mapping
- * the page into KVM and using bzero to clear its contents.
- */
-void
-pmap_zero_page(vm_page_t m)
-{
- struct sysmaps *sysmaps;
-
- sched_pin();
- sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
- mtx_lock(&sysmaps->lock);
- if (pte2_load(sysmaps->CMAP2) != 0)
- panic("%s: CMAP2 busy", __func__);
- pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW,
- m->md.pat_mode));
- pagezero(sysmaps->CADDR2);
- pte2_clear(sysmaps->CMAP2);
- tlb_flush((vm_offset_t)sysmaps->CADDR2);
- sched_unpin();
- mtx_unlock(&sysmaps->lock);
-}
-
-/*
- * pmap_zero_page_area zeros the specified hardware page by mapping
- * the page into KVM and using bzero to clear its contents.
- *
- * off and size may not cover an area beyond a single hardware page.
- */
-void
-pmap_zero_page_area(vm_page_t m, int off, int size)
-{
- struct sysmaps *sysmaps;
-
- sched_pin();
- sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
- mtx_lock(&sysmaps->lock);
- if (pte2_load(sysmaps->CMAP2) != 0)
- panic("%s: CMAP2 busy", __func__);
- pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW,
- m->md.pat_mode));
- if (off == 0 && size == PAGE_SIZE)
- pagezero(sysmaps->CADDR2);
- else
- bzero(sysmaps->CADDR2 + off, size);
- pte2_clear(sysmaps->CMAP2);
- tlb_flush((vm_offset_t)sysmaps->CADDR2);
- sched_unpin();
- mtx_unlock(&sysmaps->lock);
-}
-
-/*
- * pmap_zero_page_idle zeros the specified hardware page by mapping
- * the page into KVM and using bzero to clear its contents. This
- * is intended to be called from the vm_pagezero process only and
- * outside of Giant.
- */
-void
-pmap_zero_page_idle(vm_page_t m)
-{
-
- if (pte2_load(CMAP3) != 0)
- panic("%s: CMAP3 busy", __func__);
- sched_pin();
- pte2_store(CMAP3, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW,
- m->md.pat_mode));
- pagezero(CADDR3);
- pte2_clear(CMAP3);
- tlb_flush((vm_offset_t)CADDR3);
- sched_unpin();
-}
-
-/*
- * pmap_copy_page copies the specified (machine independent)
- * page by mapping the page into virtual memory and using
- * bcopy to copy the page, one machine dependent page at a
- * time.
- */
-void
-pmap_copy_page(vm_page_t src, vm_page_t dst)
-{
- struct sysmaps *sysmaps;
-
- sched_pin();
- sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
- mtx_lock(&sysmaps->lock);
- if (pte2_load(sysmaps->CMAP1) != 0)
- panic("%s: CMAP1 busy", __func__);
- if (pte2_load(sysmaps->CMAP2) != 0)
- panic("%s: CMAP2 busy", __func__);
- pte2_store(sysmaps->CMAP1, PTE2_KERN_NG(VM_PAGE_TO_PHYS(src),
- PTE2_AP_KR | PTE2_NM, src->md.pat_mode));
- pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(dst),
- PTE2_AP_KRW, dst->md.pat_mode));
- bcopy(sysmaps->CADDR1, sysmaps->CADDR2, PAGE_SIZE);
- pte2_clear(sysmaps->CMAP1);
- tlb_flush((vm_offset_t)sysmaps->CADDR1);
- pte2_clear(sysmaps->CMAP2);
- tlb_flush((vm_offset_t)sysmaps->CADDR2);
- sched_unpin();
- mtx_unlock(&sysmaps->lock);
-}
-
-int unmapped_buf_allowed = 1;
-
-void
-pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
- vm_offset_t b_offset, int xfersize)
-{
- struct sysmaps *sysmaps;
- vm_page_t a_pg, b_pg;
- char *a_cp, *b_cp;
- vm_offset_t a_pg_offset, b_pg_offset;
- int cnt;
-
- sched_pin();
- sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
- mtx_lock(&sysmaps->lock);
- if (*sysmaps->CMAP1 != 0)
- panic("pmap_copy_pages: CMAP1 busy");
- if (*sysmaps->CMAP2 != 0)
- panic("pmap_copy_pages: CMAP2 busy");
- while (xfersize > 0) {
- a_pg = ma[a_offset >> PAGE_SHIFT];
- a_pg_offset = a_offset & PAGE_MASK;
- cnt = min(xfersize, PAGE_SIZE - a_pg_offset);
- b_pg = mb[b_offset >> PAGE_SHIFT];
- b_pg_offset = b_offset & PAGE_MASK;
- cnt = min(cnt, PAGE_SIZE - b_pg_offset);
- pte2_store(sysmaps->CMAP1, PTE2_KERN_NG(VM_PAGE_TO_PHYS(a_pg),
- PTE2_AP_KR | PTE2_NM, a_pg->md.pat_mode));
- tlb_flush_local((vm_offset_t)sysmaps->CADDR1);
- pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(b_pg),
- PTE2_AP_KRW, b_pg->md.pat_mode));
- tlb_flush_local((vm_offset_t)sysmaps->CADDR2);
- a_cp = sysmaps->CADDR1 + a_pg_offset;
- b_cp = sysmaps->CADDR2 + b_pg_offset;
- bcopy(a_cp, b_cp, cnt);
- a_offset += cnt;
- b_offset += cnt;
- xfersize -= cnt;
- }
- pte2_clear(sysmaps->CMAP1);
- tlb_flush((vm_offset_t)sysmaps->CADDR1);
- pte2_clear(sysmaps->CMAP2);
- tlb_flush((vm_offset_t)sysmaps->CADDR2);
- sched_unpin();
- mtx_unlock(&sysmaps->lock);
-}
-
-vm_offset_t
-pmap_quick_enter_page(vm_page_t m)
-{
- pt2_entry_t *pte2p;
- vm_offset_t qmap_addr;
-
- critical_enter();
- qmap_addr = PCPU_GET(qmap_addr);
- pte2p = pt2map_entry(qmap_addr);
-
- KASSERT(pte2_load(pte2p) == 0, ("%s: PTE2 busy", __func__));
-
- pte2_store(pte2p, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW,
- pmap_page_get_memattr(m)));
- return (qmap_addr);
-}
-
-void
-pmap_quick_remove_page(vm_offset_t addr)
-{
- pt2_entry_t *pte2p;
- vm_offset_t qmap_addr;
-
- qmap_addr = PCPU_GET(qmap_addr);
- pte2p = pt2map_entry(qmap_addr);
-
- KASSERT(addr == qmap_addr, ("%s: invalid address", __func__));
- KASSERT(pte2_load(pte2p) != 0, ("%s: PTE2 not in use", __func__));
-
- pte2_clear(pte2p);
- tlb_flush(qmap_addr);
- critical_exit();
-}
-
-/*
- * Copy the range specified by src_addr/len
- * from the source map to the range dst_addr/len
- * in the destination map.
- *
- * This routine is only advisory and need not do anything.
- */
-void
-pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
- vm_offset_t src_addr)
-{
- struct spglist free;
- vm_offset_t addr;
- vm_offset_t end_addr = src_addr + len;
- vm_offset_t nextva;
-
- if (dst_addr != src_addr)
- return;
-
- if (!pmap_is_current(src_pmap))
- return;
-
- rw_wlock(&pvh_global_lock);
- if (dst_pmap < src_pmap) {
- PMAP_LOCK(dst_pmap);
- PMAP_LOCK(src_pmap);
- } else {
- PMAP_LOCK(src_pmap);
- PMAP_LOCK(dst_pmap);
- }
- sched_pin();
- for (addr = src_addr; addr < end_addr; addr = nextva) {
- pt2_entry_t *src_pte2p, *dst_pte2p;
- vm_page_t dst_mpt2pg, src_mpt2pg;
- pt1_entry_t src_pte1;
- u_int pte1_idx;
-
- KASSERT(addr < VM_MAXUSER_ADDRESS,
- ("%s: invalid to pmap_copy page tables", __func__));
-
- nextva = pte1_trunc(addr + PTE1_SIZE);
- if (nextva < addr)
- nextva = end_addr;
-
- pte1_idx = pte1_index(addr);
- src_pte1 = src_pmap->pm_pt1[pte1_idx];
- if (pte1_is_section(src_pte1)) {
- if ((addr & PTE1_OFFSET) != 0 ||
- (addr + PTE1_SIZE) > end_addr)
- continue;
- if (dst_pmap->pm_pt1[pte1_idx] == 0 &&
- (!pte1_is_managed(src_pte1) ||
- pmap_pv_insert_pte1(dst_pmap, addr,
- pte1_pa(src_pte1)))) {
- dst_pmap->pm_pt1[pte1_idx] = src_pte1 &
- ~PTE1_W;
- dst_pmap->pm_stats.resident_count +=
- PTE1_SIZE / PAGE_SIZE;
- pmap_pte1_mappings++;
- }
- continue;
- } else if (!pte1_is_link(src_pte1))
- continue;
-
- src_mpt2pg = PHYS_TO_VM_PAGE(pte1_link_pa(src_pte1));
-
- /*
- * We leave PT2s to be linked from PT1 even if they are not
- * referenced until all PT2s in a page are without reference.
- *
- * QQQ: It could be changed ...
- */
-#if 0 /* single_pt2_link_is_cleared */
- KASSERT(pt2_wirecount_get(src_mpt2pg, pte1_idx) > 0,
- ("%s: source page table page is unused", __func__));
-#else
- if (pt2_wirecount_get(src_mpt2pg, pte1_idx) == 0)
- continue;
-#endif
- if (nextva > end_addr)
- nextva = end_addr;
-
- src_pte2p = pt2map_entry(addr);
- while (addr < nextva) {
- pt2_entry_t temp_pte2;
- temp_pte2 = pte2_load(src_pte2p);
- /*
- * we only virtual copy managed pages
- */
- if (pte2_is_managed(temp_pte2)) {
- dst_mpt2pg = pmap_allocpte2(dst_pmap, addr,
- PMAP_ENTER_NOSLEEP);
- if (dst_mpt2pg == NULL)
- goto out;
- dst_pte2p = pmap_pte2_quick(dst_pmap, addr);
- if (!pte2_is_valid(pte2_load(dst_pte2p)) &&
- pmap_try_insert_pv_entry(dst_pmap, addr,
- PHYS_TO_VM_PAGE(pte2_pa(temp_pte2)))) {
- /*
- * Clear the wired, modified, and
- * accessed (referenced) bits
- * during the copy.
- */
- temp_pte2 &= ~(PTE2_W | PTE2_A);
- temp_pte2 |= PTE2_NM;
- pte2_store(dst_pte2p, temp_pte2);
- dst_pmap->pm_stats.resident_count++;
- } else {
- SLIST_INIT(&free);
- if (pmap_unwire_pt2(dst_pmap, addr,
- dst_mpt2pg, &free)) {
- pmap_tlb_flush(dst_pmap, addr);
- pmap_free_zero_pages(&free);
- }
- goto out;
- }
- if (pt2_wirecount_get(dst_mpt2pg, pte1_idx) >=
- pt2_wirecount_get(src_mpt2pg, pte1_idx))
- break;
- }
- addr += PAGE_SIZE;
- src_pte2p++;
- }
- }
-out:
- sched_unpin();
- rw_wunlock(&pvh_global_lock);
- PMAP_UNLOCK(src_pmap);
- PMAP_UNLOCK(dst_pmap);
-}
-
-/*
- * Increase the starting virtual address of the given mapping if a
- * different alignment might result in more section mappings.
- */
-void
-pmap_align_superpage(vm_object_t object, vm_ooffset_t offset,
- vm_offset_t *addr, vm_size_t size)
-{
- vm_offset_t pte1_offset;
-
- if (size < PTE1_SIZE)
- return;
- if (object != NULL && (object->flags & OBJ_COLORED) != 0)
- offset += ptoa(object->pg_color);
- pte1_offset = offset & PTE1_OFFSET;
- if (size - ((PTE1_SIZE - pte1_offset) & PTE1_OFFSET) < PTE1_SIZE ||
- (*addr & PTE1_OFFSET) == pte1_offset)
- return;
- if ((*addr & PTE1_OFFSET) < pte1_offset)
- *addr = pte1_trunc(*addr) + pte1_offset;
- else
- *addr = pte1_roundup(*addr) + pte1_offset;
-}
-
-void
-pmap_activate(struct thread *td)
-{
- pmap_t pmap, oldpmap;
- u_int cpuid, ttb;
-
- PDEBUG(9, printf("%s: td = %08x\n", __func__, (uint32_t)td));
-
- critical_enter();
- pmap = vmspace_pmap(td->td_proc->p_vmspace);
- oldpmap = PCPU_GET(curpmap);
- cpuid = PCPU_GET(cpuid);
-
-#if defined(SMP)
- CPU_CLR_ATOMIC(cpuid, &oldpmap->pm_active);
- CPU_SET_ATOMIC(cpuid, &pmap->pm_active);
-#else
- CPU_CLR(cpuid, &oldpmap->pm_active);
- CPU_SET(cpuid, &pmap->pm_active);
-#endif
-
- ttb = pmap_ttb_get(pmap);
-
- /*
- * pmap_activate is for the current thread on the current cpu
- */
- td->td_pcb->pcb_pagedir = ttb;
- cp15_ttbr_set(ttb);
- PCPU_SET(curpmap, pmap);
- critical_exit();
-}
-
-/*
- * Perform the pmap work for mincore.
- */
-int
-pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *locked_pa)
-{
- pt1_entry_t *pte1p, pte1;
- pt2_entry_t *pte2p, pte2;
- vm_paddr_t pa;
- boolean_t managed;
- int val;
-
- PMAP_LOCK(pmap);
-retry:
- pte1p = pmap_pte1(pmap, addr);
- pte1 = pte1_load(pte1p);
- if (pte1_is_section(pte1)) {
- pa = trunc_page(pte1_pa(pte1) | (addr & PTE1_OFFSET));
- managed = pte1_is_managed(pte1);
- val = MINCORE_SUPER | MINCORE_INCORE;
- if (pte1_is_dirty(pte1))
- val |= MINCORE_MODIFIED | MINCORE_MODIFIED_OTHER;
- if (pte1 & PTE1_A)
- val |= MINCORE_REFERENCED | MINCORE_REFERENCED_OTHER;
- } else if (pte1_is_link(pte1)) {
- pte2p = pmap_pte2(pmap, addr);
- pte2 = pte2_load(pte2p);
- pmap_pte2_release(pte2p);
- pa = pte2_pa(pte2);
- managed = pte2_is_managed(pte2);
- val = MINCORE_INCORE;
- if (pte2_is_dirty(pte2))
- val |= MINCORE_MODIFIED | MINCORE_MODIFIED_OTHER;
- if (pte2 & PTE2_A)
- val |= MINCORE_REFERENCED | MINCORE_REFERENCED_OTHER;
- } else {
- managed = FALSE;
- val = 0;
- }
- if ((val & (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER)) !=
- (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER) && managed) {
- /* Ensure that "PHYS_TO_VM_PAGE(pa)->object" doesn't change. */
- if (vm_page_pa_tryrelock(pmap, pa, locked_pa))
- goto retry;
- } else
- PA_UNLOCK_COND(*locked_pa);
- PMAP_UNLOCK(pmap);
- return (val);
-}
-
-void
-pmap_kenter_device(vm_offset_t va, vm_size_t size, vm_paddr_t pa)
-{
- vm_offset_t sva;
-
- KASSERT((size & PAGE_MASK) == 0,
- ("%s: device mapping not page-sized", __func__));
-
- sva = va;
- while (size != 0) {
- pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, PTE2_ATTR_DEVICE);
- va += PAGE_SIZE;
- pa += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
- tlb_flush_range(sva, va - sva);
-}
-
-void
-pmap_kremove_device(vm_offset_t va, vm_size_t size)
-{
- vm_offset_t sva;
-
- KASSERT((size & PAGE_MASK) == 0,
- ("%s: device mapping not page-sized", __func__));
-
- sva = va;
- while (size != 0) {
- pmap_kremove(va);
- va += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
- tlb_flush_range(sva, va - sva);
-}
-
-void
-pmap_set_pcb_pagedir(pmap_t pmap, struct pcb *pcb)
-{
-
- pcb->pcb_pagedir = pmap_ttb_get(pmap);
-}
-
-
-/*
- * Clean L1 data cache range by physical address.
- * The range must be within a single page.
- */
-static void
-pmap_dcache_wb_pou(vm_paddr_t pa, vm_size_t size, vm_memattr_t ma)
-{
- struct sysmaps *sysmaps;
-
- KASSERT(((pa & PAGE_MASK) + size) <= PAGE_SIZE,
- ("%s: not on single page", __func__));
-
- sched_pin();
- sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
- mtx_lock(&sysmaps->lock);
- if (*sysmaps->CMAP3)
- panic("%s: CMAP3 busy", __func__);
- pte2_store(sysmaps->CMAP3, PTE2_KERN_NG(pa, PTE2_AP_KRW, ma));
- dcache_wb_pou((vm_offset_t)sysmaps->CADDR3 + (pa & PAGE_MASK), size);
- pte2_clear(sysmaps->CMAP3);
- tlb_flush((vm_offset_t)sysmaps->CADDR3);
- sched_unpin();
- mtx_unlock(&sysmaps->lock);
-}
-
-/*
- * Sync instruction cache range which is not mapped yet.
- */
-void
-cache_icache_sync_fresh(vm_offset_t va, vm_paddr_t pa, vm_size_t size)
-{
- uint32_t len, offset;
- vm_page_t m;
-
- /* Write back d-cache on given address range. */
- offset = pa & PAGE_MASK;
- for ( ; size != 0; size -= len, pa += len, offset = 0) {
- len = min(PAGE_SIZE - offset, size);
- m = PHYS_TO_VM_PAGE(pa);
- KASSERT(m != NULL, ("%s: vm_page_t is null for %#x",
- __func__, pa));
- pmap_dcache_wb_pou(pa, len, m->md.pat_mode);
- }
- /*
- * I-cache is VIPT. Only way how to flush all virtual mappings
- * on given physical address is to invalidate all i-cache.
- */
- icache_inv_all();
-}
-
-void
-pmap_sync_icache(pmap_t pmap, vm_offset_t va, vm_size_t size)
-{
-
- /* Write back d-cache on given address range. */
- if (va >= VM_MIN_KERNEL_ADDRESS) {
- dcache_wb_pou(va, size);
- } else {
- uint32_t len, offset;
- vm_paddr_t pa;
- vm_page_t m;
-
- offset = va & PAGE_MASK;
- for ( ; size != 0; size -= len, va += len, offset = 0) {
- pa = pmap_extract(pmap, va); /* offset is preserved */
- len = min(PAGE_SIZE - offset, size);
- m = PHYS_TO_VM_PAGE(pa);
- KASSERT(m != NULL, ("%s: vm_page_t is null for %#x",
- __func__, pa));
- pmap_dcache_wb_pou(pa, len, m->md.pat_mode);
- }
- }
- /*
- * I-cache is VIPT. Only way how to flush all virtual mappings
- * on given physical address is to invalidate all i-cache.
- */
- icache_inv_all();
-}
-
-/*
- * The implementation of pmap_fault() uses IN_RANGE2() macro which
- * depends on the fact that given range size is a power of 2.
- */
-CTASSERT(powerof2(NB_IN_PT1));
-CTASSERT(powerof2(PT2MAP_SIZE));
-
-#define IN_RANGE2(addr, start, size) \
- ((vm_offset_t)(start) == ((vm_offset_t)(addr) & ~((size) - 1)))
-
-/*
- * Handle access and R/W emulation faults.
- */
-int
-pmap_fault(pmap_t pmap, vm_offset_t far, uint32_t fsr, int idx, bool usermode)
-{
- pt1_entry_t *pte1p, pte1;
- pt2_entry_t *pte2p, pte2;
-
- if (pmap == NULL)
- pmap = kernel_pmap;
-
- /*
- * In kernel, we should never get abort with FAR which is in range of
- * pmap->pm_pt1 or PT2MAP address spaces. If it happens, stop here
- * and print out a useful abort message and even get to the debugger
- * otherwise it likely ends with never ending loop of aborts.
- */
- if (__predict_false(IN_RANGE2(far, pmap->pm_pt1, NB_IN_PT1))) {
- /*
- * All L1 tables should always be mapped and present.
- * However, we check only current one herein. For user mode,
- * only permission abort from malicious user is not fatal.
- * And alignment abort as it may have higher priority.
- */
- if (!usermode || (idx != FAULT_ALIGN && idx != FAULT_PERM_L2)) {
- CTR4(KTR_PMAP, "%s: pmap %#x pm_pt1 %#x far %#x",
- __func__, pmap, pmap->pm_pt1, far);
- panic("%s: pm_pt1 abort", __func__);
- }
- return (KERN_INVALID_ADDRESS);
- }
- if (__predict_false(IN_RANGE2(far, PT2MAP, PT2MAP_SIZE))) {
- /*
- * PT2MAP should be always mapped and present in current
- * L1 table. However, only existing L2 tables are mapped
- * in PT2MAP. For user mode, only L2 translation abort and
- * permission abort from malicious user is not fatal.
- * And alignment abort as it may have higher priority.
- */
- if (!usermode || (idx != FAULT_ALIGN &&
- idx != FAULT_TRAN_L2 && idx != FAULT_PERM_L2)) {
- CTR4(KTR_PMAP, "%s: pmap %#x PT2MAP %#x far %#x",
- __func__, pmap, PT2MAP, far);
- panic("%s: PT2MAP abort", __func__);
- }
- return (KERN_INVALID_ADDRESS);
- }
-
- /*
- * Accesss bits for page and section. Note that the entry
- * is not in TLB yet, so TLB flush is not necessary.
- *
- * QQQ: This is hardware emulation, we do not call userret()
- * for aborts from user mode.
- * We do not lock PMAP, so cmpset() is a need. Hopefully,
- * no one removes the mapping when we are here.
- */
- if (idx == FAULT_ACCESS_L2) {
- pte2p = pt2map_entry(far);
-pte2_seta:
- pte2 = pte2_load(pte2p);
- if (pte2_is_valid(pte2)) {
- if (!pte2_cmpset(pte2p, pte2, pte2 | PTE2_A)) {
- goto pte2_seta;
- }
- return (KERN_SUCCESS);
- }
- }
- if (idx == FAULT_ACCESS_L1) {
- pte1p = pmap_pte1(pmap, far);
-pte1_seta:
- pte1 = pte1_load(pte1p);
- if (pte1_is_section(pte1)) {
- if (!pte1_cmpset(pte1p, pte1, pte1 | PTE1_A)) {
- goto pte1_seta;
- }
- return (KERN_SUCCESS);
- }
- }
-
- /*
- * Handle modify bits for page and section. Note that the modify
- * bit is emulated by software. So PTEx_RO is software read only
- * bit and PTEx_NM flag is real hardware read only bit.
- *
- * QQQ: This is hardware emulation, we do not call userret()
- * for aborts from user mode.
- * We do not lock PMAP, so cmpset() is a need. Hopefully,
- * no one removes the mapping when we are here.
- */
- if ((fsr & FSR_WNR) && (idx == FAULT_PERM_L2)) {
- pte2p = pt2map_entry(far);
-pte2_setrw:
- pte2 = pte2_load(pte2p);
- if (pte2_is_valid(pte2) && !(pte2 & PTE2_RO) &&
- (pte2 & PTE2_NM)) {
- if (!pte2_cmpset(pte2p, pte2, pte2 & ~PTE2_NM)) {
- goto pte2_setrw;
- }
- tlb_flush(trunc_page(far));
- return (KERN_SUCCESS);
- }
- }
- if ((fsr & FSR_WNR) && (idx == FAULT_PERM_L1)) {
- pte1p = pmap_pte1(pmap, far);
-pte1_setrw:
- pte1 = pte1_load(pte1p);
- if (pte1_is_section(pte1) && !(pte1 & PTE1_RO) &&
- (pte1 & PTE1_NM)) {
- if (!pte1_cmpset(pte1p, pte1, pte1 & ~PTE1_NM)) {
- goto pte1_setrw;
- }
- tlb_flush(pte1_trunc(far));
- return (KERN_SUCCESS);
- }
- }
-
- /*
- * QQQ: The previous code, mainly fast handling of access and
- * modify bits aborts, could be moved to ASM. Now we are
- * starting to deal with not fast aborts.
- */
-
-#ifdef INVARIANTS
- /*
- * Read an entry in PT2TAB associated with both pmap and far.
- * It's safe because PT2TAB is always mapped.
- *
- * QQQ: We do not lock PMAP, so false positives could happen if
- * the mapping is removed concurrently.
- */
- pte2 = pt2tab_load(pmap_pt2tab_entry(pmap, far));
- if (pte2_is_valid(pte2)) {
- /*
- * Now, when we know that L2 page table is allocated,
- * we can use PT2MAP to get L2 page table entry.
- */
- pte2 = pte2_load(pt2map_entry(far));
- if (pte2_is_valid(pte2)) {
- /*
- * If L2 page table entry is valid, make sure that
- * L1 page table entry is valid too. Note that we
- * leave L2 page entries untouched when promoted.
- */
- pte1 = pte1_load(pmap_pte1(pmap, far));
- if (!pte1_is_valid(pte1)) {
- panic("%s: missing L1 page entry (%p, %#x)",
- __func__, pmap, far);
- }
- }
- }
-#endif
- return (KERN_FAILURE);
-}
-
-/* !!!! REMOVE !!!! */
-void
-pmap_pte_init_mmu_v6(void)
-{
-}
-
-void vector_page_setprot(int p)
-{
-}
-
-#if defined(PMAP_DEBUG)
-/*
- * Reusing of KVA used in pmap_zero_page function !!!
- */
-static void
-pmap_zero_page_check(vm_page_t m)
-{
- uint32_t *p, *end;
- struct sysmaps *sysmaps;
-
- sched_pin();
- sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
- mtx_lock(&sysmaps->lock);
- if (pte2_load(sysmaps->CMAP2) != 0)
- panic("%s: CMAP2 busy", __func__);
- pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW,
- m->md.pat_mode));
- end = (uint32_t*)(sysmaps->CADDR2 + PAGE_SIZE);
- for (p = (uint32_t*)sysmaps->CADDR2; p < end; p++)
- if (*p != 0)
- panic("%s: page %p not zero, va: %p", __func__, m,
- sysmaps->CADDR2);
- pte2_clear(sysmaps->CMAP2);
- tlb_flush((vm_offset_t)sysmaps->CADDR2);
- sched_unpin();
- mtx_unlock(&sysmaps->lock);
-}
-
-int
-pmap_pid_dump(int pid)
-{
- pmap_t pmap;
- struct proc *p;
- int npte2 = 0;
- int i, j, index;
-
- sx_slock(&allproc_lock);
- FOREACH_PROC_IN_SYSTEM(p) {
- if (p->p_pid != pid || p->p_vmspace == NULL)
- continue;
- index = 0;
- pmap = vmspace_pmap(p->p_vmspace);
- for (i = 0; i < NPTE1_IN_PT1; i++) {
- pt1_entry_t pte1;
- pt2_entry_t *pte2p, pte2;
- vm_offset_t base, va;
- vm_paddr_t pa;
- vm_page_t m;
-
- base = i << PTE1_SHIFT;
- pte1 = pte1_load(&pmap->pm_pt1[i]);
-
- if (pte1_is_section(pte1)) {
- /*
- * QQQ: Do something here!
- */
- } else if (pte1_is_link(pte1)) {
- for (j = 0; j < NPTE2_IN_PT2; j++) {
- va = base + (j << PAGE_SHIFT);
- if (va >= VM_MIN_KERNEL_ADDRESS) {
- if (index) {
- index = 0;
- printf("\n");
- }
- sx_sunlock(&allproc_lock);
- return (npte2);
- }
- pte2p = pmap_pte2(pmap, va);
- pte2 = pte2_load(pte2p);
- pmap_pte2_release(pte2p);
- if (!pte2_is_valid(pte2))
- continue;
-
- pa = pte2_pa(pte2);
- m = PHYS_TO_VM_PAGE(pa);
- printf("va: 0x%x, pa: 0x%x, h: %d, w:"
- " %d, f: 0x%x", va, pa,
- m->hold_count, m->wire_count,
- m->flags);
- npte2++;
- index++;
- if (index >= 2) {
- index = 0;
- printf("\n");
- } else {
- printf(" ");
- }
- }
- }
- }
- }
- sx_sunlock(&allproc_lock);
- return (npte2);
-}
-
-#endif
-
-#ifdef DDB
-static pt2_entry_t *
-pmap_pte2_ddb(pmap_t pmap, vm_offset_t va)
-{
- pt1_entry_t pte1;
- vm_paddr_t pt2pg_pa;
-
- pte1 = pte1_load(pmap_pte1(pmap, va));
- if (!pte1_is_link(pte1))
- return (NULL);
-
- if (pmap_is_current(pmap))
- return (pt2map_entry(va));
-
- /* Note that L2 page table size is not equal to PAGE_SIZE. */
- pt2pg_pa = trunc_page(pte1_link_pa(pte1));
- if (pte2_pa(pte2_load(PMAP3)) != pt2pg_pa) {
- pte2_store(PMAP3, PTE2_KPT(pt2pg_pa));
-#ifdef SMP
- PMAP3cpu = PCPU_GET(cpuid);
-#endif
- tlb_flush_local((vm_offset_t)PADDR3);
- }
-#ifdef SMP
- else if (PMAP3cpu != PCPU_GET(cpuid)) {
- PMAP3cpu = PCPU_GET(cpuid);
- tlb_flush_local((vm_offset_t)PADDR3);
- }
-#endif
- return (PADDR3 + (arm32_btop(va) & (NPTE2_IN_PG - 1)));
-}
-
-static void
-dump_pmap(pmap_t pmap)
-{
-
- printf("pmap %p\n", pmap);
- printf(" pm_pt1: %p\n", pmap->pm_pt1);
- printf(" pm_pt2tab: %p\n", pmap->pm_pt2tab);
- printf(" pm_active: 0x%08lX\n", pmap->pm_active.__bits[0]);
-}
-
-DB_SHOW_COMMAND(pmaps, pmap_list_pmaps)
-{
-
- pmap_t pmap;
- LIST_FOREACH(pmap, &allpmaps, pm_list) {
- dump_pmap(pmap);
- }
-}
-
-static int
-pte2_class(pt2_entry_t pte2)
-{
- int cls;
-
- cls = (pte2 >> 2) & 0x03;
- cls |= (pte2 >> 4) & 0x04;
- return (cls);
-}
-
-static void
-dump_section(pmap_t pmap, uint32_t pte1_idx)
-{
-}
-
-static void
-dump_link(pmap_t pmap, uint32_t pte1_idx, boolean_t invalid_ok)
-{
- uint32_t i;
- vm_offset_t va;
- pt2_entry_t *pte2p, pte2;
- vm_page_t m;
-
- va = pte1_idx << PTE1_SHIFT;
- pte2p = pmap_pte2_ddb(pmap, va);
- for (i = 0; i < NPTE2_IN_PT2; i++, pte2p++, va += PAGE_SIZE) {
- pte2 = pte2_load(pte2p);
- if (pte2 == 0)
- continue;
- if (!pte2_is_valid(pte2)) {
- printf(" 0x%08X: 0x%08X", va, pte2);
- if (!invalid_ok)
- printf(" - not valid !!!");
- printf("\n");
- continue;
- }
- m = PHYS_TO_VM_PAGE(pte2_pa(pte2));
- printf(" 0x%08X: 0x%08X, TEX%d, s:%d, g:%d, m:%p", va , pte2,
- pte2_class(pte2), !!(pte2 & PTE2_S), !(pte2 & PTE2_NG), m);
- if (m != NULL) {
- printf(" v:%d h:%d w:%d f:0x%04X\n", m->valid,
- m->hold_count, m->wire_count, m->flags);
- } else {
- printf("\n");
- }
- }
-}
-
-static __inline boolean_t
-is_pv_chunk_space(vm_offset_t va)
-{
-
- if ((((vm_offset_t)pv_chunkbase) <= va) &&
- (va < ((vm_offset_t)pv_chunkbase + PAGE_SIZE * pv_maxchunks)))
- return (TRUE);
- return (FALSE);
-}
-
-DB_SHOW_COMMAND(pmap, pmap_pmap_print)
-{
- /* XXX convert args. */
- pmap_t pmap = (pmap_t)addr;
- pt1_entry_t pte1;
- pt2_entry_t pte2;
- vm_offset_t va, eva;
- vm_page_t m;
- uint32_t i;
- boolean_t invalid_ok, dump_link_ok, dump_pv_chunk;
-
- if (have_addr) {
- pmap_t pm;
-
- LIST_FOREACH(pm, &allpmaps, pm_list)
- if (pm == pmap) break;
- if (pm == NULL) {
- printf("given pmap %p is not in allpmaps list\n", pmap);
- return;
- }
- } else
- pmap = PCPU_GET(curpmap);
-
- eva = (modif[0] == 'u') ? VM_MAXUSER_ADDRESS : 0xFFFFFFFF;
- dump_pv_chunk = FALSE; /* XXX evaluate from modif[] */
-
- printf("pmap: 0x%08X\n", (uint32_t)pmap);
- printf("PT2MAP: 0x%08X\n", (uint32_t)PT2MAP);
- printf("pt2tab: 0x%08X\n", (uint32_t)pmap->pm_pt2tab);
-
- for(i = 0; i < NPTE1_IN_PT1; i++) {
- pte1 = pte1_load(&pmap->pm_pt1[i]);
- if (pte1 == 0)
- continue;
- va = i << PTE1_SHIFT;
- if (va >= eva)
- break;
-
- if (pte1_is_section(pte1)) {
- printf("0x%08X: Section 0x%08X, s:%d g:%d\n", va, pte1,
- !!(pte1 & PTE1_S), !(pte1 & PTE1_NG));
- dump_section(pmap, i);
- } else if (pte1_is_link(pte1)) {
- dump_link_ok = TRUE;
- invalid_ok = FALSE;
- pte2 = pte2_load(pmap_pt2tab_entry(pmap, va));
- m = PHYS_TO_VM_PAGE(pte1_link_pa(pte1));
- printf("0x%08X: Link 0x%08X, pt2tab: 0x%08X m: %p",
- va, pte1, pte2, m);
- if (is_pv_chunk_space(va)) {
- printf(" - pv_chunk space");
- if (dump_pv_chunk)
- invalid_ok = TRUE;
- else
- dump_link_ok = FALSE;
- }
- else if (m != NULL)
- printf(" w:%d w2:%u", m->wire_count,
- pt2_wirecount_get(m, pte1_index(va)));
- if (pte2 == 0)
- printf(" !!! pt2tab entry is ZERO");
- else if (pte2_pa(pte1) != pte2_pa(pte2))
- printf(" !!! pt2tab entry is DIFFERENT - m: %p",
- PHYS_TO_VM_PAGE(pte2_pa(pte2)));
- printf("\n");
- if (dump_link_ok)
- dump_link(pmap, i, invalid_ok);
- } else
- printf("0x%08X: Invalid entry 0x%08X\n", va, pte1);
- }
-}
-
-static void
-dump_pt2tab(pmap_t pmap)
-{
- uint32_t i;
- pt2_entry_t pte2;
- vm_offset_t va;
- vm_paddr_t pa;
- vm_page_t m;
-
- printf("PT2TAB:\n");
- for (i = 0; i < PT2TAB_ENTRIES; i++) {
- pte2 = pte2_load(&pmap->pm_pt2tab[i]);
- if (!pte2_is_valid(pte2))
- continue;
- va = i << PT2TAB_SHIFT;
- pa = pte2_pa(pte2);
- m = PHYS_TO_VM_PAGE(pa);
- printf(" 0x%08X: 0x%08X, TEX%d, s:%d, m:%p", va, pte2,
- pte2_class(pte2), !!(pte2 & PTE2_S), m);
- if (m != NULL)
- printf(" , h: %d, w: %d, f: 0x%04X pidx: %lld",
- m->hold_count, m->wire_count, m->flags, m->pindex);
- printf("\n");
- }
-}
-
-DB_SHOW_COMMAND(pmap_pt2tab, pmap_pt2tab_print)
-{
- /* XXX convert args. */
- pmap_t pmap = (pmap_t)addr;
- pt1_entry_t pte1;
- pt2_entry_t pte2;
- vm_offset_t va;
- uint32_t i, start;
-
- if (have_addr) {
- printf("supported only on current pmap\n");
- return;
- }
-
- pmap = PCPU_GET(curpmap);
- printf("curpmap: 0x%08X\n", (uint32_t)pmap);
- printf("PT2MAP: 0x%08X\n", (uint32_t)PT2MAP);
- printf("pt2tab: 0x%08X\n", (uint32_t)pmap->pm_pt2tab);
-
- start = pte1_index((vm_offset_t)PT2MAP);
- for (i = start; i < (start + NPT2_IN_PT2TAB); i++) {
- pte1 = pte1_load(&pmap->pm_pt1[i]);
- if (pte1 == 0)
- continue;
- va = i << PTE1_SHIFT;
- if (pte1_is_section(pte1)) {
- printf("0x%08X: Section 0x%08X, s:%d\n", va, pte1,
- !!(pte1 & PTE1_S));
- dump_section(pmap, i);
- } else if (pte1_is_link(pte1)) {
- pte2 = pte2_load(pmap_pt2tab_entry(pmap, va));
- printf("0x%08X: Link 0x%08X, pt2tab: 0x%08X\n", va,
- pte1, pte2);
- if (pte2 == 0)
- printf(" !!! pt2tab entry is ZERO\n");
- } else
- printf("0x%08X: Invalid entry 0x%08X\n", va, pte1);
- }
- dump_pt2tab(pmap);
-}
-#endif
diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c
index 5d7021189ed7..525280c6d822 100644
--- a/sys/arm/arm/pmap-v6.c
+++ b/sys/arm/arm/pmap-v6.c
@@ -1,11 +1,15 @@
-/* From: $NetBSD: pmap.c,v 1.148 2004/04/03 04:35:48 bsh Exp $ */
/*-
- * Copyright 2011 Semihalf
- * Copyright 2004 Olivier Houchard.
- * Copyright 2003 Wasabi Systems, Inc.
+ * Copyright (c) 1991 Regents of the University of California.
+ * Copyright (c) 1994 John S. Dyson
+ * Copyright (c) 1994 David Greenman
+ * Copyright (c) 2005-2010 Alan L. Cox <alc@cs.rice.edu>
+ * Copyright (c) 2014-2016 Svatopluk Kraus <skra@FreeBSD.org>
+ * Copyright (c) 2014-2016 Michal Meloun <mmel@FreeBSD.org>
* All rights reserved.
*
- * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and William Jolitz of UUNET Technologies Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -15,91 +19,33 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
+ * 3. 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 WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
- * 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: FreeBSD: src/sys/arm/arm/pmap.c,v 1.113 2009/07/24 13:50:29
- */
-
-/*-
- * Copyright (c) 2002-2003 Wasabi Systems, Inc.
- * Copyright (c) 2001 Richard Earnshaw
- * Copyright (c) 2001-2002 Christopher Gilbert
- * All rights reserved.
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the company nor the name of the author may be used to
- * endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR 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)
+ * 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.
- */
-/*-
- * Copyright (c) 1999 The NetBSD Foundation, Inc.
- * All rights reserved.
*
- * This code is derived from software contributed to The NetBSD Foundation
- * by Charles M. Hannum.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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: @(#)pmap.c 7.7 (Berkeley) 5/12/91
*/
-
/*-
- * Copyright (c) 1994-1998 Mark Brinicombe.
- * Copyright (c) 1994 Brini.
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
* All rights reserved.
*
- * This code is derived from software written for Brini by Mark Brinicombe
+ * This software was developed for the FreeBSD Project by Jake Burkholder,
+ * Safeport Network Services, and Network Associates Laboratories, the
+ * Security Research Division of Network Associates, Inc. under
+ * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
+ * CHATS research program.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -109,64 +55,78 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Mark Brinicombe.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *
- * RiscBSD kernel project
- *
- * pmap.c
- *
- * Machine dependant vm stuff
- *
- * Created : 20/09/94
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
/*
- * Special compilation symbols
- * PMAP_DEBUG - Build in pmap_debug_level code
+ * Manages physical address maps.
+ *
+ * Since the information managed by this module is
+ * also stored by the logical address mapping module,
+ * this module may throw away valid virtual-to-physical
+ * mappings at almost any time. However, invalidations
+ * of virtual-to-physical mappings must be done as
+ * requested.
*
- * Note that pmap_mapdev() and pmap_unmapdev() are implemented in arm/devmap.c
-*/
-/* Include header files */
+ * In order to cope with hardware architectures which
+ * make virtual-to-physical map invalidates expensive,
+ * this module may delay invalidate or reduced protection
+ * operations until such time as they are actually
+ * necessary. This module is given full information as
+ * to which processors are currently using which maps,
+ * and to when physical maps must be made correct.
+ */
#include "opt_vm.h"
#include "opt_pmap.h"
+#include "opt_ddb.h"
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/lock.h>
#include <sys/proc.h>
+#include <sys/rwlock.h>
#include <sys/malloc.h>
-#include <sys/msgbuf.h>
-#include <sys/mutex.h>
#include <sys/vmmeter.h>
+#include <sys/malloc.h>
#include <sys/mman.h>
-#include <sys/rwlock.h>
+#include <sys/sf_buf.h>
#include <sys/smp.h>
#include <sys/sched.h>
#include <sys/sysctl.h>
+#ifdef SMP
+#include <sys/smp.h>
+#else
+#include <sys/cpuset.h>
+#endif
+
+#ifdef DDB
+#include <ddb/ddb.h>
+#endif
+
+#include <machine/physmem.h>
+#include <machine/vmparam.h>
#include <vm/vm.h>
-#include <vm/vm_param.h>
#include <vm/uma.h>
#include <vm/pmap.h>
+#include <vm/vm_param.h>
#include <vm/vm_kern.h>
#include <vm/vm_object.h>
#include <vm/vm_map.h>
@@ -175,4012 +135,2674 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_phys.h>
#include <vm/vm_extern.h>
#include <vm/vm_reserv.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <machine/md_var.h>
+#include <machine/pmap_var.h>
#include <machine/cpu.h>
-#include <machine/cpufunc.h>
#include <machine/pcb.h>
+#include <machine/sf_buf.h>
+#ifdef SMP
+#include <machine/smp.h>
+#endif
-#ifdef DEBUG
-extern int last_fault_code;
+#ifndef PMAP_SHPGPERPROC
+#define PMAP_SHPGPERPROC 200
+#endif
+
+#ifndef DIAGNOSTIC
+#define PMAP_INLINE __inline
+#else
+#define PMAP_INLINE
#endif
#ifdef PMAP_DEBUG
+static void pmap_zero_page_check(vm_page_t m);
+void pmap_debug(int level);
+int pmap_pid_dump(int pid);
+
#define PDEBUG(_lev_,_stat_) \
- if (pmap_debug_level >= (_lev_)) \
- ((_stat_))
+ if (pmap_debug_level >= (_lev_)) \
+ ((_stat_))
#define dprintf printf
-
-int pmap_debug_level = 0;
-#define PMAP_INLINE
+int pmap_debug_level = 1;
#else /* PMAP_DEBUG */
#define PDEBUG(_lev_,_stat_) /* Nothing */
#define dprintf(x, arg...)
-#define PMAP_INLINE __inline
#endif /* PMAP_DEBUG */
+/*
+ * Level 2 page tables map definion ('max' is excluded).
+ */
+
+#define PT2V_MIN_ADDRESS ((vm_offset_t)PT2MAP)
+#define PT2V_MAX_ADDRESS ((vm_offset_t)PT2MAP + PT2MAP_SIZE)
+
+#define UPT2V_MIN_ADDRESS ((vm_offset_t)PT2MAP)
+#define UPT2V_MAX_ADDRESS \
+ ((vm_offset_t)(PT2MAP + (KERNBASE >> PT2MAP_SHIFT)))
+
+/*
+ * Promotion to a 1MB (PTE1) page mapping requires that the corresponding
+ * 4KB (PTE2) page mappings have identical settings for the following fields:
+ */
+#define PTE2_PROMOTE (PTE2_V | PTE2_A | PTE2_NM | PTE2_S | PTE2_NG | \
+ PTE2_NX | PTE2_RO | PTE2_U | PTE2_W | \
+ PTE2_ATTR_MASK)
+
+#define PTE1_PROMOTE (PTE1_V | PTE1_A | PTE1_NM | PTE1_S | PTE1_NG | \
+ PTE1_NX | PTE1_RO | PTE1_U | PTE1_W | \
+ PTE1_ATTR_MASK)
+
+#define ATTR_TO_L1(l2_attr) ((((l2_attr) & L2_TEX0) ? L1_S_TEX0 : 0) | \
+ (((l2_attr) & L2_C) ? L1_S_C : 0) | \
+ (((l2_attr) & L2_B) ? L1_S_B : 0) | \
+ (((l2_attr) & PTE2_A) ? PTE1_A : 0) | \
+ (((l2_attr) & PTE2_NM) ? PTE1_NM : 0) | \
+ (((l2_attr) & PTE2_S) ? PTE1_S : 0) | \
+ (((l2_attr) & PTE2_NG) ? PTE1_NG : 0) | \
+ (((l2_attr) & PTE2_NX) ? PTE1_NX : 0) | \
+ (((l2_attr) & PTE2_RO) ? PTE1_RO : 0) | \
+ (((l2_attr) & PTE2_U) ? PTE1_U : 0) | \
+ (((l2_attr) & PTE2_W) ? PTE1_W : 0))
+
+#define ATTR_TO_L2(l1_attr) ((((l1_attr) & L1_S_TEX0) ? L2_TEX0 : 0) | \
+ (((l1_attr) & L1_S_C) ? L2_C : 0) | \
+ (((l1_attr) & L1_S_B) ? L2_B : 0) | \
+ (((l1_attr) & PTE1_A) ? PTE2_A : 0) | \
+ (((l1_attr) & PTE1_NM) ? PTE2_NM : 0) | \
+ (((l1_attr) & PTE1_S) ? PTE2_S : 0) | \
+ (((l1_attr) & PTE1_NG) ? PTE2_NG : 0) | \
+ (((l1_attr) & PTE1_NX) ? PTE2_NX : 0) | \
+ (((l1_attr) & PTE1_RO) ? PTE2_RO : 0) | \
+ (((l1_attr) & PTE1_U) ? PTE2_U : 0) | \
+ (((l1_attr) & PTE1_W) ? PTE2_W : 0))
+
+/*
+ * PTE2 descriptors creation macros.
+ */
+#define PTE2_ATTR_DEFAULT vm_memattr_to_pte2(VM_MEMATTR_DEFAULT)
+#define PTE2_ATTR_PT vm_memattr_to_pte2(pt_memattr)
+
+#define PTE2_KPT(pa) PTE2_KERN(pa, PTE2_AP_KRW, PTE2_ATTR_PT)
+#define PTE2_KPT_NG(pa) PTE2_KERN_NG(pa, PTE2_AP_KRW, PTE2_ATTR_PT)
+
+#define PTE2_KRW(pa) PTE2_KERN(pa, PTE2_AP_KRW, PTE2_ATTR_DEFAULT)
+#define PTE2_KRO(pa) PTE2_KERN(pa, PTE2_AP_KR, PTE2_ATTR_DEFAULT)
+
+#define PV_STATS
#ifdef PV_STATS
#define PV_STAT(x) do { x ; } while (0)
#else
#define PV_STAT(x) do { } while (0)
#endif
-#define pa_to_pvh(pa) (&pv_table[pa_index(pa)])
-
-#ifdef ARM_L2_PIPT
-#define pmap_l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range((pa), (size))
-#define pmap_l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range((pa), (size))
-#else
-#define pmap_l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range((va), (size))
-#define pmap_l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range((va), (size))
-#endif
-
-extern struct pv_addr systempage;
-
/*
- * Internal function prototypes
+ * The boot_pt1 is used temporary in very early boot stage as L1 page table.
+ * We can init many things with no memory allocation thanks to its static
+ * allocation and this brings two main advantages:
+ * (1) other cores can be started very simply,
+ * (2) various boot loaders can be supported as its arguments can be processed
+ * in virtual address space and can be moved to safe location before
+ * first allocation happened.
+ * Only disadvantage is that boot_pt1 is used only in very early boot stage.
+ * However, the table is uninitialized and so lays in bss. Therefore kernel
+ * image size is not influenced.
+ *
+ * QQQ: In the future, maybe, boot_pt1 can be used for soft reset and
+ * CPU suspend/resume game.
*/
+extern pt1_entry_t boot_pt1[];
+
+vm_paddr_t base_pt1;
+pt1_entry_t *kern_pt1;
+pt2_entry_t *kern_pt2tab;
+pt2_entry_t *PT2MAP;
-static PMAP_INLINE
-struct pv_entry *pmap_find_pv(struct md_page *, pmap_t, vm_offset_t);
-static void pmap_free_pv_chunk(struct pv_chunk *pc);
-static void pmap_free_pv_entry(pmap_t pmap, pv_entry_t pv);
-static pv_entry_t pmap_get_pv_entry(pmap_t pmap, boolean_t try);
-static vm_page_t pmap_pv_reclaim(pmap_t locked_pmap);
-static boolean_t pmap_pv_insert_section(pmap_t, vm_offset_t,
- vm_paddr_t);
-static struct pv_entry *pmap_remove_pv(struct vm_page *, pmap_t, vm_offset_t);
-static int pmap_pvh_wired_mappings(struct md_page *, int);
-
-static int pmap_enter_locked(pmap_t, vm_offset_t, vm_page_t,
- vm_prot_t, u_int);
-static vm_paddr_t pmap_extract_locked(pmap_t pmap, vm_offset_t va);
-static void pmap_alloc_l1(pmap_t);
-static void pmap_free_l1(pmap_t);
-
-static void pmap_map_section(pmap_t, vm_offset_t, vm_offset_t,
- vm_prot_t, boolean_t);
-static void pmap_promote_section(pmap_t, vm_offset_t);
-static boolean_t pmap_demote_section(pmap_t, vm_offset_t);
-static boolean_t pmap_enter_section(pmap_t, vm_offset_t, vm_page_t,
- vm_prot_t);
-static void pmap_remove_section(pmap_t, vm_offset_t);
-
-static int pmap_clearbit(struct vm_page *, u_int);
-
-static struct l2_bucket *pmap_get_l2_bucket(pmap_t, vm_offset_t);
-static struct l2_bucket *pmap_alloc_l2_bucket(pmap_t, vm_offset_t);
-static void pmap_free_l2_bucket(pmap_t, struct l2_bucket *, u_int);
-static vm_offset_t kernel_pt_lookup(vm_paddr_t);
-
-static MALLOC_DEFINE(M_VMPMAP, "pmap", "PMAP L1");
+static uint32_t ttb_flags;
+static vm_memattr_t pt_memattr;
+ttb_entry_t pmap_kern_ttb;
+
+struct pmap kernel_pmap_store;
+LIST_HEAD(pmaplist, pmap);
+static struct pmaplist allpmaps;
+static struct mtx allpmaps_lock;
vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */
vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */
-vm_offset_t pmap_curmaxkvaddr;
+
+static vm_offset_t kernel_vm_end_new;
+vm_offset_t kernel_vm_end = KERNBASE + NKPT2PG * NPT2_IN_PG * PTE1_SIZE;
+vm_offset_t vm_max_kernel_address;
vm_paddr_t kernel_l1pa;
-vm_offset_t kernel_vm_end = 0;
+static struct rwlock __aligned(CACHE_LINE_SIZE) pvh_global_lock;
-vm_offset_t vm_max_kernel_address;
+/*
+ * Data for the pv entry allocation mechanism
+ */
+static TAILQ_HEAD(pch, pv_chunk) pv_chunks = TAILQ_HEAD_INITIALIZER(pv_chunks);
+static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0;
+static struct md_page *pv_table; /* XXX: Is it used only the list in md_page? */
+static int shpgperproc = PMAP_SHPGPERPROC;
-struct pmap kernel_pmap_store;
+struct pv_chunk *pv_chunkbase; /* KVA block for pv_chunks */
+int pv_maxchunks; /* How many chunks we have KVA for */
+vm_offset_t pv_vafree; /* freelist stored in the PTE */
+
+vm_paddr_t first_managed_pa;
+#define pa_to_pvh(pa) (&pv_table[pte1_index(pa - first_managed_pa)])
/*
- * Resources for quickly copying and zeroing pages using virtual address space
- * and page table entries that are pre-allocated per-CPU by pmap_init().
+ * All those kernel PT submaps that BSD is so fond of
*/
-struct czpages {
- struct mtx lock;
- pt_entry_t *srcptep;
- pt_entry_t *dstptep;
- vm_offset_t srcva;
- vm_offset_t dstva;
+struct sysmaps {
+ struct mtx lock;
+ pt2_entry_t *CMAP1;
+ pt2_entry_t *CMAP2;
+ pt2_entry_t *CMAP3;
+ caddr_t CADDR1;
+ caddr_t CADDR2;
+ caddr_t CADDR3;
};
-static struct czpages cpu_czpages[MAXCPU];
+static struct sysmaps sysmaps_pcpu[MAXCPU];
+static pt2_entry_t *CMAP3;
+static caddr_t CADDR3;
+caddr_t _tmppt = 0;
+
+struct msgbuf *msgbufp = 0; /* XXX move it to machdep.c */
-static void pmap_init_l1(struct l1_ttable *, pd_entry_t *);
/*
- * These routines are called when the CPU type is identified to set up
- * the PTE prototypes, cache modes, etc.
- *
- * The variables are always here, just in case LKMs need to reference
- * them (though, they shouldn't).
+ * Crashdump maps.
*/
-static void pmap_set_prot(pt_entry_t *pte, vm_prot_t prot, uint8_t user);
-pt_entry_t pte_l1_s_cache_mode;
-pt_entry_t pte_l1_s_cache_mode_pt;
+static caddr_t crashdumpmap;
-pt_entry_t pte_l2_l_cache_mode;
-pt_entry_t pte_l2_l_cache_mode_pt;
+static pt2_entry_t *PMAP1 = 0, *PMAP2;
+static pt2_entry_t *PADDR1 = 0, *PADDR2;
+#ifdef DDB
+static pt2_entry_t *PMAP3;
+static pt2_entry_t *PADDR3;
+static int PMAP3cpu __unused; /* for SMP only */
+#endif
+#ifdef SMP
+static int PMAP1cpu;
+static int PMAP1changedcpu;
+SYSCTL_INT(_debug, OID_AUTO, PMAP1changedcpu, CTLFLAG_RD,
+ &PMAP1changedcpu, 0,
+ "Number of times pmap_pte2_quick changed CPU with same PMAP1");
+#endif
+static int PMAP1changed;
+SYSCTL_INT(_debug, OID_AUTO, PMAP1changed, CTLFLAG_RD,
+ &PMAP1changed, 0,
+ "Number of times pmap_pte2_quick changed PMAP1");
+static int PMAP1unchanged;
+SYSCTL_INT(_debug, OID_AUTO, PMAP1unchanged, CTLFLAG_RD,
+ &PMAP1unchanged, 0,
+ "Number of times pmap_pte2_quick didn't change PMAP1");
+static struct mtx PMAP2mutex;
+
+static __inline void pt2_wirecount_init(vm_page_t m);
+static boolean_t pmap_demote_pte1(pmap_t pmap, pt1_entry_t *pte1p,
+ vm_offset_t va);
+void cache_icache_sync_fresh(vm_offset_t va, vm_paddr_t pa, vm_size_t size);
-pt_entry_t pte_l2_s_cache_mode;
-pt_entry_t pte_l2_s_cache_mode_pt;
+/*
+ * Function to set the debug level of the pmap code.
+ */
+#ifdef PMAP_DEBUG
+void
+pmap_debug(int level)
+{
-struct msgbuf *msgbufp = 0;
+ pmap_debug_level = level;
+ dprintf("pmap_debug: level=%d\n", pmap_debug_level);
+}
+#endif /* PMAP_DEBUG */
/*
- * Crashdump maps.
+ * This table must corespond with memory attribute configuration in vm.h.
+ * First entry is used for normal system mapping.
+ *
+ * Device memory is always marked as shared.
+ * Normal memory is shared only in SMP .
+ * Not outer shareable bits are not used yet.
+ * Class 6 cannot be used on ARM11.
*/
-static caddr_t crashdumpmap;
+#define TEXDEF_TYPE_SHIFT 0
+#define TEXDEF_TYPE_MASK 0x3
+#define TEXDEF_INNER_SHIFT 2
+#define TEXDEF_INNER_MASK 0x3
+#define TEXDEF_OUTER_SHIFT 4
+#define TEXDEF_OUTER_MASK 0x3
+#define TEXDEF_NOS_SHIFT 6
+#define TEXDEF_NOS_MASK 0x1
+
+#define TEX(t, i, o, s) \
+ ((t) << TEXDEF_TYPE_SHIFT) | \
+ ((i) << TEXDEF_INNER_SHIFT) | \
+ ((o) << TEXDEF_OUTER_SHIFT | \
+ ((s) << TEXDEF_NOS_SHIFT))
+
+static uint32_t tex_class[8] = {
+/* type inner cache outer cache */
+ TEX(PRRR_MEM, NMRR_WB_WA, NMRR_WB_WA, 0), /* 0 - ATTR_WB_WA */
+ TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 1 - ATTR_NOCACHE */
+ TEX(PRRR_DEV, NMRR_NC, NMRR_NC, 0), /* 2 - ATTR_DEVICE */
+ TEX(PRRR_SO, NMRR_NC, NMRR_NC, 0), /* 3 - ATTR_SO */
+ TEX(PRRR_MEM, NMRR_WT, NMRR_WT, 0), /* 4 - ATTR_WT */
+ TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 5 - NOT USED YET */
+ TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 6 - NOT USED YET */
+ TEX(PRRR_MEM, NMRR_NC, NMRR_NC, 0), /* 7 - NOT USED YET */
+};
+#undef TEX
+
+static uint32_t pte2_attr_tab[8] = {
+ PTE2_ATTR_WB_WA, /* 0 - VM_MEMATTR_WB_WA */
+ PTE2_ATTR_NOCACHE, /* 1 - VM_MEMATTR_NOCACHE */
+ PTE2_ATTR_DEVICE, /* 2 - VM_MEMATTR_DEVICE */
+ PTE2_ATTR_SO, /* 3 - VM_MEMATTR_SO */
+ PTE2_ATTR_WT, /* 4 - VM_MEMATTR_WRITE_THROUGH */
+ 0, /* 5 - NOT USED YET */
+ 0, /* 6 - NOT USED YET */
+ 0 /* 7 - NOT USED YET */
+};
+CTASSERT(VM_MEMATTR_WB_WA == 0);
+CTASSERT(VM_MEMATTR_NOCACHE == 1);
+CTASSERT(VM_MEMATTR_DEVICE == 2);
+CTASSERT(VM_MEMATTR_SO == 3);
+CTASSERT(VM_MEMATTR_WRITE_THROUGH == 4);
+
+static inline uint32_t
+vm_memattr_to_pte2(vm_memattr_t ma)
+{
-extern void bcopy_page(vm_offset_t, vm_offset_t);
-extern void bzero_page(vm_offset_t);
+ KASSERT((u_int)ma < 5, ("%s: bad vm_memattr_t %d", __func__, ma));
+ return (pte2_attr_tab[(u_int)ma]);
+}
-char *_tmppt;
+static inline uint32_t
+vm_page_pte2_attr(vm_page_t m)
+{
+
+ return (vm_memattr_to_pte2(m->md.pat_mode));
+}
/*
- * Metadata for L1 translation tables.
+ * Convert TEX definition entry to TTB flags.
*/
-struct l1_ttable {
- /* Entry on the L1 Table list */
- SLIST_ENTRY(l1_ttable) l1_link;
+static uint32_t
+encode_ttb_flags(int idx)
+{
+ uint32_t inner, outer, nos, reg;
+
+ inner = (tex_class[idx] >> TEXDEF_INNER_SHIFT) &
+ TEXDEF_INNER_MASK;
+ outer = (tex_class[idx] >> TEXDEF_OUTER_SHIFT) &
+ TEXDEF_OUTER_MASK;
+ nos = (tex_class[idx] >> TEXDEF_NOS_SHIFT) &
+ TEXDEF_NOS_MASK;
+
+ reg = nos << 5;
+ reg |= outer << 3;
+ if (cpuinfo.coherent_walk)
+ reg |= (inner & 0x1) << 6;
+ reg |= (inner & 0x2) >> 1;
+#ifdef SMP
+ reg |= 1 << 1;
+#endif
+ return reg;
+}
- /* Entry on the L1 Least Recently Used list */
- TAILQ_ENTRY(l1_ttable) l1_lru;
+/*
+ * Set TEX remapping registers in current CPU.
+ */
+void
+pmap_set_tex(void)
+{
+ uint32_t prrr, nmrr;
+ uint32_t type, inner, outer, nos;
+ int i;
- /* Track how many domains are allocated from this L1 */
- volatile u_int l1_domain_use_count;
+#ifdef PMAP_PTE_NOCACHE
+ /* XXX fixme */
+ if (cpuinfo.coherent_walk) {
+ pt_memattr = VM_MEMATTR_WB_WA;
+ ttb_flags = encode_ttb_flags(0);
+ }
+ else {
+ pt_memattr = VM_MEMATTR_NOCACHE;
+ ttb_flags = encode_ttb_flags(1);
+ }
+#else
+ pt_memattr = VM_MEMATTR_WB_WA;
+ ttb_flags = encode_ttb_flags(0);
+#endif
- /*
- * A free-list of domain numbers for this L1.
- * We avoid using ffs() and a bitmap to track domains since ffs()
- * is slow on ARM.
- */
- u_int8_t l1_domain_first;
- u_int8_t l1_domain_free[PMAP_DOMAINS];
+ prrr = 0;
+ nmrr = 0;
+
+ /* Build remapping register from TEX classes. */
+ for (i = 0; i < 8; i++) {
+ type = (tex_class[i] >> TEXDEF_TYPE_SHIFT) &
+ TEXDEF_TYPE_MASK;
+ inner = (tex_class[i] >> TEXDEF_INNER_SHIFT) &
+ TEXDEF_INNER_MASK;
+ outer = (tex_class[i] >> TEXDEF_OUTER_SHIFT) &
+ TEXDEF_OUTER_MASK;
+ nos = (tex_class[i] >> TEXDEF_NOS_SHIFT) &
+ TEXDEF_NOS_MASK;
+
+ prrr |= type << (i * 2);
+ prrr |= nos << (i + 24);
+ nmrr |= inner << (i * 2);
+ nmrr |= outer << (i * 2 + 16);
+ }
+ /* Add shareable bits for device memory. */
+ prrr |= PRRR_DS0 | PRRR_DS1;
- /* Physical address of this L1 page table */
- vm_paddr_t l1_physaddr;
+ /* Add shareable bits for normal memory in SMP case. */
+#ifdef SMP
+ prrr |= PRRR_NS1;
+#endif
+ cp15_prrr_set(prrr);
+ cp15_nmrr_set(nmrr);
- /* KVA of this L1 page table */
- pd_entry_t *l1_kva;
-};
+ /* Caches are disabled, so full TLB flush should be enough. */
+ tlb_flush_all_local();
+}
/*
- * Convert a virtual address into its L1 table index. That is, the
- * index used to locate the L2 descriptor table pointer in an L1 table.
- * This is basically used to index l1->l1_kva[].
- *
- * Each L2 descriptor table represents 1MB of VA space.
+ * KERNBASE must be multiple of NPT2_IN_PG * PTE1_SIZE. In other words,
+ * KERNBASE is mapped by first L2 page table in L2 page table page. It
+ * meets same constrain due to PT2MAP being placed just under KERNBASE.
*/
-#define L1_IDX(va) (((vm_offset_t)(va)) >> L1_S_SHIFT)
+CTASSERT((KERNBASE & (NPT2_IN_PG * PTE1_SIZE - 1)) == 0);
+CTASSERT((KERNBASE - VM_MAXUSER_ADDRESS) >= PT2MAP_SIZE);
/*
- * L1 Page Tables are tracked using a Least Recently Used list.
- * - New L1s are allocated from the HEAD.
- * - Freed L1s are added to the TAIl.
- * - Recently accessed L1s (where an 'access' is some change to one of
- * the userland pmaps which owns this L1) are moved to the TAIL.
+ * In crazy dreams, PAGE_SIZE could be a multiple of PTE2_SIZE in general.
+ * For now, anyhow, the following check must be fulfilled.
*/
-static TAILQ_HEAD(, l1_ttable) l1_lru_list;
+CTASSERT(PAGE_SIZE == PTE2_SIZE);
/*
- * A list of all L1 tables
+ * We don't want to mess up MI code with all MMU and PMAP definitions,
+ * so some things, which depend on other ones, are defined independently.
+ * Now, it is time to check that we don't screw up something.
*/
-static SLIST_HEAD(, l1_ttable) l1_list;
-static struct mtx l1_lru_lock;
-
+CTASSERT(PDRSHIFT == PTE1_SHIFT);
/*
- * The l2_dtable tracks L2_BUCKET_SIZE worth of L1 slots.
- *
- * This is normally 16MB worth L2 page descriptors for any given pmap.
- * Reference counts are maintained for L2 descriptors so they can be
- * freed when empty.
+ * Check L1 and L2 page table entries definitions consistency.
*/
-struct l2_dtable {
- /* The number of L2 page descriptors allocated to this l2_dtable */
- u_int l2_occupancy;
-
- /* List of L2 page descriptors */
- struct l2_bucket {
- pt_entry_t *l2b_kva; /* KVA of L2 Descriptor Table */
- vm_paddr_t l2b_phys; /* Physical address of same */
- u_short l2b_l1idx; /* This L2 table's L1 index */
- u_short l2b_occupancy; /* How many active descriptors */
- } l2_bucket[L2_BUCKET_SIZE];
-};
-
-/* pmap_kenter_internal flags */
-#define KENTER_CACHE 0x1
-#define KENTER_DEVICE 0x2
-#define KENTER_USER 0x4
-
+CTASSERT(NB_IN_PT1 == (sizeof(pt1_entry_t) * NPTE1_IN_PT1));
+CTASSERT(NB_IN_PT2 == (sizeof(pt2_entry_t) * NPTE2_IN_PT2));
/*
- * Given an L1 table index, calculate the corresponding l2_dtable index
- * and bucket index within the l2_dtable.
+ * Check L2 page tables page consistency.
*/
-#define L2_IDX(l1idx) (((l1idx) >> L2_BUCKET_LOG2) & \
- (L2_SIZE - 1))
-#define L2_BUCKET(l1idx) ((l1idx) & (L2_BUCKET_SIZE - 1))
-
+CTASSERT(PAGE_SIZE == (NPT2_IN_PG * NB_IN_PT2));
+CTASSERT((1 << PT2PG_SHIFT) == NPT2_IN_PG);
/*
- * Given a virtual address, this macro returns the
- * virtual address required to drop into the next L2 bucket.
+ * Check PT2TAB consistency.
+ * PT2TAB_ENTRIES is defined as a division of NPTE1_IN_PT1 by NPT2_IN_PG.
+ * This should be done without remainder.
*/
-#define L2_NEXT_BUCKET(va) (((va) & L1_S_FRAME) + L1_S_SIZE)
+CTASSERT(NPTE1_IN_PT1 == (PT2TAB_ENTRIES * NPT2_IN_PG));
/*
- * We try to map the page tables write-through, if possible. However, not
- * all CPUs have a write-through cache mode, so on those we have to sync
- * the cache when we frob page tables.
+ * A PT2MAP magic.
*
- * We try to evaluate this at compile time, if possible. However, it's
- * not always possible to do that, hence this run-time var.
+ * All level 2 page tables (PT2s) are mapped continuously and accordingly
+ * into PT2MAP address space. As PT2 size is less than PAGE_SIZE, this can
+ * be done only if PAGE_SIZE is a multiple of PT2 size. All PT2s in one page
+ * must be used together, but not necessary at once. The first PT2 in a page
+ * must map things on correctly aligned address and the others must follow
+ * in right order.
*/
-int pmap_needs_pte_sync;
+#define NB_IN_PT2TAB (PT2TAB_ENTRIES * sizeof(pt2_entry_t))
+#define NPT2_IN_PT2TAB (NB_IN_PT2TAB / NB_IN_PT2)
+#define NPG_IN_PT2TAB (NB_IN_PT2TAB / PAGE_SIZE)
/*
- * Macro to determine if a mapping might be resident in the
- * instruction cache and/or TLB
+ * Check PT2TAB consistency.
+ * NPT2_IN_PT2TAB is defined as a division of NB_IN_PT2TAB by NB_IN_PT2.
+ * NPG_IN_PT2TAB is defined as a division of NB_IN_PT2TAB by PAGE_SIZE.
+ * The both should be done without remainder.
*/
-#define PTE_BEEN_EXECD(pte) (L2_S_EXECUTABLE(pte) && L2_S_REFERENCED(pte))
-
+CTASSERT(NB_IN_PT2TAB == (NPT2_IN_PT2TAB * NB_IN_PT2));
+CTASSERT(NB_IN_PT2TAB == (NPG_IN_PT2TAB * PAGE_SIZE));
/*
- * Macro to determine if a mapping might be resident in the
- * data cache and/or TLB
+ * The implementation was made general, however, with the assumption
+ * bellow in mind. In case of another value of NPG_IN_PT2TAB,
+ * the code should be once more rechecked.
*/
-#define PTE_BEEN_REFD(pte) (L2_S_REFERENCED(pte))
-
-#ifndef PMAP_SHPGPERPROC
-#define PMAP_SHPGPERPROC 200
-#endif
-
-#define pmap_is_current(pm) ((pm) == pmap_kernel() || \
- curproc->p_vmspace->vm_map.pmap == (pm))
+CTASSERT(NPG_IN_PT2TAB == 1);
/*
- * Data for the pv entry allocation mechanism
+ * Get offset of PT2 in a page
+ * associated with given PT1 index.
*/
-static TAILQ_HEAD(pch, pv_chunk) pv_chunks = TAILQ_HEAD_INITIALIZER(pv_chunks);
-static int pv_entry_count, pv_entry_max, pv_entry_high_water;
-static struct md_page *pv_table;
-static int shpgperproc = PMAP_SHPGPERPROC;
-
-struct pv_chunk *pv_chunkbase; /* KVA block for pv_chunks */
-int pv_maxchunks; /* How many chunks we have KVA for */
-vm_offset_t pv_vafree; /* Freelist stored in the PTE */
-
-static __inline struct pv_chunk *
-pv_to_chunk(pv_entry_t pv)
+static __inline u_int
+page_pt2off(u_int pt1_idx)
{
- return ((struct pv_chunk *)((uintptr_t)pv & ~(uintptr_t)PAGE_MASK));
+ return ((pt1_idx & PT2PG_MASK) * NB_IN_PT2);
}
-#define PV_PMAP(pv) (pv_to_chunk(pv)->pc_pmap)
-
-CTASSERT(sizeof(struct pv_chunk) == PAGE_SIZE);
-CTASSERT(_NPCM == 8);
-CTASSERT(_NPCPV == 252);
-
-#define PC_FREE0_6 0xfffffffful /* Free values for index 0 through 6 */
-#define PC_FREE7 0x0ffffffful /* Free values for index 7 */
-
-static const uint32_t pc_freemask[_NPCM] = {
- PC_FREE0_6, PC_FREE0_6, PC_FREE0_6,
- PC_FREE0_6, PC_FREE0_6, PC_FREE0_6,
- PC_FREE0_6, PC_FREE7
-};
-
-static SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
-
-/* Superpages utilization enabled = 1 / disabled = 0 */
-static int sp_enabled = 1;
-SYSCTL_INT(_vm_pmap, OID_AUTO, sp_enabled, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &sp_enabled, 0,
- "Are large page mappings enabled?");
-
-SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_count, CTLFLAG_RD, &pv_entry_count, 0,
- "Current number of pv entries");
-
-#ifdef PV_STATS
-static int pc_chunk_count, pc_chunk_allocs, pc_chunk_frees, pc_chunk_tryfail;
-
-SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_count, CTLFLAG_RD, &pc_chunk_count, 0,
- "Current number of pv entry chunks");
-SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_allocs, CTLFLAG_RD, &pc_chunk_allocs, 0,
- "Current number of pv entry chunks allocated");
-SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_frees, CTLFLAG_RD, &pc_chunk_frees, 0,
- "Current number of pv entry chunks frees");
-SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_tryfail, CTLFLAG_RD, &pc_chunk_tryfail, 0,
- "Number of times tried to get a chunk page but failed.");
-
-static long pv_entry_frees, pv_entry_allocs;
-static int pv_entry_spare;
-
-SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_frees, CTLFLAG_RD, &pv_entry_frees, 0,
- "Current number of pv entry frees");
-SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_allocs, CTLFLAG_RD, &pv_entry_allocs, 0,
- "Current number of pv entry allocs");
-SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_spare, CTLFLAG_RD, &pv_entry_spare, 0,
- "Current number of spare pv entries");
-#endif
-
-uma_zone_t l2zone;
-static uma_zone_t l2table_zone;
-static vm_offset_t pmap_kernel_l2dtable_kva;
-static vm_offset_t pmap_kernel_l2ptp_kva;
-static vm_paddr_t pmap_kernel_l2ptp_phys;
-static struct rwlock pvh_global_lock;
-
-int l1_mem_types[] = {
- ARM_L1S_STRONG_ORD,
- ARM_L1S_DEVICE_NOSHARE,
- ARM_L1S_DEVICE_SHARE,
- ARM_L1S_NRML_NOCACHE,
- ARM_L1S_NRML_IWT_OWT,
- ARM_L1S_NRML_IWB_OWB,
- ARM_L1S_NRML_IWBA_OWBA
-};
-
-int l2l_mem_types[] = {
- ARM_L2L_STRONG_ORD,
- ARM_L2L_DEVICE_NOSHARE,
- ARM_L2L_DEVICE_SHARE,
- ARM_L2L_NRML_NOCACHE,
- ARM_L2L_NRML_IWT_OWT,
- ARM_L2L_NRML_IWB_OWB,
- ARM_L2L_NRML_IWBA_OWBA
-};
-
-int l2s_mem_types[] = {
- ARM_L2S_STRONG_ORD,
- ARM_L2S_DEVICE_NOSHARE,
- ARM_L2S_DEVICE_SHARE,
- ARM_L2S_NRML_NOCACHE,
- ARM_L2S_NRML_IWT_OWT,
- ARM_L2S_NRML_IWB_OWB,
- ARM_L2S_NRML_IWBA_OWBA
-};
-
/*
- * This list exists for the benefit of pmap_map_chunk(). It keeps track
- * of the kernel L2 tables during bootstrap, so that pmap_map_chunk() can
- * find them as necessary.
- *
- * Note that the data on this list MUST remain valid after initarm() returns,
- * as pmap_bootstrap() uses it to contruct L2 table metadata.
+ * Get physical address of PT2
+ * associated with given PT2s page and PT1 index.
*/
-SLIST_HEAD(, pv_addr) kernel_pt_list = SLIST_HEAD_INITIALIZER(kernel_pt_list);
-
-static void
-pmap_init_l1(struct l1_ttable *l1, pd_entry_t *l1pt)
-{
- int i;
-
- l1->l1_kva = l1pt;
- l1->l1_domain_use_count = 0;
- l1->l1_domain_first = 0;
-
- for (i = 0; i < PMAP_DOMAINS; i++)
- l1->l1_domain_free[i] = i + 1;
-
- /*
- * Copy the kernel's L1 entries to each new L1.
- */
- if (l1pt != pmap_kernel()->pm_l1->l1_kva)
- memcpy(l1pt, pmap_kernel()->pm_l1->l1_kva, L1_TABLE_SIZE);
-
- if ((l1->l1_physaddr = pmap_extract(pmap_kernel(), (vm_offset_t)l1pt)) == 0)
- panic("pmap_init_l1: can't get PA of L1 at %p", l1pt);
- SLIST_INSERT_HEAD(&l1_list, l1, l1_link);
- TAILQ_INSERT_TAIL(&l1_lru_list, l1, l1_lru);
-}
-
-static vm_offset_t
-kernel_pt_lookup(vm_paddr_t pa)
+static __inline vm_paddr_t
+page_pt2pa(vm_paddr_t pgpa, u_int pt1_idx)
{
- struct pv_addr *pv;
-
- SLIST_FOREACH(pv, &kernel_pt_list, pv_list) {
- if (pv->pv_pa == pa)
- return (pv->pv_va);
- }
- return (0);
-}
-
-void
-pmap_pte_init_mmu_v6(void)
-{
-
- if (PTE_PAGETABLE >= 3)
- pmap_needs_pte_sync = 1;
- pte_l1_s_cache_mode = l1_mem_types[PTE_CACHE];
- pte_l2_l_cache_mode = l2l_mem_types[PTE_CACHE];
- pte_l2_s_cache_mode = l2s_mem_types[PTE_CACHE];
-
- pte_l1_s_cache_mode_pt = l1_mem_types[PTE_PAGETABLE];
- pte_l2_l_cache_mode_pt = l2l_mem_types[PTE_PAGETABLE];
- pte_l2_s_cache_mode_pt = l2s_mem_types[PTE_PAGETABLE];
+ return (pgpa + page_pt2off(pt1_idx));
}
/*
- * Allocate an L1 translation table for the specified pmap.
- * This is called at pmap creation time.
+ * Get first entry of PT2
+ * associated with given PT2s page and PT1 index.
*/
-static void
-pmap_alloc_l1(pmap_t pmap)
+static __inline pt2_entry_t *
+page_pt2(vm_offset_t pgva, u_int pt1_idx)
{
- struct l1_ttable *l1;
- u_int8_t domain;
-
- /*
- * Remove the L1 at the head of the LRU list
- */
- mtx_lock(&l1_lru_lock);
- l1 = TAILQ_FIRST(&l1_lru_list);
- TAILQ_REMOVE(&l1_lru_list, l1, l1_lru);
- /*
- * Pick the first available domain number, and update
- * the link to the next number.
- */
- domain = l1->l1_domain_first;
- l1->l1_domain_first = l1->l1_domain_free[domain];
-
- /*
- * If there are still free domain numbers in this L1,
- * put it back on the TAIL of the LRU list.
- */
- if (++l1->l1_domain_use_count < PMAP_DOMAINS)
- TAILQ_INSERT_TAIL(&l1_lru_list, l1, l1_lru);
-
- mtx_unlock(&l1_lru_lock);
-
- /*
- * Fix up the relevant bits in the pmap structure
- */
- pmap->pm_l1 = l1;
- pmap->pm_domain = domain + 1;
+ return ((pt2_entry_t *)(pgva + page_pt2off(pt1_idx)));
}
/*
- * Free an L1 translation table.
- * This is called at pmap destruction time.
+ * Get virtual address of PT2s page (mapped in PT2MAP)
+ * which holds PT2 which holds entry which maps given virtual address.
*/
-static void
-pmap_free_l1(pmap_t pmap)
+static __inline vm_offset_t
+pt2map_pt2pg(vm_offset_t va)
{
- struct l1_ttable *l1 = pmap->pm_l1;
- mtx_lock(&l1_lru_lock);
+ va &= ~(NPT2_IN_PG * PTE1_SIZE - 1);
+ return ((vm_offset_t)pt2map_entry(va));
+}
- /*
- * If this L1 is currently on the LRU list, remove it.
- */
- if (l1->l1_domain_use_count < PMAP_DOMAINS)
- TAILQ_REMOVE(&l1_lru_list, l1, l1_lru);
+/*****************************************************************************
+ *
+ * THREE pmap initialization milestones exist:
+ *
+ * locore.S
+ * -> fundamental init (including MMU) in ASM
+ *
+ * initarm()
+ * -> fundamental init continues in C
+ * -> first available physical address is known
+ *
+ * pmap_bootstrap_prepare() -> FIRST PMAP MILESTONE (first epoch begins)
+ * -> basic (safe) interface for physical address allocation is made
+ * -> basic (safe) interface for virtual mapping is made
+ * -> limited not SMP coherent work is possible
+ *
+ * -> more fundamental init continues in C
+ * -> locks and some more things are available
+ * -> all fundamental allocations and mappings are done
+ *
+ * pmap_bootstrap() -> SECOND PMAP MILESTONE (second epoch begins)
+ * -> phys_avail[] and virtual_avail is set
+ * -> control is passed to vm subsystem
+ * -> physical and virtual address allocation are off limit
+ * -> low level mapping functions, some SMP coherent,
+ * are available, which cannot be used before vm subsystem
+ * is being inited
+ *
+ * mi_startup()
+ * -> vm subsystem is being inited
+ *
+ * pmap_init() -> THIRD PMAP MILESTONE (third epoch begins)
+ * -> pmap is fully inited
+ *
+ *****************************************************************************/
- /*
- * Free up the domain number which was allocated to the pmap
- */
- l1->l1_domain_free[pmap->pm_domain - 1] = l1->l1_domain_first;
- l1->l1_domain_first = pmap->pm_domain - 1;
- l1->l1_domain_use_count--;
+/*****************************************************************************
+ *
+ * PMAP first stage initialization and utility functions
+ * for pre-bootstrap epoch.
+ *
+ * After pmap_bootstrap_prepare() is called, the following functions
+ * can be used:
+ *
+ * (1) strictly only for this stage functions for physical page allocations,
+ * virtual space allocations, and mappings:
+ *
+ * vm_paddr_t pmap_preboot_get_pages(u_int num);
+ * void pmap_preboot_map_pages(vm_paddr_t pa, vm_offset_t va, u_int num);
+ * vm_offset_t pmap_preboot_reserve_pages(u_int num);
+ * vm_offset_t pmap_preboot_get_vpages(u_int num);
+ * void pmap_preboot_map_attr(vm_paddr_t pa, vm_offset_t va, vm_size_t size,
+ * vm_prot_t prot, vm_memattr_t attr);
+ *
+ * (2) for all stages:
+ *
+ * vm_paddr_t pmap_kextract(vm_offset_t va);
+ *
+ * NOTE: This is not SMP coherent stage.
+ *
+ *****************************************************************************/
- /*
- * The L1 now must have at least 1 free domain, so add
- * it back to the LRU list. If the use count is zero,
- * put it at the head of the list, otherwise it goes
- * to the tail.
- */
- if (l1->l1_domain_use_count == 0) {
- TAILQ_INSERT_HEAD(&l1_lru_list, l1, l1_lru);
- } else
- TAILQ_INSERT_TAIL(&l1_lru_list, l1, l1_lru);
+#define KERNEL_P2V(pa) \
+ ((vm_offset_t)((pa) - arm_physmem_kernaddr + KERNVIRTADDR))
+#define KERNEL_V2P(va) \
+ ((vm_paddr_t)((va) - KERNVIRTADDR + arm_physmem_kernaddr))
- mtx_unlock(&l1_lru_lock);
-}
+static vm_paddr_t last_paddr;
/*
- * Returns a pointer to the L2 bucket associated with the specified pmap
- * and VA, or NULL if no L2 bucket exists for the address.
+ * Pre-bootstrap epoch page allocator.
*/
-static PMAP_INLINE struct l2_bucket *
-pmap_get_l2_bucket(pmap_t pmap, vm_offset_t va)
+vm_paddr_t
+pmap_preboot_get_pages(u_int num)
{
- struct l2_dtable *l2;
- struct l2_bucket *l2b;
- u_short l1idx;
+ vm_paddr_t ret;
- l1idx = L1_IDX(va);
+ ret = last_paddr;
+ last_paddr += num * PAGE_SIZE;
- if ((l2 = pmap->pm_l2[L2_IDX(l1idx)]) == NULL ||
- (l2b = &l2->l2_bucket[L2_BUCKET(l1idx)])->l2b_kva == NULL)
- return (NULL);
-
- return (l2b);
+ return (ret);
}
/*
- * Returns a pointer to the L2 bucket associated with the specified pmap
- * and VA.
+ * The fundamental initalization of PMAP stuff.
+ *
+ * Some things already happened in locore.S and some things could happen
+ * before pmap_bootstrap_prepare() is called, so let's recall what is done:
+ * 1. Caches are disabled.
+ * 2. We are running on virtual addresses already with 'boot_pt1'
+ * as L1 page table.
+ * 3. So far, all virtual addresses can be converted to physical ones and
+ * vice versa by the following macros:
+ * KERNEL_P2V(pa) .... physical to virtual ones,
+ * KERNEL_V2P(va) .... virtual to physical ones.
*
- * If no L2 bucket exists, perform the necessary allocations to put an L2
- * bucket/page table in place.
+ * What is done herein:
+ * 1. The 'boot_pt1' is replaced by real kernel L1 page table 'kern_pt1'.
+ * 2. PT2MAP magic is brought to live.
+ * 3. Basic preboot functions for page allocations and mappings can be used.
+ * 4. Everything is prepared for L1 cache enabling.
*
- * Note that if a new L2 bucket/page was allocated, the caller *must*
- * increment the bucket occupancy counter appropriately *before*
- * releasing the pmap's lock to ensure no other thread or cpu deallocates
- * the bucket/page in the meantime.
+ * Variations:
+ * 1. To use second TTB register, so kernel and users page tables will be
+ * separated. This way process forking - pmap_pinit() - could be faster,
+ * it saves physical pages and KVA per a process, and it's simple change.
+ * However, it will lead, due to hardware matter, to the following:
+ * (a) 2G space for kernel and 2G space for users.
+ * (b) 1G space for kernel in low addresses and 3G for users above it.
+ * A question is: Is the case (b) really an option? Note that case (b)
+ * does save neither physical memory and KVA.
*/
-static struct l2_bucket *
-pmap_alloc_l2_bucket(pmap_t pmap, vm_offset_t va)
+void
+pmap_bootstrap_prepare(vm_paddr_t last)
{
- struct l2_dtable *l2;
- struct l2_bucket *l2b;
- u_short l1idx;
-
- l1idx = L1_IDX(va);
-
- PMAP_ASSERT_LOCKED(pmap);
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- if ((l2 = pmap->pm_l2[L2_IDX(l1idx)]) == NULL) {
- /*
- * No mapping at this address, as there is
- * no entry in the L1 table.
- * Need to allocate a new l2_dtable.
- */
- PMAP_UNLOCK(pmap);
- rw_wunlock(&pvh_global_lock);
- if ((l2 = uma_zalloc(l2table_zone, M_NOWAIT)) == NULL) {
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
- return (NULL);
- }
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
- if (pmap->pm_l2[L2_IDX(l1idx)] != NULL) {
- /*
- * Someone already allocated the l2_dtable while
- * we were doing the same.
- */
- uma_zfree(l2table_zone, l2);
- l2 = pmap->pm_l2[L2_IDX(l1idx)];
- } else {
- bzero(l2, sizeof(*l2));
- /*
- * Link it into the parent pmap
- */
- pmap->pm_l2[L2_IDX(l1idx)] = l2;
- }
- }
-
- l2b = &l2->l2_bucket[L2_BUCKET(l1idx)];
+ vm_paddr_t pt2pg_pa, pt2tab_pa, pa, size;
+ vm_offset_t pt2pg_va;
+ pt1_entry_t *pte1p;
+ pt2_entry_t *pte2p;
+ u_int i;
+ uint32_t actlr_mask, actlr_set, l1_attr;
/*
- * Fetch pointer to the L2 page table associated with the address.
+ * Now, we are going to make real kernel mapping. Note that we are
+ * already running on some mapping made in locore.S and we expect
+ * that it's large enough to ensure nofault access to physical memory
+ * allocated herein before switch.
+ *
+ * As kernel image and everything needed before are and will be mapped
+ * by section mappings, we align last physical address to PTE1_SIZE.
*/
- if (l2b->l2b_kva == NULL) {
- pt_entry_t *ptep;
-
- /*
- * No L2 page table has been allocated. Chances are, this
- * is because we just allocated the l2_dtable, above.
- */
- l2->l2_occupancy++;
- PMAP_UNLOCK(pmap);
- rw_wunlock(&pvh_global_lock);
- ptep = uma_zalloc(l2zone, M_NOWAIT);
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
- if (l2b->l2b_kva != 0) {
- /* We lost the race. */
- l2->l2_occupancy--;
- uma_zfree(l2zone, ptep);
- return (l2b);
- }
- l2b->l2b_phys = vtophys(ptep);
- if (ptep == NULL) {
- /*
- * Oops, no more L2 page tables available at this
- * time. We may need to deallocate the l2_dtable
- * if we allocated a new one above.
- */
- l2->l2_occupancy--;
- if (l2->l2_occupancy == 0) {
- pmap->pm_l2[L2_IDX(l1idx)] = NULL;
- uma_zfree(l2table_zone, l2);
- }
- return (NULL);
- }
-
- l2b->l2b_kva = ptep;
- l2b->l2b_l1idx = l1idx;
- }
-
- return (l2b);
-}
-
-static PMAP_INLINE void
-pmap_free_l2_ptp(pt_entry_t *l2)
-{
- uma_zfree(l2zone, l2);
-}
-/*
- * One or more mappings in the specified L2 descriptor table have just been
- * invalidated.
- *
- * Garbage collect the metadata and descriptor table itself if necessary.
- *
- * The pmap lock must be acquired when this is called (not necessary
- * for the kernel pmap).
- */
-static void
-pmap_free_l2_bucket(pmap_t pmap, struct l2_bucket *l2b, u_int count)
-{
- struct l2_dtable *l2;
- pd_entry_t *pl1pd, l1pd;
- pt_entry_t *ptep;
- u_short l1idx;
-
+ last_paddr = pte1_roundup(last);
/*
- * Update the bucket's reference count according to how many
- * PTEs the caller has just invalidated.
+ * Allocate and zero page(s) for kernel L1 page table.
+ *
+ * Note that it's first allocation on space which was PTE1_SIZE
+ * aligned and as such base_pt1 is aligned to NB_IN_PT1 too.
*/
- l2b->l2b_occupancy -= count;
+ base_pt1 = pmap_preboot_get_pages(NPG_IN_PT1);
+ kern_pt1 = (pt1_entry_t *)KERNEL_P2V(base_pt1);
+ bzero((void*)kern_pt1, NB_IN_PT1);
+ pte1_sync_range(kern_pt1, NB_IN_PT1);
+
+ /* Allocate and zero page(s) for kernel PT2TAB. */
+ pt2tab_pa = pmap_preboot_get_pages(NPG_IN_PT2TAB);
+ kern_pt2tab = (pt2_entry_t *)KERNEL_P2V(pt2tab_pa);
+ bzero(kern_pt2tab, NB_IN_PT2TAB);
+ pte2_sync_range(kern_pt2tab, NB_IN_PT2TAB);
+
+ /* Allocate and zero page(s) for kernel L2 page tables. */
+ pt2pg_pa = pmap_preboot_get_pages(NKPT2PG);
+ pt2pg_va = KERNEL_P2V(pt2pg_pa);
+ size = NKPT2PG * PAGE_SIZE;
+ bzero((void*)pt2pg_va, size);
+ pte2_sync_range((pt2_entry_t *)pt2pg_va, size);
/*
- * Note:
- *
- * Level 2 page tables allocated to the kernel pmap are never freed
- * as that would require checking all Level 1 page tables and
- * removing any references to the Level 2 page table. See also the
- * comment elsewhere about never freeing bootstrap L2 descriptors.
- *
- * We make do with just invalidating the mapping in the L2 table.
- *
- * This isn't really a big deal in practice and, in fact, leads
- * to a performance win over time as we don't need to continually
- * alloc/free.
+ * Add a physical memory segment (vm_phys_seg) corresponding to the
+ * preallocated pages for kernel L2 page tables so that vm_page
+ * structures representing these pages will be created. The vm_page
+ * structures are required for promotion of the corresponding kernel
+ * virtual addresses to section mappings.
*/
- if (l2b->l2b_occupancy > 0 || pmap == pmap_kernel())
- return;
+ vm_phys_add_seg(pt2tab_pa, pmap_preboot_get_pages(0));
/*
- * There are no more valid mappings in this level 2 page table.
- * Go ahead and NULL-out the pointer in the bucket, then
- * free the page table.
+ * Insert allocated L2 page table pages to PT2TAB and make
+ * link to all PT2s in L1 page table. See how kernel_vm_end
+ * is initialized.
+ *
+ * We play simple and safe. So every KVA will have underlaying
+ * L2 page table, even kernel image mapped by sections.
*/
- l1idx = l2b->l2b_l1idx;
- ptep = l2b->l2b_kva;
- l2b->l2b_kva = NULL;
+ pte2p = kern_pt2tab_entry(KERNBASE);
+ for (pa = pt2pg_pa; pa < pt2pg_pa + size; pa += PTE2_SIZE)
+ pt2tab_store(pte2p++, PTE2_KPT(pa));
- pl1pd = &pmap->pm_l1->l1_kva[l1idx];
+ pte1p = kern_pte1(KERNBASE);
+ for (pa = pt2pg_pa; pa < pt2pg_pa + size; pa += NB_IN_PT2)
+ pte1_store(pte1p++, PTE1_LINK(pa));
+
+ /* Make section mappings for kernel. */
+ l1_attr = ATTR_TO_L1(PTE2_ATTR_DEFAULT);
+ pte1p = kern_pte1(KERNBASE);
+ for (pa = KERNEL_V2P(KERNBASE); pa < last; pa += PTE1_SIZE)
+ pte1_store(pte1p++, PTE1_KERN(pa, PTE1_AP_KRW, l1_attr));
/*
- * If the L1 slot matches the pmap's domain
- * number, then invalidate it.
+ * Get free and aligned space for PT2MAP and make L1 page table links
+ * to L2 page tables held in PT2TAB.
+ *
+ * Note that pages holding PT2s are stored in PT2TAB as pt2_entry_t
+ * descriptors and PT2TAB page(s) itself is(are) used as PT2s. Thus
+ * each entry in PT2TAB maps all PT2s in a page. This implies that
+ * virtual address of PT2MAP must be aligned to NPT2_IN_PG * PTE1_SIZE.
*/
- l1pd = *pl1pd & (L1_TYPE_MASK | L1_C_DOM_MASK);
- if (l1pd == (L1_C_DOM(pmap->pm_domain) | L1_TYPE_C)) {
- *pl1pd = 0;
- PTE_SYNC(pl1pd);
- cpu_tlb_flushD_SE((vm_offset_t)ptep);
- cpu_cpwait();
+ PT2MAP = (pt2_entry_t *)(KERNBASE - PT2MAP_SIZE);
+ pte1p = kern_pte1((vm_offset_t)PT2MAP);
+ for (pa = pt2tab_pa, i = 0; i < NPT2_IN_PT2TAB; i++, pa += NB_IN_PT2) {
+ pte1_store(pte1p++, PTE1_LINK(pa));
}
/*
- * Release the L2 descriptor table back to the pool cache.
+ * Store PT2TAB in PT2TAB itself, i.e. self reference mapping.
+ * Each pmap will hold own PT2TAB, so the mapping should be not global.
*/
- pmap_free_l2_ptp(ptep);
+ pte2p = kern_pt2tab_entry((vm_offset_t)PT2MAP);
+ for (pa = pt2tab_pa, i = 0; i < NPG_IN_PT2TAB; i++, pa += PTE2_SIZE) {
+ pt2tab_store(pte2p++, PTE2_KPT_NG(pa));
+ }
/*
- * Update the reference count in the associated l2_dtable
+ * Choose correct L2 page table and make mappings for allocations
+ * made herein which replaces temporary locore.S mappings after a while.
+ * Note that PT2MAP cannot be used until we switch to kern_pt1.
+ *
+ * Note, that these allocations started aligned on 1M section and
+ * kernel PT1 was allocated first. Making of mappings must follow
+ * order of physical allocations as we've used KERNEL_P2V() macro
+ * for virtual addresses resolution.
*/
- l2 = pmap->pm_l2[L2_IDX(l1idx)];
- if (--l2->l2_occupancy > 0)
- return;
+ pte2p = kern_pt2tab_entry((vm_offset_t)kern_pt1);
+ pt2pg_va = KERNEL_P2V(pte2_pa(pte2_load(pte2p)));
- /*
- * There are no more valid mappings in any of the Level 1
- * slots managed by this l2_dtable. Go ahead and NULL-out
- * the pointer in the parent pmap and free the l2_dtable.
- */
- pmap->pm_l2[L2_IDX(l1idx)] = NULL;
- uma_zfree(l2table_zone, l2);
-}
+ pte2p = page_pt2(pt2pg_va, pte1_index((vm_offset_t)kern_pt1));
-/*
- * Pool cache constructors for L2 descriptor tables, metadata and pmap
- * structures.
- */
-static int
-pmap_l2ptp_ctor(void *mem, int size, void *arg, int flags)
-{
- struct l2_bucket *l2b;
- pt_entry_t *ptep, pte;
- vm_offset_t va = (vm_offset_t)mem & ~PAGE_MASK;
+ /* Make mapping for kernel L1 page table. */
+ for (pa = base_pt1, i = 0; i < NPG_IN_PT1; i++, pa += PTE2_SIZE)
+ pte2_store(pte2p++, PTE2_KPT(pa));
+
+ /* Make mapping for kernel PT2TAB. */
+ for (pa = pt2tab_pa, i = 0; i < NPG_IN_PT2TAB; i++, pa += PTE2_SIZE)
+ pte2_store(pte2p++, PTE2_KPT(pa));
+ /* Finally, switch from 'boot_pt1' to 'kern_pt1'. */
+ pmap_kern_ttb = base_pt1 | ttb_flags;
+ cpuinfo_get_actlr_modifier(&actlr_mask, &actlr_set);
+ reinit_mmu(pmap_kern_ttb, actlr_mask, actlr_set);
/*
- * The mappings for these page tables were initially made using
- * pmap_kenter() by the pool subsystem. Therefore, the cache-
- * mode will not be right for page table mappings. To avoid
- * polluting the pmap_kenter() code with a special case for
- * page tables, we simply fix up the cache-mode here if it's not
- * correct.
+ * Initialize the first available KVA. As kernel image is mapped by
+ * sections, we are leaving some gap behind.
*/
- l2b = pmap_get_l2_bucket(pmap_kernel(), va);
- ptep = &l2b->l2b_kva[l2pte_index(va)];
- pte = *ptep;
-
- cpu_idcache_wbinv_range(va, PAGE_SIZE);
- pmap_l2cache_wbinv_range(va, pte & L2_S_FRAME, PAGE_SIZE);
- if ((pte & L2_S_CACHE_MASK) != pte_l2_s_cache_mode_pt) {
- /*
- * Page tables must have the cache-mode set to
- * Write-Thru.
- */
- *ptep = (pte & ~L2_S_CACHE_MASK) | pte_l2_s_cache_mode_pt;
- PTE_SYNC(ptep);
- cpu_tlb_flushD_SE(va);
- cpu_cpwait();
- }
-
- memset(mem, 0, L2_TABLE_SIZE_REAL);
- return (0);
+ virtual_avail = (vm_offset_t)kern_pt2tab + NPG_IN_PT2TAB * PAGE_SIZE;
}
/*
- * Modify pte bits for all ptes corresponding to the given physical address.
- * We use `maskbits' rather than `clearbits' because we're always passing
- * constants and the latter would require an extra inversion at run-time.
+ * Setup L2 page table page for given KVA.
+ * Used in pre-bootstrap epoch.
+ *
+ * Note that we have allocated NKPT2PG pages for L2 page tables in advance
+ * and used them for mapping KVA starting from KERNBASE. However, this is not
+ * enough. Vectors and devices need L2 page tables too. Note that they are
+ * even above VM_MAX_KERNEL_ADDRESS.
*/
-static int
-pmap_clearbit(struct vm_page *m, u_int maskbits)
+static __inline vm_paddr_t
+pmap_preboot_pt2pg_setup(vm_offset_t va)
{
- struct l2_bucket *l2b;
- struct pv_entry *pv, *pve, *next_pv;
- struct md_page *pvh;
- pd_entry_t *pl1pd;
- pt_entry_t *ptep, npte, opte;
- pmap_t pmap;
- vm_offset_t va;
- u_int oflags;
- int count = 0;
+ pt2_entry_t *pte2p, pte2;
+ vm_paddr_t pt2pg_pa;
- rw_wlock(&pvh_global_lock);
- if ((m->flags & PG_FICTITIOUS) != 0)
- goto small_mappings;
+ /* Get associated entry in PT2TAB. */
+ pte2p = kern_pt2tab_entry(va);
- pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
- TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_list, next_pv) {
- va = pv->pv_va;
- pmap = PV_PMAP(pv);
- PMAP_LOCK(pmap);
- pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
- KASSERT((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO,
- ("pmap_clearbit: valid section mapping expected"));
- if ((maskbits & PVF_WRITE) && (pv->pv_flags & PVF_WRITE))
- (void)pmap_demote_section(pmap, va);
- else if ((maskbits & PVF_REF) && L1_S_REFERENCED(*pl1pd)) {
- if (pmap_demote_section(pmap, va)) {
- if ((pv->pv_flags & PVF_WIRED) == 0) {
- /*
- * Remove the mapping to a single page
- * so that a subsequent access may
- * repromote. Since the underlying
- * l2_bucket is fully populated, this
- * removal never frees an entire
- * l2_bucket.
- */
- va += (VM_PAGE_TO_PHYS(m) &
- L1_S_OFFSET);
- l2b = pmap_get_l2_bucket(pmap, va);
- KASSERT(l2b != NULL,
- ("pmap_clearbit: no l2 bucket for "
- "va 0x%#x, pmap 0x%p", va, pmap));
- ptep = &l2b->l2b_kva[l2pte_index(va)];
- *ptep = 0;
- PTE_SYNC(ptep);
- pmap_free_l2_bucket(pmap, l2b, 1);
- pve = pmap_remove_pv(m, pmap, va);
- KASSERT(pve != NULL, ("pmap_clearbit: "
- "no PV entry for managed mapping"));
- pmap_free_pv_entry(pmap, pve);
+ /* Just return, if PT2s page exists already. */
+ pte2 = pt2tab_load(pte2p);
+ if (pte2_is_valid(pte2))
+ return (pte2_pa(pte2));
- }
- }
- } else if ((maskbits & PVF_MOD) && L1_S_WRITABLE(*pl1pd)) {
- if (pmap_demote_section(pmap, va)) {
- if ((pv->pv_flags & PVF_WIRED) == 0) {
- /*
- * Write protect the mapping to a
- * single page so that a subsequent
- * write access may repromote.
- */
- va += (VM_PAGE_TO_PHYS(m) &
- L1_S_OFFSET);
- l2b = pmap_get_l2_bucket(pmap, va);
- KASSERT(l2b != NULL,
- ("pmap_clearbit: no l2 bucket for "
- "va 0x%#x, pmap 0x%p", va, pmap));
- ptep = &l2b->l2b_kva[l2pte_index(va)];
- if ((*ptep & L2_S_PROTO) != 0) {
- pve = pmap_find_pv(&m->md,
- pmap, va);
- KASSERT(pve != NULL,
- ("pmap_clearbit: no PV "
- "entry for managed mapping"));
- pve->pv_flags &= ~PVF_WRITE;
- *ptep |= L2_APX;
- PTE_SYNC(ptep);
- }
- }
- }
- }
- PMAP_UNLOCK(pmap);
- }
-
-small_mappings:
- if (TAILQ_EMPTY(&m->md.pv_list)) {
- rw_wunlock(&pvh_global_lock);
- return (0);
- }
+ KASSERT(va >= VM_MAX_KERNEL_ADDRESS,
+ ("%s: NKPT2PG too small", __func__));
/*
- * Loop over all current mappings setting/clearing as appropos
+ * Allocate page for PT2s and insert it to PT2TAB.
+ * In other words, map it into PT2MAP space.
*/
- TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
- va = pv->pv_va;
- pmap = PV_PMAP(pv);
- oflags = pv->pv_flags;
- pv->pv_flags &= ~maskbits;
-
- PMAP_LOCK(pmap);
+ pt2pg_pa = pmap_preboot_get_pages(1);
+ pt2tab_store(pte2p, PTE2_KPT(pt2pg_pa));
- l2b = pmap_get_l2_bucket(pmap, va);
- KASSERT(l2b != NULL, ("pmap_clearbit: no l2 bucket for "
- "va 0x%#x, pmap 0x%p", va, pmap));
-
- ptep = &l2b->l2b_kva[l2pte_index(va)];
- npte = opte = *ptep;
-
- if (maskbits & (PVF_WRITE | PVF_MOD)) {
- /* make the pte read only */
- npte |= L2_APX;
- }
-
- if (maskbits & PVF_REF) {
- /*
- * Clear referenced flag in PTE so that we
- * will take a flag fault the next time the mapping
- * is referenced.
- */
- npte &= ~L2_S_REF;
- }
-
- CTR4(KTR_PMAP,"clearbit: pmap:%p bits:%x pte:%x->%x",
- pmap, maskbits, opte, npte);
- if (npte != opte) {
- count++;
- *ptep = npte;
- PTE_SYNC(ptep);
- /* Flush the TLB entry if a current pmap. */
- if (PTE_BEEN_EXECD(opte))
- cpu_tlb_flushID_SE(pv->pv_va);
- else if (PTE_BEEN_REFD(opte))
- cpu_tlb_flushD_SE(pv->pv_va);
- cpu_cpwait();
- }
-
- PMAP_UNLOCK(pmap);
-
- }
+ /* Zero all PT2s in allocated page. */
+ bzero((void*)pt2map_pt2pg(va), PAGE_SIZE);
+ pte2_sync_range((pt2_entry_t *)pt2map_pt2pg(va), PAGE_SIZE);
- if (maskbits & PVF_WRITE)
- vm_page_aflag_clear(m, PGA_WRITEABLE);
- rw_wunlock(&pvh_global_lock);
- return (count);
+ return (pt2pg_pa);
}
/*
- * main pv_entry manipulation functions:
- * pmap_enter_pv: enter a mapping onto a vm_page list
- * pmap_remove_pv: remove a mappiing from a vm_page list
- *
- * NOTE: pmap_enter_pv expects to lock the pvh itself
- * pmap_remove_pv expects the caller to lock the pvh before calling
- */
-
-/*
- * pmap_enter_pv: enter a mapping onto a vm_page's PV list
- *
- * => caller should hold the proper lock on pvh_global_lock
- * => caller should have pmap locked
- * => we will (someday) gain the lock on the vm_page's PV list
- * => caller should adjust ptp's wire_count before calling
- * => caller should not adjust pmap's wire_count
+ * Setup L2 page table for given KVA.
+ * Used in pre-bootstrap epoch.
*/
static void
-pmap_enter_pv(struct vm_page *m, struct pv_entry *pve, pmap_t pmap,
- vm_offset_t va, u_int flags)
+pmap_preboot_pt2_setup(vm_offset_t va)
{
+ pt1_entry_t *pte1p;
+ vm_paddr_t pt2pg_pa, pt2_pa;
- rw_assert(&pvh_global_lock, RA_WLOCKED);
-
- PMAP_ASSERT_LOCKED(pmap);
- pve->pv_va = va;
- pve->pv_flags = flags;
+ /* Setup PT2's page. */
+ pt2pg_pa = pmap_preboot_pt2pg_setup(va);
+ pt2_pa = page_pt2pa(pt2pg_pa, pte1_index(va));
- TAILQ_INSERT_HEAD(&m->md.pv_list, pve, pv_list);
- if (pve->pv_flags & PVF_WIRED)
- ++pmap->pm_stats.wired_count;
+ /* Insert PT2 to PT1. */
+ pte1p = kern_pte1(va);
+ pte1_store(pte1p, PTE1_LINK(pt2_pa));
}
/*
- *
- * pmap_find_pv: Find a pv entry
- *
- * => caller should hold lock on vm_page
+ * Get L2 page entry associated with given KVA.
+ * Used in pre-bootstrap epoch.
*/
-static PMAP_INLINE struct pv_entry *
-pmap_find_pv(struct md_page *md, pmap_t pmap, vm_offset_t va)
+static __inline pt2_entry_t*
+pmap_preboot_vtopte2(vm_offset_t va)
{
- struct pv_entry *pv;
+ pt1_entry_t *pte1p;
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- TAILQ_FOREACH(pv, &md->pv_list, pv_list)
- if (pmap == PV_PMAP(pv) && va == pv->pv_va)
- break;
+ /* Setup PT2 if needed. */
+ pte1p = kern_pte1(va);
+ if (!pte1_is_valid(pte1_load(pte1p))) /* XXX - sections ?! */
+ pmap_preboot_pt2_setup(va);
- return (pv);
+ return (pt2map_entry(va));
}
/*
- * vector_page_setprot:
- *
- * Manipulate the protection of the vector page.
+ * Pre-bootstrap epoch page(s) mapping(s).
*/
void
-vector_page_setprot(int prot)
-{
- struct l2_bucket *l2b;
- pt_entry_t *ptep;
-
- l2b = pmap_get_l2_bucket(pmap_kernel(), vector_page);
-
- ptep = &l2b->l2b_kva[l2pte_index(vector_page)];
- /*
- * Set referenced flag.
- * Vectors' page is always desired
- * to be allowed to reside in TLB.
- */
- *ptep |= L2_S_REF;
-
- pmap_set_prot(ptep, prot|VM_PROT_EXECUTE, 0);
- PTE_SYNC(ptep);
- cpu_tlb_flushID_SE(vector_page);
- cpu_cpwait();
-}
-
-static void
-pmap_set_prot(pt_entry_t *ptep, vm_prot_t prot, uint8_t user)
+pmap_preboot_map_pages(vm_paddr_t pa, vm_offset_t va, u_int num)
{
+ u_int i;
+ pt2_entry_t *pte2p;
- *ptep &= ~(L2_S_PROT_MASK | L2_XN);
-
- if (!(prot & VM_PROT_EXECUTE))
- *ptep |= L2_XN;
-
- /* Set defaults first - kernel read access */
- *ptep |= L2_APX;
- *ptep |= L2_S_PROT_R;
- /* Now tune APs as desired */
- if (user)
- *ptep |= L2_S_PROT_U;
-
- if (prot & VM_PROT_WRITE)
- *ptep &= ~(L2_APX);
+ /* Map all the pages. */
+ for (i = 0; i < num; i++) {
+ pte2p = pmap_preboot_vtopte2(va);
+ pte2_store(pte2p, PTE2_KRW(pa));
+ va += PAGE_SIZE;
+ pa += PAGE_SIZE;
+ }
}
/*
- * pmap_remove_pv: try to remove a mapping from a pv_list
- *
- * => caller should hold proper lock on pmap_main_lock
- * => pmap should be locked
- * => caller should hold lock on vm_page [so that attrs can be adjusted]
- * => caller should adjust ptp's wire_count and free PTP if needed
- * => caller should NOT adjust pmap's wire_count
- * => we return the removed pve
+ * Pre-bootstrap epoch virtual space alocator.
*/
-static struct pv_entry *
-pmap_remove_pv(struct vm_page *m, pmap_t pmap, vm_offset_t va)
+vm_offset_t
+pmap_preboot_reserve_pages(u_int num)
{
- struct pv_entry *pve;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- PMAP_ASSERT_LOCKED(pmap);
-
- pve = pmap_find_pv(&m->md, pmap, va); /* find corresponding pve */
- if (pve != NULL) {
- TAILQ_REMOVE(&m->md.pv_list, pve, pv_list);
- if (pve->pv_flags & PVF_WIRED)
- --pmap->pm_stats.wired_count;
+ u_int i;
+ vm_offset_t start, va;
+ pt2_entry_t *pte2p;
+
+ /* Allocate virtual space. */
+ start = va = virtual_avail;
+ virtual_avail += num * PAGE_SIZE;
+
+ /* Zero the mapping. */
+ for (i = 0; i < num; i++) {
+ pte2p = pmap_preboot_vtopte2(va);
+ pte2_store(pte2p, 0);
+ va += PAGE_SIZE;
}
- if (TAILQ_EMPTY(&m->md.pv_list))
- vm_page_aflag_clear(m, PGA_WRITEABLE);
- return(pve); /* return removed pve */
+ return (start);
}
/*
- *
- * pmap_modify_pv: Update pv flags
- *
- * => caller should hold lock on vm_page [so that attrs can be adjusted]
- * => caller should NOT adjust pmap's wire_count
- * => we return the old flags
- *
- * Modify a physical-virtual mapping in the pv table
+ * Pre-bootstrap epoch page(s) allocation and mapping(s).
*/
-static u_int
-pmap_modify_pv(struct vm_page *m, pmap_t pmap, vm_offset_t va,
- u_int clr_mask, u_int set_mask)
+vm_offset_t
+pmap_preboot_get_vpages(u_int num)
{
- struct pv_entry *npv;
- u_int flags, oflags;
-
- PMAP_ASSERT_LOCKED(pmap);
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- if ((npv = pmap_find_pv(&m->md, pmap, va)) == NULL)
- return (0);
-
- /*
- * There is at least one VA mapping this page.
- */
- oflags = npv->pv_flags;
- npv->pv_flags = flags = (oflags & ~clr_mask) | set_mask;
-
- if ((flags ^ oflags) & PVF_WIRED) {
- if (flags & PVF_WIRED)
- ++pmap->pm_stats.wired_count;
- else
- --pmap->pm_stats.wired_count;
- }
+ vm_paddr_t pa;
+ vm_offset_t va;
- return (oflags);
-}
+ /* Allocate physical page(s). */
+ pa = pmap_preboot_get_pages(num);
-/* Function to set the debug level of the pmap code */
-#ifdef PMAP_DEBUG
-void
-pmap_debug(int level)
-{
- pmap_debug_level = level;
- dprintf("pmap_debug: level=%d\n", pmap_debug_level);
-}
-#endif /* PMAP_DEBUG */
+ /* Allocate virtual space. */
+ va = virtual_avail;
+ virtual_avail += num * PAGE_SIZE;
-void
-pmap_pinit0(struct pmap *pmap)
-{
- PDEBUG(1, printf("pmap_pinit0: pmap = %08x\n", (u_int32_t) pmap));
+ /* Map and zero all. */
+ pmap_preboot_map_pages(pa, va, num);
+ bzero((void *)va, num * PAGE_SIZE);
- bcopy(kernel_pmap, pmap, sizeof(*pmap));
- bzero(&pmap->pm_mtx, sizeof(pmap->pm_mtx));
- PMAP_LOCK_INIT(pmap);
- TAILQ_INIT(&pmap->pm_pvchunk);
+ return (va);
}
/*
- * Initialize a vm_page's machine-dependent fields.
+ * Pre-bootstrap epoch page mapping(s) with attributes.
*/
void
-pmap_page_init(vm_page_t m)
+pmap_preboot_map_attr(vm_paddr_t pa, vm_offset_t va, vm_size_t size,
+ vm_prot_t prot, vm_memattr_t attr)
{
-
- TAILQ_INIT(&m->md.pv_list);
- m->md.pv_memattr = VM_MEMATTR_DEFAULT;
-}
-
-static vm_offset_t
-pmap_ptelist_alloc(vm_offset_t *head)
-{
- pt_entry_t *pte;
- vm_offset_t va;
-
- va = *head;
- if (va == 0)
- return (va); /* Out of memory */
- pte = vtopte(va);
- *head = *pte;
- if ((*head & L2_TYPE_MASK) != L2_TYPE_INV)
- panic("%s: va is not L2_TYPE_INV!", __func__);
- *pte = 0;
- return (va);
+ u_int num;
+ u_int l1_attr, l1_prot, l2_prot, l2_attr;
+ pt1_entry_t *pte1p;
+ pt2_entry_t *pte2p;
+
+ l2_prot = prot & VM_PROT_WRITE ? PTE2_AP_KRW : PTE2_AP_KR;
+ l2_attr = vm_memattr_to_pte2(attr);
+ l1_prot = ATTR_TO_L1(l2_prot);
+ l1_attr = ATTR_TO_L1(l2_attr);
+
+ /* Map all the pages. */
+ num = round_page(size);
+ while (num > 0) {
+ if ((((va | pa) & PTE1_OFFSET) == 0) && (num >= PTE1_SIZE)) {
+ pte1p = kern_pte1(va);
+ pte1_store(pte1p, PTE1_KERN(pa, l1_prot, l1_attr));
+ va += PTE1_SIZE;
+ pa += PTE1_SIZE;
+ num -= PTE1_SIZE;
+ } else {
+ pte2p = pmap_preboot_vtopte2(va);
+ pte2_store(pte2p, PTE2_KERN(pa, l2_prot, l2_attr));
+ va += PAGE_SIZE;
+ pa += PAGE_SIZE;
+ num -= PAGE_SIZE;
+ }
+ }
}
-static void
-pmap_ptelist_free(vm_offset_t *head, vm_offset_t va)
+/*
+ * Extract from the kernel page table the physical address
+ * that is mapped by the given virtual address "va".
+ */
+vm_paddr_t
+pmap_kextract(vm_offset_t va)
{
- pt_entry_t *pte;
+ vm_paddr_t pa;
+ pt1_entry_t pte1;
+ pt2_entry_t pte2;
- if ((va & L2_TYPE_MASK) != L2_TYPE_INV)
- panic("%s: freeing va that is not L2_TYPE INV!", __func__);
- pte = vtopte(va);
- *pte = *head; /* virtual! L2_TYPE is L2_TYPE_INV though */
- *head = va;
+ pte1 = pte1_load(kern_pte1(va));
+ if (pte1_is_section(pte1)) {
+ pa = pte1_pa(pte1) | (va & PTE1_OFFSET);
+ } else if (pte1_is_link(pte1)) {
+ /*
+ * We should beware of concurrent promotion that changes
+ * pte1 at this point. However, it's not a problem as PT2
+ * page is preserved by promotion in PT2TAB. So even if
+ * it happens, using of PT2MAP is still safe.
+ *
+ * QQQ: However, concurrent removing is a problem which
+ * ends in abort on PT2MAP space. Locking must be used
+ * to deal with this.
+ */
+ pte2 = pte2_load(pt2map_entry(va));
+ pa = pte2_pa(pte2) | (va & PTE2_OFFSET);
+ }
+ else {
+ panic("%s: va %#x pte1 %#x", __func__, va, pte1);
+ }
+ return (pa);
}
-static void
-pmap_ptelist_init(vm_offset_t *head, void *base, int npages)
+/*
+ * Extract from the kernel page table the physical address
+ * that is mapped by the given virtual address "va". Also
+ * return L2 page table entry which maps the address.
+ *
+ * This is only intended to be used for panic dumps.
+ */
+vm_paddr_t
+pmap_dump_kextract(vm_offset_t va, pt2_entry_t *pte2p)
{
- int i;
- vm_offset_t va;
-
- *head = 0;
- for (i = npages - 1; i >= 0; i--) {
- va = (vm_offset_t)base + i * PAGE_SIZE;
- pmap_ptelist_free(head, va);
+ vm_paddr_t pa;
+ pt1_entry_t pte1;
+ pt2_entry_t pte2;
+
+ pte1 = pte1_load(kern_pte1(va));
+ if (pte1_is_section(pte1)) {
+ pa = pte1_pa(pte1) | (va & PTE1_OFFSET);
+ pte2 = pa | ATTR_TO_L2(pte1) | PTE2_V;
+ } else if (pte1_is_link(pte1)) {
+ pte2 = pte2_load(pt2map_entry(va));
+ pa = pte2_pa(pte2);
+ } else {
+ pte2 = 0;
+ pa = 0;
}
+ if (pte2p != NULL)
+ *pte2p = pte2;
+ return (pa);
}
+/*****************************************************************************
+ *
+ * PMAP second stage initialization and utility functions
+ * for bootstrap epoch.
+ *
+ * After pmap_bootstrap() is called, the following functions for
+ * mappings can be used:
+ *
+ * void pmap_kenter(vm_offset_t va, vm_paddr_t pa);
+ * void pmap_kremove(vm_offset_t va);
+ * vm_offset_t pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end,
+ * int prot);
+ *
+ * NOTE: This is not SMP coherent stage. And physical page allocation is not
+ * allowed during this stage.
+ *
+ *****************************************************************************/
+
/*
- * Initialize the pmap module.
- * Called by vm_init, to initialize any structures that the pmap
- * system needs to map virtual memory.
+ * Initialize kernel PMAP locks and lists, kernel_pmap itself, and
+ * reserve various virtual spaces for temporary mappings.
*/
void
-pmap_init(void)
+pmap_bootstrap(vm_offset_t firstaddr)
{
- vm_size_t s;
- int i, pv_npg;
-
- l2zone = uma_zcreate("L2 Table", L2_TABLE_SIZE_REAL, pmap_l2ptp_ctor,
- NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
- l2table_zone = uma_zcreate("L2 Table", sizeof(struct l2_dtable), NULL,
- NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
+ pt2_entry_t *unused __unused;
+ struct sysmaps *sysmaps;
+ u_int i;
/*
- * Are large page mappings supported and enabled?
+ * Initialize the kernel pmap (which is statically allocated).
*/
- TUNABLE_INT_FETCH("vm.pmap.sp_enabled", &sp_enabled);
- if (sp_enabled) {
- KASSERT(MAXPAGESIZES > 1 && pagesizes[1] == 0,
- ("pmap_init: can't assign to pagesizes[1]"));
- pagesizes[1] = NBPDR;
- }
+ PMAP_LOCK_INIT(kernel_pmap);
+ kernel_l1pa = (vm_paddr_t)kern_pt1; /* for libkvm */
+ kernel_pmap->pm_pt1 = kern_pt1;
+ kernel_pmap->pm_pt2tab = kern_pt2tab;
+ CPU_FILL(&kernel_pmap->pm_active); /* don't allow deactivation */
+ TAILQ_INIT(&kernel_pmap->pm_pvchunk);
/*
- * Calculate the size of the pv head table for superpages.
- * Handle the possibility that "vm_phys_segs[...].end" is zero.
+ * Initialize the global pv list lock.
*/
- pv_npg = trunc_1mpage(vm_phys_segs[vm_phys_nsegs - 1].end -
- PAGE_SIZE) / NBPDR + 1;
+ rw_init(&pvh_global_lock, "pmap pv global");
- /*
- * Allocate memory for the pv head table for superpages.
- */
- s = (vm_size_t)(pv_npg * sizeof(struct md_page));
- s = round_page(s);
- pv_table = (struct md_page *)kmem_malloc(kernel_arena, s,
- M_WAITOK | M_ZERO);
- for (i = 0; i < pv_npg; i++)
- TAILQ_INIT(&pv_table[i].pv_list);
+ LIST_INIT(&allpmaps);
/*
- * Initialize the address space for the pv chunks.
+ * Request a spin mutex so that changes to allpmaps cannot be
+ * preempted by smp_rendezvous_cpus().
*/
-
- TUNABLE_INT_FETCH("vm.pmap.shpgperproc", &shpgperproc);
- pv_entry_max = shpgperproc * maxproc + vm_cnt.v_page_count;
- TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max);
- pv_entry_max = roundup(pv_entry_max, _NPCPV);
- pv_entry_high_water = 9 * (pv_entry_max / 10);
-
- pv_maxchunks = MAX(pv_entry_max / _NPCPV, maxproc);
- pv_chunkbase = (struct pv_chunk *)kva_alloc(PAGE_SIZE * pv_maxchunks);
-
- if (pv_chunkbase == NULL)
- panic("pmap_init: not enough kvm for pv chunks");
-
- pmap_ptelist_init(&pv_vafree, pv_chunkbase, pv_maxchunks);
+ mtx_init(&allpmaps_lock, "allpmaps", NULL, MTX_SPIN);
+ mtx_lock_spin(&allpmaps_lock);
+ LIST_INSERT_HEAD(&allpmaps, kernel_pmap, pm_list);
+ mtx_unlock_spin(&allpmaps_lock);
/*
- * Now it is safe to enable pv_table recording.
+ * Reserve some special page table entries/VA space for temporary
+ * mapping of pages.
*/
- PDEBUG(1, printf("pmap_init: done!\n"));
-}
-
-SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_max, CTLFLAG_RD, &pv_entry_max, 0,
- "Max number of PV entries");
-SYSCTL_INT(_vm_pmap, OID_AUTO, shpgperproc, CTLFLAG_RD, &shpgperproc, 0,
- "Page share factor per proc");
-
-static SYSCTL_NODE(_vm_pmap, OID_AUTO, section, CTLFLAG_RD, 0,
- "1MB page mapping counters");
-
-static u_long pmap_section_demotions;
-SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, demotions, CTLFLAG_RD,
- &pmap_section_demotions, 0, "1MB page demotions");
-
-static u_long pmap_section_mappings;
-SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, mappings, CTLFLAG_RD,
- &pmap_section_mappings, 0, "1MB page mappings");
-
-static u_long pmap_section_p_failures;
-SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, p_failures, CTLFLAG_RD,
- &pmap_section_p_failures, 0, "1MB page promotion failures");
+#define SYSMAP(c, p, v, n) do { \
+ v = (c)pmap_preboot_reserve_pages(n); \
+ p = pt2map_entry((vm_offset_t)v); \
+ } while (0)
-static u_long pmap_section_promotions;
-SYSCTL_ULONG(_vm_pmap_section, OID_AUTO, promotions, CTLFLAG_RD,
- &pmap_section_promotions, 0, "1MB page promotions");
-
-int
-pmap_fault_fixup(pmap_t pmap, vm_offset_t va, vm_prot_t ftype, int user)
-{
- struct l2_dtable *l2;
- struct l2_bucket *l2b;
- pd_entry_t *pl1pd, l1pd;
- pt_entry_t *ptep, pte;
- vm_paddr_t pa;
- u_int l1idx;
- int rv = 0;
-
- l1idx = L1_IDX(va);
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
/*
- * Check and possibly fix-up L1 section mapping
- * only when superpage mappings are enabled to speed up.
+ * Local CMAP1/CMAP2 are used for zeroing and copying pages.
+ * Local CMAP3 is used for data cache cleaning.
+ * Global CMAP3 is used for the idle process page zeroing.
*/
- if (sp_enabled) {
- pl1pd = &pmap->pm_l1->l1_kva[l1idx];
- l1pd = *pl1pd;
- if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
- /* Catch an access to the vectors section */
- if (l1idx == L1_IDX(vector_page))
- goto out;
- /*
- * Stay away from the kernel mappings.
- * None of them should fault from L1 entry.
- */
- if (pmap == pmap_kernel())
- goto out;
- /*
- * Catch a forbidden userland access
- */
- if (user && !(l1pd & L1_S_PROT_U))
- goto out;
- /*
- * Superpage is always either mapped read only
- * or it is modified and permitted to be written
- * by default. Therefore, process only reference
- * flag fault and demote page in case of write fault.
- */
- if ((ftype & VM_PROT_WRITE) && !L1_S_WRITABLE(l1pd) &&
- L1_S_REFERENCED(l1pd)) {
- (void)pmap_demote_section(pmap, va);
- goto out;
- } else if (!L1_S_REFERENCED(l1pd)) {
- /* Mark the page "referenced" */
- *pl1pd = l1pd | L1_S_REF;
- PTE_SYNC(pl1pd);
- goto l1_section_out;
- } else
- goto out;
- }
+ for (i = 0; i < MAXCPU; i++) {
+ sysmaps = &sysmaps_pcpu[i];
+ mtx_init(&sysmaps->lock, "SYSMAPS", NULL, MTX_DEF);
+ SYSMAP(caddr_t, sysmaps->CMAP1, sysmaps->CADDR1, 1);
+ SYSMAP(caddr_t, sysmaps->CMAP2, sysmaps->CADDR2, 1);
+ SYSMAP(caddr_t, sysmaps->CMAP3, sysmaps->CADDR3, 1);
}
- /*
- * If there is no l2_dtable for this address, then the process
- * has no business accessing it.
- *
- * Note: This will catch userland processes trying to access
- * kernel addresses.
- */
- l2 = pmap->pm_l2[L2_IDX(l1idx)];
- if (l2 == NULL)
- goto out;
+ SYSMAP(caddr_t, CMAP3, CADDR3, 1);
/*
- * Likewise if there is no L2 descriptor table
+ * Crashdump maps.
*/
- l2b = &l2->l2_bucket[L2_BUCKET(l1idx)];
- if (l2b->l2b_kva == NULL)
- goto out;
+ SYSMAP(caddr_t, unused, crashdumpmap, MAXDUMPPGS);
/*
- * Check the PTE itself.
+ * _tmppt is used for reading arbitrary physical pages via /dev/mem.
*/
- ptep = &l2b->l2b_kva[l2pte_index(va)];
- pte = *ptep;
- if (pte == 0)
- goto out;
+ SYSMAP(caddr_t, unused, _tmppt, 1);
/*
- * Catch a userland access to the vector page mapped at 0x0
+ * PADDR1 and PADDR2 are used by pmap_pte2_quick() and pmap_pte2(),
+ * respectively. PADDR3 is used by pmap_pte2_ddb().
*/
- if (user && !(pte & L2_S_PROT_U))
- goto out;
- if (va == vector_page)
- goto out;
-
- pa = l2pte_pa(pte);
- CTR5(KTR_PMAP, "pmap_fault_fix: pmap:%p va:%x pte:0x%x ftype:%x user:%x",
- pmap, va, pte, ftype, user);
- if ((ftype & VM_PROT_WRITE) && !(L2_S_WRITABLE(pte)) &&
- L2_S_REFERENCED(pte)) {
- /*
- * This looks like a good candidate for "page modified"
- * emulation...
- */
- struct pv_entry *pv;
- struct vm_page *m;
-
- /* Extract the physical address of the page */
- if ((m = PHYS_TO_VM_PAGE(pa)) == NULL) {
- goto out;
- }
- /* Get the current flags for this page. */
-
- pv = pmap_find_pv(&m->md, pmap, va);
- if (pv == NULL) {
- goto out;
- }
-
- /*
- * Do the flags say this page is writable? If not then it
- * is a genuine write fault. If yes then the write fault is
- * our fault as we did not reflect the write access in the
- * PTE. Now we know a write has occurred we can correct this
- * and also set the modified bit
- */
- if ((pv->pv_flags & PVF_WRITE) == 0) {
- goto out;
- }
-
- vm_page_dirty(m);
-
- /* Re-enable write permissions for the page */
- *ptep = (pte & ~L2_APX);
- PTE_SYNC(ptep);
- rv = 1;
- CTR1(KTR_PMAP, "pmap_fault_fix: new pte:0x%x", *ptep);
- } else if (!L2_S_REFERENCED(pte)) {
- /*
- * This looks like a good candidate for "page referenced"
- * emulation.
- */
- struct pv_entry *pv;
- struct vm_page *m;
-
- /* Extract the physical address of the page */
- if ((m = PHYS_TO_VM_PAGE(pa)) == NULL)
- goto out;
- /* Get the current flags for this page. */
- pv = pmap_find_pv(&m->md, pmap, va);
- if (pv == NULL)
- goto out;
-
- vm_page_aflag_set(m, PGA_REFERENCED);
-
- /* Mark the page "referenced" */
- *ptep = pte | L2_S_REF;
- PTE_SYNC(ptep);
- rv = 1;
- CTR1(KTR_PMAP, "pmap_fault_fix: new pte:0x%x", *ptep);
- }
-
- /*
- * We know there is a valid mapping here, so simply
- * fix up the L1 if necessary.
- */
- pl1pd = &pmap->pm_l1->l1_kva[l1idx];
- l1pd = l2b->l2b_phys | L1_C_DOM(pmap->pm_domain) | L1_C_PROTO;
- if (*pl1pd != l1pd) {
- *pl1pd = l1pd;
- PTE_SYNC(pl1pd);
- rv = 1;
- }
-
-#ifdef DEBUG
- /*
- * If 'rv == 0' at this point, it generally indicates that there is a
- * stale TLB entry for the faulting address. This happens when two or
- * more processes are sharing an L1. Since we don't flush the TLB on
- * a context switch between such processes, we can take domain faults
- * for mappings which exist at the same VA in both processes. EVEN IF
- * WE'VE RECENTLY FIXED UP THE CORRESPONDING L1 in pmap_enter(), for
- * example.
- *
- * This is extremely likely to happen if pmap_enter() updated the L1
- * entry for a recently entered mapping. In this case, the TLB is
- * flushed for the new mapping, but there may still be TLB entries for
- * other mappings belonging to other processes in the 1MB range
- * covered by the L1 entry.
- *
- * Since 'rv == 0', we know that the L1 already contains the correct
- * value, so the fault must be due to a stale TLB entry.
- *
- * Since we always need to flush the TLB anyway in the case where we
- * fixed up the L1, or frobbed the L2 PTE, we effectively deal with
- * stale TLB entries dynamically.
- *
- * However, the above condition can ONLY happen if the current L1 is
- * being shared. If it happens when the L1 is unshared, it indicates
- * that other parts of the pmap are not doing their job WRT managing
- * the TLB.
- */
- if (rv == 0 && pmap->pm_l1->l1_domain_use_count == 1) {
- printf("fixup: pmap %p, va 0x%08x, ftype %d - nothing to do!\n",
- pmap, va, ftype);
- printf("fixup: l2 %p, l2b %p, ptep %p, pl1pd %p\n",
- l2, l2b, ptep, pl1pd);
- printf("fixup: pte 0x%x, l1pd 0x%x, last code 0x%x\n",
- pte, l1pd, last_fault_code);
+ SYSMAP(pt2_entry_t *, PMAP1, PADDR1, 1);
+ SYSMAP(pt2_entry_t *, PMAP2, PADDR2, 1);
#ifdef DDB
- Debugger();
-#endif
- }
+ SYSMAP(pt2_entry_t *, PMAP3, PADDR3, 1);
#endif
+ mtx_init(&PMAP2mutex, "PMAP2", NULL, MTX_DEF);
-l1_section_out:
- cpu_tlb_flushID_SE(va);
- cpu_cpwait();
-
- rv = 1;
-
-out:
- rw_wunlock(&pvh_global_lock);
- PMAP_UNLOCK(pmap);
- return (rv);
+ /*
+ * Note that in very short time in initarm(), we are going to
+ * initialize phys_avail[] array and no futher page allocation
+ * can happen after that until vm subsystem will be initialized.
+ */
+ kernel_vm_end_new = kernel_vm_end;
+ virtual_end = vm_max_kernel_address;
}
-void
-pmap_postinit(void)
+static void
+pmap_init_qpages(void)
{
- struct l2_bucket *l2b;
- struct l1_ttable *l1;
- pd_entry_t *pl1pt;
- pt_entry_t *ptep, pte;
- vm_offset_t va, eva;
- u_int loop, needed;
-
- needed = (maxproc / PMAP_DOMAINS) + ((maxproc % PMAP_DOMAINS) ? 1 : 0);
- needed -= 1;
- l1 = malloc(sizeof(*l1) * needed, M_VMPMAP, M_WAITOK);
-
- for (loop = 0; loop < needed; loop++, l1++) {
- /* Allocate a L1 page table */
- va = (vm_offset_t)contigmalloc(L1_TABLE_SIZE, M_VMPMAP, 0, 0x0,
- 0xffffffff, L1_TABLE_SIZE, 0);
-
- if (va == 0)
- panic("Cannot allocate L1 KVM");
-
- eva = va + L1_TABLE_SIZE;
- pl1pt = (pd_entry_t *)va;
-
- while (va < eva) {
- l2b = pmap_get_l2_bucket(pmap_kernel(), va);
- ptep = &l2b->l2b_kva[l2pte_index(va)];
- pte = *ptep;
- pte = (pte & ~L2_S_CACHE_MASK) | pte_l2_s_cache_mode_pt;
- *ptep = pte;
- PTE_SYNC(ptep);
- cpu_tlb_flushID_SE(va);
- cpu_cpwait();
- va += PAGE_SIZE;
- }
- pmap_init_l1(l1, pl1pt);
+ struct pcpu *pc;
+ int i;
+
+ CPU_FOREACH(i) {
+ pc = pcpu_find(i);
+ pc->pc_qmap_addr = kva_alloc(PAGE_SIZE);
+ if (pc->pc_qmap_addr == 0)
+ panic("%s: unable to allocate KVA", __func__);
}
-#ifdef DEBUG
- printf("pmap_postinit: Allocated %d static L1 descriptor tables\n",
- needed);
-#endif
}
+SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, pmap_init_qpages, NULL);
/*
- * This is used to stuff certain critical values into the PCB where they
- * can be accessed quickly from cpu_switch() et al.
+ * The function can already be use in second initialization stage.
+ * As such, the function DOES NOT call pmap_growkernel() where PT2
+ * allocation can happen. So if used, be sure that PT2 for given
+ * virtual address is allocated already!
+ *
+ * Add a wired page to the kva.
+ * Note: not SMP coherent.
*/
-void
-pmap_set_pcb_pagedir(pmap_t pmap, struct pcb *pcb)
+static __inline void
+pmap_kenter_prot_attr(vm_offset_t va, vm_paddr_t pa, uint32_t prot,
+ uint32_t attr)
{
- struct l2_bucket *l2b;
+ pt1_entry_t *pte1p;
+ pt2_entry_t *pte2p;
- pcb->pcb_pagedir = pmap->pm_l1->l1_physaddr;
- pcb->pcb_dacr = (DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) |
- (DOMAIN_CLIENT << (pmap->pm_domain * 2));
+ pte1p = kern_pte1(va);
+ if (!pte1_is_valid(pte1_load(pte1p))) { /* XXX - sections ?! */
+ /*
+ * This is a very low level function, so PT2 and particularly
+ * PT2PG associated with given virtual address must be already
+ * allocated. It's a pain mainly during pmap initialization
+ * stage. However, called after pmap initialization with
+ * virtual address not under kernel_vm_end will lead to
+ * the same misery.
+ */
+ if (!pte2_is_valid(pte2_load(kern_pt2tab_entry(va))))
+ panic("%s: kernel PT2 not allocated!", __func__);
+ }
- if (vector_page < KERNBASE) {
- pcb->pcb_pl1vec = &pmap->pm_l1->l1_kva[L1_IDX(vector_page)];
- l2b = pmap_get_l2_bucket(pmap, vector_page);
- pcb->pcb_l1vec = l2b->l2b_phys | L1_C_PROTO |
- L1_C_DOM(pmap->pm_domain) | L1_C_DOM(PMAP_DOMAIN_KERNEL);
- } else
- pcb->pcb_pl1vec = NULL;
+ pte2p = pt2map_entry(va);
+ pte2_store(pte2p, PTE2_KERN(pa, prot, attr));
}
-void
-pmap_activate(struct thread *td)
+static __inline void
+pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int attr)
{
- pmap_t pmap;
- struct pcb *pcb;
-
- pmap = vmspace_pmap(td->td_proc->p_vmspace);
- pcb = td->td_pcb;
- critical_enter();
- pmap_set_pcb_pagedir(pmap, pcb);
-
- if (td == curthread) {
- u_int cur_dacr, cur_ttb;
-
- __asm __volatile("mrc p15, 0, %0, c2, c0, 0" : "=r"(cur_ttb));
- __asm __volatile("mrc p15, 0, %0, c3, c0, 0" : "=r"(cur_dacr));
-
- cur_ttb &= ~(L1_TABLE_SIZE - 1);
+ pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, attr);
+}
- if (cur_ttb == (u_int)pcb->pcb_pagedir &&
- cur_dacr == pcb->pcb_dacr) {
- /*
- * No need to switch address spaces.
- */
- critical_exit();
- return;
- }
+PMAP_INLINE void
+pmap_kenter(vm_offset_t va, vm_paddr_t pa)
+{
+ pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, PTE2_ATTR_DEFAULT);
+}
- /*
- * We MUST, I repeat, MUST fix up the L1 entry corresponding
- * to 'vector_page' in the incoming L1 table before switching
- * to it otherwise subsequent interrupts/exceptions (including
- * domain faults!) will jump into hyperspace.
- */
- if (pcb->pcb_pl1vec) {
- *pcb->pcb_pl1vec = pcb->pcb_l1vec;
- }
+/*
+ * Remove a page from the kernel pagetables.
+ * Note: not SMP coherent.
+ */
+PMAP_INLINE void
+pmap_kremove(vm_offset_t va)
+{
+ pt2_entry_t *pte2p;
- cpu_domains(pcb->pcb_dacr);
- cpu_setttb(pcb->pcb_pagedir);
- }
- critical_exit();
+ pte2p = pt2map_entry(va);
+ pte2_clear(pte2p);
}
-static int
-pmap_set_pt_cache_mode(pd_entry_t *kl1, vm_offset_t va)
+/*
+ * Share new kernel PT2PG with all pmaps.
+ * The caller is responsible for maintaining TLB consistency.
+ */
+static void
+pmap_kenter_pt2tab(vm_offset_t va, pt2_entry_t npte2)
{
- pd_entry_t *pdep, pde;
- pt_entry_t *ptep, pte;
- vm_offset_t pa;
- int rv = 0;
+ pmap_t pmap;
+ pt2_entry_t *pte2p;
- /*
- * Make sure the descriptor itself has the correct cache mode
- */
- pdep = &kl1[L1_IDX(va)];
- pde = *pdep;
-
- if (l1pte_section_p(pde)) {
- if ((pde & L1_S_CACHE_MASK) != pte_l1_s_cache_mode_pt) {
- *pdep = (pde & ~L1_S_CACHE_MASK) |
- pte_l1_s_cache_mode_pt;
- PTE_SYNC(pdep);
- rv = 1;
- }
- } else {
- pa = (vm_paddr_t)(pde & L1_C_ADDR_MASK);
- ptep = (pt_entry_t *)kernel_pt_lookup(pa);
- if (ptep == NULL)
- panic("pmap_bootstrap: No L2 for L2 @ va %p\n", ptep);
-
- ptep = &ptep[l2pte_index(va)];
- pte = *ptep;
- if ((pte & L2_S_CACHE_MASK) != pte_l2_s_cache_mode_pt) {
- *ptep = (pte & ~L2_S_CACHE_MASK) |
- pte_l2_s_cache_mode_pt;
- PTE_SYNC(ptep);
- rv = 1;
- }
+ mtx_lock_spin(&allpmaps_lock);
+ LIST_FOREACH(pmap, &allpmaps, pm_list) {
+ pte2p = pmap_pt2tab_entry(pmap, va);
+ pt2tab_store(pte2p, npte2);
}
-
- return (rv);
+ mtx_unlock_spin(&allpmaps_lock);
}
+/*
+ * Share new kernel PTE1 with all pmaps.
+ * The caller is responsible for maintaining TLB consistency.
+ */
static void
-pmap_alloc_specials(vm_offset_t *availp, int pages, vm_offset_t *vap,
- pt_entry_t **ptep)
+pmap_kenter_pte1(vm_offset_t va, pt1_entry_t npte1)
{
- vm_offset_t va = *availp;
- struct l2_bucket *l2b;
-
- if (ptep) {
- l2b = pmap_get_l2_bucket(pmap_kernel(), va);
- if (l2b == NULL)
- panic("pmap_alloc_specials: no l2b for 0x%x", va);
+ pmap_t pmap;
+ pt1_entry_t *pte1p;
- *ptep = &l2b->l2b_kva[l2pte_index(va)];
+ mtx_lock_spin(&allpmaps_lock);
+ LIST_FOREACH(pmap, &allpmaps, pm_list) {
+ pte1p = pmap_pte1(pmap, va);
+ pte1_store(pte1p, npte1);
}
-
- *vap = va;
- *availp = va + (PAGE_SIZE * pages);
+ mtx_unlock_spin(&allpmaps_lock);
}
/*
- * Bootstrap the system enough to run with virtual memory.
+ * Used to map a range of physical addresses into kernel
+ * virtual address space.
+ *
+ * The value passed in '*virt' is a suggested virtual address for
+ * the mapping. Architectures which can support a direct-mapped
+ * physical to virtual region can return the appropriate address
+ * within that region, leaving '*virt' unchanged. Other
+ * architectures should map the pages starting at '*virt' and
+ * update '*virt' with the first usable address after the mapped
+ * region.
*
- * On the arm this is called after mapping has already been enabled
- * and just syncs the pmap module with what has already been done.
- * [We can't call it easily with mapping off since the kernel is not
- * mapped with PA == VA, hence we would have to relocate every address
- * from the linked base (virtual) address "KERNBASE" to the actual
- * (physical) address starting relative to 0]
+ * NOTE: Read the comments above pmap_kenter_prot_attr() as
+ * the function is used herein!
*/
-#define PMAP_STATIC_L2_SIZE 16
+vm_offset_t
+pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot)
+{
+ vm_offset_t va, sva;
+ vm_paddr_t pte1_offset;
+ pt1_entry_t npte1;
+ uint32_t l1prot, l2prot;
+ uint32_t l1attr, l2attr;
-void
-pmap_bootstrap(vm_offset_t firstaddr, struct pv_addr *l1pt)
-{
- static struct l1_ttable static_l1;
- static struct l2_dtable static_l2[PMAP_STATIC_L2_SIZE];
- struct l1_ttable *l1 = &static_l1;
- struct l2_dtable *l2;
- struct l2_bucket *l2b;
- struct czpages *czp;
- pd_entry_t pde;
- pd_entry_t *kernel_l1pt = (pd_entry_t *)l1pt->pv_va;
- pt_entry_t *ptep;
- vm_paddr_t pa;
- vm_offset_t va;
- vm_size_t size;
- int i, l1idx, l2idx, l2next = 0;
+ PDEBUG(1, printf("%s: virt = %#x, start = %#x, end = %#x (size = %#x),"
+ " prot = %d\n", __func__, *virt, start, end, end - start, prot));
- PDEBUG(1, printf("firstaddr = %08x, lastaddr = %08x\n",
- firstaddr, vm_max_kernel_address));
+ l2prot = (prot & VM_PROT_WRITE) ? PTE2_AP_KRW : PTE2_AP_KR;
+ l2prot |= (prot & VM_PROT_EXECUTE) ? PTE2_X : PTE2_NX;
+ l1prot = ATTR_TO_L1(l2prot);
- virtual_avail = firstaddr;
- kernel_pmap->pm_l1 = l1;
- kernel_l1pa = l1pt->pv_pa;
+ l2attr = PTE2_ATTR_DEFAULT;
+ l1attr = ATTR_TO_L1(l2attr);
+ va = *virt;
/*
- * Scan the L1 translation table created by initarm() and create
- * the required metadata for all valid mappings found in it.
+ * Does the physical address range's size and alignment permit at
+ * least one section mapping to be created?
*/
- for (l1idx = 0; l1idx < (L1_TABLE_SIZE / sizeof(pd_entry_t)); l1idx++) {
- pde = kernel_l1pt[l1idx];
-
- /*
- * We're only interested in Coarse mappings.
- * pmap_extract() can deal with section mappings without
- * recourse to checking L2 metadata.
- */
- if ((pde & L1_TYPE_MASK) != L1_TYPE_C)
- continue;
-
- /*
- * Lookup the KVA of this L2 descriptor table
- */
- pa = (vm_paddr_t)(pde & L1_C_ADDR_MASK);
- ptep = (pt_entry_t *)kernel_pt_lookup(pa);
-
- if (ptep == NULL) {
- panic("pmap_bootstrap: No L2 for va 0x%x, pa 0x%lx",
- (u_int)l1idx << L1_S_SHIFT, (long unsigned int)pa);
- }
-
- /*
- * Fetch the associated L2 metadata structure.
- * Allocate a new one if necessary.
- */
- if ((l2 = kernel_pmap->pm_l2[L2_IDX(l1idx)]) == NULL) {
- if (l2next == PMAP_STATIC_L2_SIZE)
- panic("pmap_bootstrap: out of static L2s");
- kernel_pmap->pm_l2[L2_IDX(l1idx)] = l2 =
- &static_l2[l2next++];
- }
-
+ pte1_offset = start & PTE1_OFFSET;
+ if ((end - start) - ((PTE1_SIZE - pte1_offset) & PTE1_OFFSET) >=
+ PTE1_SIZE) {
/*
- * One more L1 slot tracked...
+ * Increase the starting virtual address so that its alignment
+ * does not preclude the use of section mappings.
*/
- l2->l2_occupancy++;
-
- /*
- * Fill in the details of the L2 descriptor in the
- * appropriate bucket.
- */
- l2b = &l2->l2_bucket[L2_BUCKET(l1idx)];
- l2b->l2b_kva = ptep;
- l2b->l2b_phys = pa;
- l2b->l2b_l1idx = l1idx;
-
- /*
- * Establish an initial occupancy count for this descriptor
- */
- for (l2idx = 0;
- l2idx < (L2_TABLE_SIZE_REAL / sizeof(pt_entry_t));
- l2idx++) {
- if ((ptep[l2idx] & L2_TYPE_MASK) != L2_TYPE_INV) {
- l2b->l2b_occupancy++;
- }
- }
-
- /*
- * Make sure the descriptor itself has the correct cache mode.
- * If not, fix it, but whine about the problem. Port-meisters
- * should consider this a clue to fix up their initarm()
- * function. :)
- */
- if (pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)ptep)) {
- printf("pmap_bootstrap: WARNING! wrong cache mode for "
- "L2 pte @ %p\n", ptep);
- }
+ if ((va & PTE1_OFFSET) < pte1_offset)
+ va = pte1_trunc(va) + pte1_offset;
+ else if ((va & PTE1_OFFSET) > pte1_offset)
+ va = pte1_roundup(va) + pte1_offset;
}
-
-
- /*
- * Ensure the primary (kernel) L1 has the correct cache mode for
- * a page table. Bitch if it is not correctly set.
- */
- for (va = (vm_offset_t)kernel_l1pt;
- va < ((vm_offset_t)kernel_l1pt + L1_TABLE_SIZE); va += PAGE_SIZE) {
- if (pmap_set_pt_cache_mode(kernel_l1pt, va))
- printf("pmap_bootstrap: WARNING! wrong cache mode for "
- "primary L1 @ 0x%x\n", va);
+ sva = va;
+ while (start < end) {
+ if ((start & PTE1_OFFSET) == 0 && end - start >= PTE1_SIZE) {
+ KASSERT((va & PTE1_OFFSET) == 0,
+ ("%s: misaligned va %#x", __func__, va));
+ npte1 = PTE1_KERN(start, l1prot, l1attr);
+ pmap_kenter_pte1(va, npte1);
+ va += PTE1_SIZE;
+ start += PTE1_SIZE;
+ } else {
+ pmap_kenter_prot_attr(va, start, l2prot, l2attr);
+ va += PAGE_SIZE;
+ start += PAGE_SIZE;
+ }
}
-
- cpu_dcache_wbinv_all();
- cpu_l2cache_wbinv_all();
- cpu_tlb_flushID();
- cpu_cpwait();
-
- PMAP_LOCK_INIT(kernel_pmap);
- CPU_FILL(&kernel_pmap->pm_active);
- kernel_pmap->pm_domain = PMAP_DOMAIN_KERNEL;
- TAILQ_INIT(&kernel_pmap->pm_pvchunk);
-
- /*
- * Initialize the global pv list lock.
- */
- rw_init(&pvh_global_lock, "pmap pv global");
-
- /*
- * Reserve some special page table entries/VA space for temporary
- * mapping of pages that are being copied or zeroed.
- */
- for (czp = cpu_czpages, i = 0; i < MAXCPU; ++i, ++czp) {
- mtx_init(&czp->lock, "czpages", NULL, MTX_DEF);
- pmap_alloc_specials(&virtual_avail, 1, &czp->srcva, &czp->srcptep);
- pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)czp->srcptep);
- pmap_alloc_specials(&virtual_avail, 1, &czp->dstva, &czp->dstptep);
- pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)czp->dstptep);
- }
-
- size = ((vm_max_kernel_address - pmap_curmaxkvaddr) + L1_S_OFFSET) /
- L1_S_SIZE;
- pmap_alloc_specials(&virtual_avail,
- round_page(size * L2_TABLE_SIZE_REAL) / PAGE_SIZE,
- &pmap_kernel_l2ptp_kva, NULL);
-
- size = (size + (L2_BUCKET_SIZE - 1)) / L2_BUCKET_SIZE;
- pmap_alloc_specials(&virtual_avail,
- round_page(size * sizeof(struct l2_dtable)) / PAGE_SIZE,
- &pmap_kernel_l2dtable_kva, NULL);
-
- pmap_alloc_specials(&virtual_avail,
- 1, (vm_offset_t*)&_tmppt, NULL);
- pmap_alloc_specials(&virtual_avail,
- MAXDUMPPGS, (vm_offset_t *)&crashdumpmap, NULL);
- SLIST_INIT(&l1_list);
- TAILQ_INIT(&l1_lru_list);
- mtx_init(&l1_lru_lock, "l1 list lock", NULL, MTX_DEF);
- pmap_init_l1(l1, kernel_l1pt);
- cpu_dcache_wbinv_all();
- cpu_l2cache_wbinv_all();
- cpu_tlb_flushID();
- cpu_cpwait();
-
- virtual_avail = round_page(virtual_avail);
- virtual_end = vm_max_kernel_address;
- kernel_vm_end = pmap_curmaxkvaddr;
-
- pmap_set_pcb_pagedir(kernel_pmap, thread0.td_pcb);
+ tlb_flush_range(sva, va - sva);
+ *virt = va;
+ return (sva);
}
-
-/***************************************************
- * Pmap allocation/deallocation routines.
- ***************************************************/
-
/*
- * Release any resources held by the given physical map.
- * Called when a pmap initialized by pmap_pinit is being released.
- * Should only be called if the map contains no valid mappings.
+ * Make a temporary mapping for a physical address.
+ * This is only intended to be used for panic dumps.
*/
-void
-pmap_release(pmap_t pmap)
+void *
+pmap_kenter_temporary(vm_paddr_t pa, int i)
{
- struct pcb *pcb;
-
- cpu_tlb_flushID();
- cpu_cpwait();
- if (vector_page < KERNBASE) {
- struct pcb *curpcb = PCPU_GET(curpcb);
- pcb = thread0.td_pcb;
- if (pmap_is_current(pmap)) {
- /*
- * Frob the L1 entry corresponding to the vector
- * page so that it contains the kernel pmap's domain
- * number. This will ensure pmap_remove() does not
- * pull the current vector page out from under us.
- */
- critical_enter();
- *pcb->pcb_pl1vec = pcb->pcb_l1vec;
- cpu_domains(pcb->pcb_dacr);
- cpu_setttb(pcb->pcb_pagedir);
- critical_exit();
- }
- pmap_remove(pmap, vector_page, vector_page + PAGE_SIZE);
- /*
- * Make sure cpu_switch(), et al, DTRT. This is safe to do
- * since this process has no remaining mappings of its own.
- */
- curpcb->pcb_pl1vec = pcb->pcb_pl1vec;
- curpcb->pcb_l1vec = pcb->pcb_l1vec;
- curpcb->pcb_dacr = pcb->pcb_dacr;
- curpcb->pcb_pagedir = pcb->pcb_pagedir;
+ vm_offset_t va;
- }
- pmap_free_l1(pmap);
+ /* QQQ: 'i' should be less or equal to MAXDUMPPGS. */
- dprintf("pmap_release()\n");
+ va = (vm_offset_t)crashdumpmap + (i * PAGE_SIZE);
+ pmap_kenter(va, pa);
+ tlb_flush_local(va);
+ return ((void *)crashdumpmap);
}
+/*************************************
+ *
+ * TLB & cache maintenance routines.
+ *
+ *************************************/
/*
- * Helper function for pmap_grow_l2_bucket()
+ * We inline these within pmap.c for speed.
*/
-static __inline int
-pmap_grow_map(vm_offset_t va, pt_entry_t cache_mode, vm_paddr_t *pap)
+PMAP_INLINE void
+pmap_tlb_flush(pmap_t pmap, vm_offset_t va)
{
- struct l2_bucket *l2b;
- pt_entry_t *ptep;
- vm_paddr_t pa;
- struct vm_page *m;
- m = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_WIRED);
- if (m == NULL)
- return (1);
- pa = VM_PAGE_TO_PHYS(m);
-
- if (pap)
- *pap = pa;
-
- l2b = pmap_get_l2_bucket(pmap_kernel(), va);
-
- ptep = &l2b->l2b_kva[l2pte_index(va)];
- *ptep = L2_S_PROTO | pa | cache_mode | L2_S_REF;
- pmap_set_prot(ptep, VM_PROT_READ | VM_PROT_WRITE, 0);
- PTE_SYNC(ptep);
- cpu_tlb_flushD_SE(va);
- cpu_cpwait();
-
- return (0);
+ if (pmap == kernel_pmap || !CPU_EMPTY(&pmap->pm_active))
+ tlb_flush(va);
}
-/*
- * This is the same as pmap_alloc_l2_bucket(), except that it is only
- * used by pmap_growkernel().
- */
-static __inline struct l2_bucket *
-pmap_grow_l2_bucket(pmap_t pmap, vm_offset_t va)
+PMAP_INLINE void
+pmap_tlb_flush_range(pmap_t pmap, vm_offset_t sva, vm_size_t size)
{
- struct l2_dtable *l2;
- struct l2_bucket *l2b;
- struct l1_ttable *l1;
- pd_entry_t *pl1pd;
- u_short l1idx;
- vm_offset_t nva;
-
- l1idx = L1_IDX(va);
- if ((l2 = pmap->pm_l2[L2_IDX(l1idx)]) == NULL) {
- /*
- * No mapping at this address, as there is
- * no entry in the L1 table.
- * Need to allocate a new l2_dtable.
- */
- nva = pmap_kernel_l2dtable_kva;
- if ((nva & PAGE_MASK) == 0) {
- /*
- * Need to allocate a backing page
- */
- if (pmap_grow_map(nva, pte_l2_s_cache_mode, NULL))
- return (NULL);
- }
-
- l2 = (struct l2_dtable *)nva;
- nva += sizeof(struct l2_dtable);
-
- if ((nva & PAGE_MASK) < (pmap_kernel_l2dtable_kva &
- PAGE_MASK)) {
- /*
- * The new l2_dtable straddles a page boundary.
- * Map in another page to cover it.
- */
- if (pmap_grow_map(nva, pte_l2_s_cache_mode, NULL))
- return (NULL);
- }
-
- pmap_kernel_l2dtable_kva = nva;
-
- /*
- * Link it into the parent pmap
- */
- pmap->pm_l2[L2_IDX(l1idx)] = l2;
- memset(l2, 0, sizeof(*l2));
- }
-
- l2b = &l2->l2_bucket[L2_BUCKET(l1idx)];
-
- /*
- * Fetch pointer to the L2 page table associated with the address.
- */
- if (l2b->l2b_kva == NULL) {
- pt_entry_t *ptep;
-
- /*
- * No L2 page table has been allocated. Chances are, this
- * is because we just allocated the l2_dtable, above.
- */
- nva = pmap_kernel_l2ptp_kva;
- ptep = (pt_entry_t *)nva;
- if ((nva & PAGE_MASK) == 0) {
- /*
- * Need to allocate a backing page
- */
- if (pmap_grow_map(nva, pte_l2_s_cache_mode_pt,
- &pmap_kernel_l2ptp_phys))
- return (NULL);
- }
- memset(ptep, 0, L2_TABLE_SIZE_REAL);
- l2->l2_occupancy++;
- l2b->l2b_kva = ptep;
- l2b->l2b_l1idx = l1idx;
- l2b->l2b_phys = pmap_kernel_l2ptp_phys;
-
- pmap_kernel_l2ptp_kva += L2_TABLE_SIZE_REAL;
- pmap_kernel_l2ptp_phys += L2_TABLE_SIZE_REAL;
- }
-
- /* Distribute new L1 entry to all other L1s */
- SLIST_FOREACH(l1, &l1_list, l1_link) {
- pl1pd = &l1->l1_kva[L1_IDX(va)];
- *pl1pd = l2b->l2b_phys | L1_C_DOM(PMAP_DOMAIN_KERNEL) |
- L1_C_PROTO;
- PTE_SYNC(pl1pd);
- }
- cpu_tlb_flushID_SE(va);
- cpu_cpwait();
-
- return (l2b);
+ if (pmap == kernel_pmap || !CPU_EMPTY(&pmap->pm_active))
+ tlb_flush_range(sva, size);
}
-
/*
- * grow the number of kernel page table entries, if needed
+ * Abuse the pte2 nodes for unmapped kva to thread a kva freelist through.
+ * Requirements:
+ * - Must deal with pages in order to ensure that none of the PTE2_* bits
+ * are ever set, PTE2_V in particular.
+ * - Assumes we can write to pte2s without pte2_store() atomic ops.
+ * - Assumes nothing will ever test these addresses for 0 to indicate
+ * no mapping instead of correctly checking PTE2_V.
+ * - Assumes a vm_offset_t will fit in a pte2 (true for arm).
+ * Because PTE2_V is never set, there can be no mappings to invalidate.
*/
-void
-pmap_growkernel(vm_offset_t addr)
+static vm_offset_t
+pmap_pte2list_alloc(vm_offset_t *head)
{
- pmap_t kpmap = pmap_kernel();
-
- if (addr <= pmap_curmaxkvaddr)
- return; /* we are OK */
-
- /*
- * whoops! we need to add kernel PTPs
- */
-
- /* Map 1MB at a time */
- for (; pmap_curmaxkvaddr < addr; pmap_curmaxkvaddr += L1_S_SIZE)
- pmap_grow_l2_bucket(kpmap, pmap_curmaxkvaddr);
+ pt2_entry_t *pte2p;
+ vm_offset_t va;
- kernel_vm_end = pmap_curmaxkvaddr;
+ va = *head;
+ if (va == 0)
+ panic("pmap_ptelist_alloc: exhausted ptelist KVA");
+ pte2p = pt2map_entry(va);
+ *head = *pte2p;
+ if (*head & PTE2_V)
+ panic("%s: va with PTE2_V set!", __func__);
+ *pte2p = 0;
+ return (va);
}
-/*
- * Returns TRUE if the given page is mapped individually or as part of
- * a 1MB section. Otherwise, returns FALSE.
- */
-boolean_t
-pmap_page_is_mapped(vm_page_t m)
+static void
+pmap_pte2list_free(vm_offset_t *head, vm_offset_t va)
{
- boolean_t rv;
+ pt2_entry_t *pte2p;
- if ((m->oflags & VPO_UNMANAGED) != 0)
- return (FALSE);
- rw_wlock(&pvh_global_lock);
- rv = !TAILQ_EMPTY(&m->md.pv_list) ||
- ((m->flags & PG_FICTITIOUS) == 0 &&
- !TAILQ_EMPTY(&pa_to_pvh(VM_PAGE_TO_PHYS(m))->pv_list));
- rw_wunlock(&pvh_global_lock);
- return (rv);
+ if (va & PTE2_V)
+ panic("%s: freeing va with PTE2_V set!", __func__);
+ pte2p = pt2map_entry(va);
+ *pte2p = *head; /* virtual! PTE2_V is 0 though */
+ *head = va;
}
-/*
- * Remove all pages from specified address space
- * this aids process exit speeds. Also, this code
- * is special cased for current process only, but
- * can have the more generic (and slightly slower)
- * mode enabled. This is much faster than pmap_remove
- * in the case of running down an entire address space.
- */
-void
-pmap_remove_pages(pmap_t pmap)
+static void
+pmap_pte2list_init(vm_offset_t *head, void *base, int npages)
{
- struct pv_entry *pv;
- struct l2_bucket *l2b = NULL;
- struct pv_chunk *pc, *npc;
- struct md_page *pvh;
- pd_entry_t *pl1pd, l1pd;
- pt_entry_t *ptep;
- vm_page_t m, mt;
+ int i;
vm_offset_t va;
- uint32_t inuse, bitmask;
- int allfree, bit, field, idx;
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
+ *head = 0;
+ for (i = npages - 1; i >= 0; i--) {
+ va = (vm_offset_t)base + i * PAGE_SIZE;
+ pmap_pte2list_free(head, va);
+ }
+}
- TAILQ_FOREACH_SAFE(pc, &pmap->pm_pvchunk, pc_list, npc) {
- allfree = 1;
- for (field = 0; field < _NPCM; field++) {
- inuse = ~pc->pc_map[field] & pc_freemask[field];
- while (inuse != 0) {
- bit = ffs(inuse) - 1;
- bitmask = 1ul << bit;
- idx = field * sizeof(inuse) * NBBY + bit;
- pv = &pc->pc_pventry[idx];
- va = pv->pv_va;
- inuse &= ~bitmask;
- if (pv->pv_flags & PVF_WIRED) {
- /* Cannot remove wired pages now. */
- allfree = 0;
- continue;
- }
- pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
- l1pd = *pl1pd;
- l2b = pmap_get_l2_bucket(pmap, va);
- if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
- pvh = pa_to_pvh(l1pd & L1_S_FRAME);
- TAILQ_REMOVE(&pvh->pv_list, pv, pv_list);
- if (TAILQ_EMPTY(&pvh->pv_list)) {
- m = PHYS_TO_VM_PAGE(l1pd & L1_S_FRAME);
- KASSERT((vm_offset_t)m >= KERNBASE,
- ("Trying to access non-existent page "
- "va %x l1pd %x", trunc_1mpage(va), l1pd));
- for (mt = m; mt < &m[L2_PTE_NUM_TOTAL]; mt++) {
- if (TAILQ_EMPTY(&mt->md.pv_list))
- vm_page_aflag_clear(mt, PGA_WRITEABLE);
- }
- }
- if (l2b != NULL) {
- KASSERT(l2b->l2b_occupancy == L2_PTE_NUM_TOTAL,
- ("pmap_remove_pages: l2_bucket occupancy error"));
- pmap_free_l2_bucket(pmap, l2b, L2_PTE_NUM_TOTAL);
- }
- pmap->pm_stats.resident_count -= L2_PTE_NUM_TOTAL;
- *pl1pd = 0;
- PTE_SYNC(pl1pd);
- } else {
- KASSERT(l2b != NULL,
- ("No L2 bucket in pmap_remove_pages"));
- ptep = &l2b->l2b_kva[l2pte_index(va)];
- m = PHYS_TO_VM_PAGE(l2pte_pa(*ptep));
- KASSERT((vm_offset_t)m >= KERNBASE,
- ("Trying to access non-existent page "
- "va %x pte %x", va, *ptep));
- TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
- if (TAILQ_EMPTY(&m->md.pv_list) &&
- (m->flags & PG_FICTITIOUS) == 0) {
- pvh = pa_to_pvh(l2pte_pa(*ptep));
- if (TAILQ_EMPTY(&pvh->pv_list))
- vm_page_aflag_clear(m, PGA_WRITEABLE);
- }
- *ptep = 0;
- PTE_SYNC(ptep);
- pmap_free_l2_bucket(pmap, l2b, 1);
- pmap->pm_stats.resident_count--;
- }
+/*****************************************************************************
+ *
+ * PMAP third and final stage initialization.
+ *
+ * After pmap_init() is called, PMAP subsystem is fully initialized.
+ *
+ *****************************************************************************/
- /* Mark free */
- PV_STAT(pv_entry_frees++);
- PV_STAT(pv_entry_spare++);
- pv_entry_count--;
- pc->pc_map[field] |= bitmask;
- }
- }
- if (allfree) {
- TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
- pmap_free_pv_chunk(pc);
- }
+SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
- }
+SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_max, CTLFLAG_RD, &pv_entry_max, 0,
+ "Max number of PV entries");
+SYSCTL_INT(_vm_pmap, OID_AUTO, shpgperproc, CTLFLAG_RD, &shpgperproc, 0,
+ "Page share factor per proc");
- rw_wunlock(&pvh_global_lock);
- cpu_tlb_flushID();
- cpu_cpwait();
- PMAP_UNLOCK(pmap);
-}
+static u_long nkpt2pg = NKPT2PG;
+SYSCTL_ULONG(_vm_pmap, OID_AUTO, nkpt2pg, CTLFLAG_RD,
+ &nkpt2pg, 0, "Pre-allocated pages for kernel PT2s");
-static void
-pmap_init_qpages(void)
-{
- struct pcpu *pc;
- struct l2_bucket *l2b;
- int i;
+static int sp_enabled = 1;
+SYSCTL_INT(_vm_pmap, OID_AUTO, sp_enabled, CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
+ &sp_enabled, 0, "Are large page mappings enabled?");
- CPU_FOREACH(i) {
- pc = pcpu_find(i);
- pc->pc_qmap_addr = kva_alloc(PAGE_SIZE);
- if (pc->pc_qmap_addr == 0)
- panic("pmap_init_qpages: unable to allocate KVA");
+static SYSCTL_NODE(_vm_pmap, OID_AUTO, pte1, CTLFLAG_RD, 0,
+ "1MB page mapping counters");
- l2b = pmap_get_l2_bucket(pmap_kernel(), pc->pc_qmap_addr);
- if (l2b == NULL)
- l2b = pmap_grow_l2_bucket(pmap_kernel(),
- pc->pc_qmap_addr);
- if (l2b == NULL)
- panic("pmap_alloc_specials: no l2b for 0x%x",
- pc->pc_qmap_addr);
- pc->pc_qmap_pte = &l2b->l2b_kva[l2pte_index(pc->pc_qmap_addr)];
- }
-}
+static u_long pmap_pte1_demotions;
+SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, demotions, CTLFLAG_RD,
+ &pmap_pte1_demotions, 0, "1MB page demotions");
-SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, pmap_init_qpages, NULL);
+static u_long pmap_pte1_mappings;
+SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, mappings, CTLFLAG_RD,
+ &pmap_pte1_mappings, 0, "1MB page mappings");
-/***************************************************
- * Low level mapping routines.....
- ***************************************************/
+static u_long pmap_pte1_p_failures;
+SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, p_failures, CTLFLAG_RD,
+ &pmap_pte1_p_failures, 0, "1MB page promotion failures");
-#ifdef ARM_HAVE_SUPERSECTIONS
-/* Map a super section into the KVA. */
+static u_long pmap_pte1_promotions;
+SYSCTL_ULONG(_vm_pmap_pte1, OID_AUTO, promotions, CTLFLAG_RD,
+ &pmap_pte1_promotions, 0, "1MB page promotions");
-void
-pmap_kenter_supersection(vm_offset_t va, uint64_t pa, int flags)
-{
- pd_entry_t pd = L1_S_PROTO | L1_S_SUPERSEC | (pa & L1_SUP_FRAME) |
- (((pa >> 32) & 0xf) << 20) | L1_S_PROT(PTE_KERNEL,
- VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) |
- L1_S_DOM(PMAP_DOMAIN_KERNEL);
- struct l1_ttable *l1;
- vm_offset_t va0, va_end;
-
- KASSERT(((va | pa) & L1_SUP_OFFSET) == 0,
- ("Not a valid super section mapping"));
- if (flags & SECTION_CACHE)
- pd |= pte_l1_s_cache_mode;
- else if (flags & SECTION_PT)
- pd |= pte_l1_s_cache_mode_pt;
-
- va0 = va & L1_SUP_FRAME;
- va_end = va + L1_SUP_SIZE;
- SLIST_FOREACH(l1, &l1_list, l1_link) {
- va = va0;
- for (; va < va_end; va += L1_S_SIZE) {
- l1->l1_kva[L1_IDX(va)] = pd;
- PTE_SYNC(&l1->l1_kva[L1_IDX(va)]);
- }
- }
-}
-#endif
+static __inline ttb_entry_t
+pmap_ttb_get(pmap_t pmap)
+{
-/* Map a section into the KVA. */
+ return (vtophys(pmap->pm_pt1) | ttb_flags);
+}
+/*
+ * Initialize a vm_page's machine-dependent fields.
+ *
+ * Variations:
+ * 1. Pages for L2 page tables are always not managed. So, pv_list and
+ * pt2_wirecount can share same physical space. However, proper
+ * initialization on a page alloc for page tables and reinitialization
+ * on the page free must be ensured.
+ */
void
-pmap_kenter_section(vm_offset_t va, vm_offset_t pa, int flags)
+pmap_page_init(vm_page_t m)
{
- pd_entry_t pd = L1_S_PROTO | pa | L1_S_PROT(PTE_KERNEL,
- VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) | L1_S_REF |
- L1_S_DOM(PMAP_DOMAIN_KERNEL);
- struct l1_ttable *l1;
-
- KASSERT(((va | pa) & L1_S_OFFSET) == 0,
- ("Not a valid section mapping"));
- if (flags & SECTION_CACHE)
- pd |= pte_l1_s_cache_mode;
- else if (flags & SECTION_PT)
- pd |= pte_l1_s_cache_mode_pt;
- SLIST_FOREACH(l1, &l1_list, l1_link) {
- l1->l1_kva[L1_IDX(va)] = pd;
- PTE_SYNC(&l1->l1_kva[L1_IDX(va)]);
- }
- cpu_tlb_flushID_SE(va);
- cpu_cpwait();
+ TAILQ_INIT(&m->md.pv_list);
+ pt2_wirecount_init(m);
+ m->md.pat_mode = VM_MEMATTR_DEFAULT;
}
/*
- * Make a temporary mapping for a physical address. This is only intended
- * to be used for panic dumps.
+ * Virtualization for faster way how to zero whole page.
*/
-void *
-pmap_kenter_temporary(vm_paddr_t pa, int i)
+static __inline void
+pagezero(void *page)
{
- vm_offset_t va;
- va = (vm_offset_t)crashdumpmap + (i * PAGE_SIZE);
- pmap_kenter(va, pa);
- return ((void *)crashdumpmap);
+ bzero(page, PAGE_SIZE);
}
/*
- * add a wired page to the kva
- * note that in order for the mapping to take effect -- you
- * should do a invltlb after doing the pmap_kenter...
+ * Zero L2 page table page.
+ * Use same KVA as in pmap_zero_page().
*/
-static PMAP_INLINE void
-pmap_kenter_internal(vm_offset_t va, vm_offset_t pa, int flags)
+static __inline vm_paddr_t
+pmap_pt2pg_zero(vm_page_t m)
{
- struct l2_bucket *l2b;
- pt_entry_t *ptep;
- pt_entry_t opte;
+ vm_paddr_t pa;
+ struct sysmaps *sysmaps;
- PDEBUG(1, printf("pmap_kenter: va = %08x, pa = %08x\n",
- (uint32_t) va, (uint32_t) pa));
+ pa = VM_PAGE_TO_PHYS(m);
+ /*
+ * XXX: For now, we map whole page even if it's already zero,
+ * to sync it even if the sync is only DSB.
+ */
+ sched_pin();
+ sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
+ mtx_lock(&sysmaps->lock);
+ if (pte2_load(sysmaps->CMAP2) != 0)
+ panic("%s: CMAP2 busy", __func__);
+ pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW,
+ vm_page_pte2_attr(m)));
+ /* Even VM_ALLOC_ZERO request is only advisory. */
+ if ((m->flags & PG_ZERO) == 0)
+ pagezero(sysmaps->CADDR2);
+ pte2_sync_range((pt2_entry_t *)sysmaps->CADDR2, PAGE_SIZE);
+ pte2_clear(sysmaps->CMAP2);
+ tlb_flush((vm_offset_t)sysmaps->CADDR2);
+ sched_unpin();
+ mtx_unlock(&sysmaps->lock);
- l2b = pmap_get_l2_bucket(pmap_kernel(), va);
- if (l2b == NULL)
- l2b = pmap_grow_l2_bucket(pmap_kernel(), va);
- KASSERT(l2b != NULL, ("No L2 Bucket"));
+ return (pa);
+}
- ptep = &l2b->l2b_kva[l2pte_index(va)];
- opte = *ptep;
+/*
+ * Init just allocated page as L2 page table(s) holder
+ * and return its physical address.
+ */
+static __inline vm_paddr_t
+pmap_pt2pg_init(pmap_t pmap, vm_offset_t va, vm_page_t m)
+{
+ vm_paddr_t pa;
+ pt2_entry_t *pte2p;
- if (flags & KENTER_CACHE)
- *ptep = L2_S_PROTO | l2s_mem_types[PTE_CACHE] | pa | L2_S_REF;
- else if (flags & KENTER_DEVICE)
- *ptep = L2_S_PROTO | l2s_mem_types[PTE_DEVICE] | pa | L2_S_REF;
- else
- *ptep = L2_S_PROTO | l2s_mem_types[PTE_NOCACHE] | pa | L2_S_REF;
+ /* Check page attributes. */
+ if (m->md.pat_mode != pt_memattr)
+ pmap_page_set_memattr(m, pt_memattr);
- if (flags & KENTER_CACHE) {
- pmap_set_prot(ptep, VM_PROT_READ | VM_PROT_WRITE,
- flags & KENTER_USER);
- } else {
- pmap_set_prot(ptep, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
- 0);
- }
+ /* Zero page and init wire counts. */
+ pa = pmap_pt2pg_zero(m);
+ pt2_wirecount_init(m);
- PTE_SYNC(ptep);
- if (l2pte_valid(opte)) {
- if (L2_S_EXECUTABLE(opte) || L2_S_EXECUTABLE(*ptep))
- cpu_tlb_flushID_SE(va);
- else
- cpu_tlb_flushD_SE(va);
- } else {
- if (opte == 0)
- l2b->l2b_occupancy++;
+ /*
+ * Map page to PT2MAP address space for given pmap.
+ * Note that PT2MAP space is shared with all pmaps.
+ */
+ if (pmap == kernel_pmap)
+ pmap_kenter_pt2tab(va, PTE2_KPT(pa));
+ else {
+ pte2p = pmap_pt2tab_entry(pmap, va);
+ pt2tab_store(pte2p, PTE2_KPT_NG(pa));
}
- cpu_cpwait();
- PDEBUG(1, printf("pmap_kenter: pte = %08x, opte = %08x, npte = %08x\n",
- (uint32_t) ptep, opte, *ptep));
+ return (pa);
}
+/*
+ * Initialize the pmap module.
+ * Called by vm_init, to initialize any structures that the pmap
+ * system needs to map virtual memory.
+ */
void
-pmap_kenter(vm_offset_t va, vm_paddr_t pa)
+pmap_init(void)
{
- pmap_kenter_internal(va, pa, KENTER_CACHE);
-}
+ vm_size_t s;
+ pt2_entry_t *pte2p, pte2;
+ u_int i, pte1_idx, pv_npg;
-void
-pmap_kenter_nocache(vm_offset_t va, vm_paddr_t pa)
-{
+ PDEBUG(1, printf("%s: phys_start = %#x\n", __func__, PHYSADDR));
- pmap_kenter_internal(va, pa, 0);
-}
+ /*
+ * Initialize the vm page array entries for kernel pmap's
+ * L2 page table pages allocated in advance.
+ */
+ pte1_idx = pte1_index(KERNBASE - PT2MAP_SIZE);
+ pte2p = kern_pt2tab_entry(KERNBASE - PT2MAP_SIZE);
+ for (i = 0; i < nkpt2pg + NPG_IN_PT2TAB; i++, pte2p++) {
+ vm_paddr_t pa;
+ vm_page_t m;
-void
-pmap_kenter_device(vm_offset_t va, vm_size_t size, vm_paddr_t pa)
-{
- vm_offset_t sva;
+ pte2 = pte2_load(pte2p);
+ KASSERT(pte2_is_valid(pte2), ("%s: no valid entry", __func__));
- KASSERT((size & PAGE_MASK) == 0,
- ("%s: device mapping not page-sized", __func__));
+ pa = pte2_pa(pte2);
+ m = PHYS_TO_VM_PAGE(pa);
+ KASSERT(m >= vm_page_array &&
+ m < &vm_page_array[vm_page_array_size],
+ ("%s: L2 page table page is out of range", __func__));
- sva = va;
- while (size != 0) {
- pmap_kenter_internal(va, pa, KENTER_DEVICE);
- va += PAGE_SIZE;
- pa += PAGE_SIZE;
- size -= PAGE_SIZE;
+ m->pindex = pte1_idx;
+ m->phys_addr = pa;
+ pte1_idx += NPT2_IN_PG;
}
-}
-
-void
-pmap_kremove_device(vm_offset_t va, vm_size_t size)
-{
- vm_offset_t sva;
- KASSERT((size & PAGE_MASK) == 0,
- ("%s: device mapping not page-sized", __func__));
+ /*
+ * Initialize the address space (zone) for the pv entries. Set a
+ * high water mark so that the system can recover from excessive
+ * numbers of pv entries.
+ */
+ TUNABLE_INT_FETCH("vm.pmap.shpgperproc", &shpgperproc);
+ pv_entry_max = shpgperproc * maxproc + vm_cnt.v_page_count;
+ TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max);
+ pv_entry_max = roundup(pv_entry_max, _NPCPV);
+ pv_entry_high_water = 9 * (pv_entry_max / 10);
- sva = va;
- while (size != 0) {
- pmap_kremove(va);
- va += PAGE_SIZE;
- size -= PAGE_SIZE;
+ /*
+ * Are large page mappings enabled?
+ */
+ TUNABLE_INT_FETCH("vm.pmap.sp_enabled", &sp_enabled);
+ if (sp_enabled) {
+ KASSERT(MAXPAGESIZES > 1 && pagesizes[1] == 0,
+ ("%s: can't assign to pagesizes[1]", __func__));
+ pagesizes[1] = PTE1_SIZE;
}
-}
-void
-pmap_kenter_user(vm_offset_t va, vm_paddr_t pa)
-{
-
- pmap_kenter_internal(va, pa, KENTER_CACHE|KENTER_USER);
/*
- * Call pmap_fault_fixup now, to make sure we'll have no exception
- * at the first use of the new address, or bad things will happen,
- * as we use one of these addresses in the exception handlers.
+ * Calculate the size of the pv head table for sections.
+ * Handle the possibility that "vm_phys_segs[...].end" is zero.
+ * Note that the table is only for sections which could be promoted.
*/
- pmap_fault_fixup(pmap_kernel(), va, VM_PROT_READ|VM_PROT_WRITE, 1);
-}
+ first_managed_pa = pte1_trunc(vm_phys_segs[0].start);
+ pv_npg = (pte1_trunc(vm_phys_segs[vm_phys_nsegs - 1].end - PAGE_SIZE)
+ - first_managed_pa) / PTE1_SIZE + 1;
-vm_paddr_t
-pmap_kextract(vm_offset_t va)
-{
+ /*
+ * Allocate memory for the pv head table for sections.
+ */
+ s = (vm_size_t)(pv_npg * sizeof(struct md_page));
+ s = round_page(s);
+ pv_table = (struct md_page *)kmem_malloc(kernel_arena, s,
+ M_WAITOK | M_ZERO);
+ for (i = 0; i < pv_npg; i++)
+ TAILQ_INIT(&pv_table[i].pv_list);
- if (kernel_vm_end == 0)
- return (0);
- return (pmap_extract_locked(kernel_pmap, va));
+ pv_maxchunks = MAX(pv_entry_max / _NPCPV, maxproc);
+ pv_chunkbase = (struct pv_chunk *)kva_alloc(PAGE_SIZE * pv_maxchunks);
+ if (pv_chunkbase == NULL)
+ panic("%s: not enough kvm for pv chunks", __func__);
+ pmap_pte2list_init(&pv_vafree, pv_chunkbase, pv_maxchunks);
}
/*
- * remove a page from the kernel pagetables
+ * Add a list of wired pages to the kva
+ * this routine is only used for temporary
+ * kernel mappings that do not need to have
+ * page modification or references recorded.
+ * Note that old mappings are simply written
+ * over. The page *must* be wired.
+ * Note: SMP coherent. Uses a ranged shootdown IPI.
*/
void
-pmap_kremove(vm_offset_t va)
+pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count)
{
- struct l2_bucket *l2b;
- pt_entry_t *ptep, opte;
+ u_int anychanged;
+ pt2_entry_t *epte2p, *pte2p, pte2;
+ vm_page_t m;
+ vm_paddr_t pa;
- l2b = pmap_get_l2_bucket(pmap_kernel(), va);
- if (!l2b)
- return;
- KASSERT(l2b != NULL, ("No L2 Bucket"));
- ptep = &l2b->l2b_kva[l2pte_index(va)];
- opte = *ptep;
- if (l2pte_valid(opte)) {
- va = va & ~PAGE_MASK;
- *ptep = 0;
- PTE_SYNC(ptep);
- if (L2_S_EXECUTABLE(opte))
- cpu_tlb_flushID_SE(va);
- else
- cpu_tlb_flushD_SE(va);
- cpu_cpwait();
+ anychanged = 0;
+ pte2p = pt2map_entry(sva);
+ epte2p = pte2p + count;
+ while (pte2p < epte2p) {
+ m = *ma++;
+ pa = VM_PAGE_TO_PHYS(m);
+ pte2 = pte2_load(pte2p);
+ if ((pte2_pa(pte2) != pa) ||
+ (pte2_attr(pte2) != vm_page_pte2_attr(m))) {
+ anychanged++;
+ pte2_store(pte2p, PTE2_KERN(pa, PTE2_AP_KRW,
+ vm_page_pte2_attr(m)));
+ }
+ pte2p++;
}
+ if (__predict_false(anychanged))
+ tlb_flush_range(sva, count * PAGE_SIZE);
}
-
/*
- * Used to map a range of physical addresses into kernel
- * virtual address space.
- *
- * The value passed in '*virt' is a suggested virtual address for
- * the mapping. Architectures which can support a direct-mapped
- * physical to virtual region can return the appropriate address
- * within that region, leaving '*virt' unchanged. Other
- * architectures should map the pages starting at '*virt' and
- * update '*virt' with the first usable address after the mapped
- * region.
+ * This routine tears out page mappings from the
+ * kernel -- it is meant only for temporary mappings.
+ * Note: SMP coherent. Uses a ranged shootdown IPI.
*/
-vm_offset_t
-pmap_map(vm_offset_t *virt, vm_offset_t start, vm_offset_t end, int prot)
+void
+pmap_qremove(vm_offset_t sva, int count)
{
- vm_offset_t sva = *virt;
- vm_offset_t va = sva;
-
- PDEBUG(1, printf("pmap_map: virt = %08x, start = %08x, end = %08x, "
- "prot = %d\n", (uint32_t) *virt, (uint32_t) start, (uint32_t) end,
- prot));
+ vm_offset_t va;
- while (start < end) {
- pmap_kenter(va, start);
+ va = sva;
+ while (count-- > 0) {
+ pmap_kremove(va);
va += PAGE_SIZE;
- start += PAGE_SIZE;
}
- *virt = va;
- return (sva);
+ tlb_flush_range(sva, va - sva);
}
/*
- * Add a list of wired pages to the kva
- * this routine is only used for temporary
- * kernel mappings that do not need to have
- * page modification or references recorded.
- * Note that old mappings are simply written
- * over. The page *must* be wired.
+ * Are we current address space or kernel?
*/
-void
-pmap_qenter(vm_offset_t va, vm_page_t *m, int count)
+static __inline int
+pmap_is_current(pmap_t pmap)
{
- int i;
- for (i = 0; i < count; i++) {
- pmap_kenter_internal(va, VM_PAGE_TO_PHYS(m[i]),
- KENTER_CACHE);
- va += PAGE_SIZE;
- }
+ return (pmap == kernel_pmap ||
+ (pmap == vmspace_pmap(curthread->td_proc->p_vmspace)));
}
-
/*
- * this routine jerks page mappings from the
- * kernel -- it is meant only for temporary mappings.
+ * If the given pmap is not the current or kernel pmap, the returned
+ * pte2 must be released by passing it to pmap_pte2_release().
*/
-void
-pmap_qremove(vm_offset_t va, int count)
+static pt2_entry_t *
+pmap_pte2(pmap_t pmap, vm_offset_t va)
{
- int i;
-
- for (i = 0; i < count; i++) {
- if (vtophys(va))
- pmap_kremove(va);
-
- va += PAGE_SIZE;
+ pt1_entry_t pte1;
+ vm_paddr_t pt2pg_pa;
+
+ pte1 = pte1_load(pmap_pte1(pmap, va));
+ if (pte1_is_section(pte1))
+ panic("%s: attempt to map PTE1", __func__);
+ if (pte1_is_link(pte1)) {
+ /* Are we current address space or kernel? */
+ if (pmap_is_current(pmap))
+ return (pt2map_entry(va));
+ /* Note that L2 page table size is not equal to PAGE_SIZE. */
+ pt2pg_pa = trunc_page(pte1_link_pa(pte1));
+ mtx_lock(&PMAP2mutex);
+ if (pte2_pa(pte2_load(PMAP2)) != pt2pg_pa) {
+ pte2_store(PMAP2, PTE2_KPT(pt2pg_pa));
+ tlb_flush((vm_offset_t)PADDR2);
+ }
+ return (PADDR2 + (arm32_btop(va) & (NPTE2_IN_PG - 1)));
}
+ return (NULL);
}
-
/*
- * pmap_object_init_pt preloads the ptes for a given object
- * into the specified pmap. This eliminates the blast of soft
- * faults on process startup and immediately after an mmap.
+ * Releases a pte2 that was obtained from pmap_pte2().
+ * Be prepared for the pte2p being NULL.
*/
-void
-pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object,
- vm_pindex_t pindex, vm_size_t size)
+static __inline void
+pmap_pte2_release(pt2_entry_t *pte2p)
{
- VM_OBJECT_ASSERT_WLOCKED(object);
- KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG,
- ("pmap_object_init_pt: non-device object"));
+ if ((pt2_entry_t *)(trunc_page((vm_offset_t)pte2p)) == PADDR2) {
+ mtx_unlock(&PMAP2mutex);
+ }
}
-
/*
- * pmap_is_prefaultable:
+ * Super fast pmap_pte2 routine best used when scanning
+ * the pv lists. This eliminates many coarse-grained
+ * invltlb calls. Note that many of the pv list
+ * scans are across different pmaps. It is very wasteful
+ * to do an entire tlb flush for checking a single mapping.
*
- * Return whether or not the specified virtual address is elgible
- * for prefault.
+ * If the given pmap is not the current pmap, pvh_global_lock
+ * must be held and curthread pinned to a CPU.
*/
-boolean_t
-pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr)
+static pt2_entry_t *
+pmap_pte2_quick(pmap_t pmap, vm_offset_t va)
{
- pd_entry_t *pdep;
- pt_entry_t *ptep;
-
- if (!pmap_get_pde_pte(pmap, addr, &pdep, &ptep))
- return (FALSE);
- KASSERT((pdep != NULL && (l1pte_section_p(*pdep) || ptep != NULL)),
- ("Valid mapping but no pte ?"));
- if (*pdep != 0 && !l1pte_section_p(*pdep))
- if (*ptep == 0)
- return (TRUE);
- return (FALSE);
+ pt1_entry_t pte1;
+ vm_paddr_t pt2pg_pa;
+
+ pte1 = pte1_load(pmap_pte1(pmap, va));
+ if (pte1_is_section(pte1))
+ panic("%s: attempt to map PTE1", __func__);
+ if (pte1_is_link(pte1)) {
+ /* Are we current address space or kernel? */
+ if (pmap_is_current(pmap))
+ return (pt2map_entry(va));
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ KASSERT(curthread->td_pinned > 0,
+ ("%s: curthread not pinned", __func__));
+ /* Note that L2 page table size is not equal to PAGE_SIZE. */
+ pt2pg_pa = trunc_page(pte1_link_pa(pte1));
+ if (pte2_pa(pte2_load(PMAP1)) != pt2pg_pa) {
+ pte2_store(PMAP1, PTE2_KPT(pt2pg_pa));
+#ifdef SMP
+ PMAP1cpu = PCPU_GET(cpuid);
+#endif
+ tlb_flush_local((vm_offset_t)PADDR1);
+ PMAP1changed++;
+ } else
+#ifdef SMP
+ if (PMAP1cpu != PCPU_GET(cpuid)) {
+ PMAP1cpu = PCPU_GET(cpuid);
+ tlb_flush_local((vm_offset_t)PADDR1);
+ PMAP1changedcpu++;
+ } else
+#endif
+ PMAP1unchanged++;
+ return (PADDR1 + (arm32_btop(va) & (NPTE2_IN_PG - 1)));
+ }
+ return (NULL);
}
/*
- * Fetch pointers to the PDE/PTE for the given pmap/VA pair.
- * Returns TRUE if the mapping exists, else FALSE.
- *
- * NOTE: This function is only used by a couple of arm-specific modules.
- * It is not safe to take any pmap locks here, since we could be right
- * in the middle of debugging the pmap anyway...
- *
- * It is possible for this routine to return FALSE even though a valid
- * mapping does exist. This is because we don't lock, so the metadata
- * state may be inconsistent.
- *
- * NOTE: We can return a NULL *ptp in the case where the L1 pde is
- * a "section" mapping.
+ * Routine: pmap_extract
+ * Function:
+ * Extract the physical page address associated
+ * with the given map/virtual_address pair.
*/
-boolean_t
-pmap_get_pde_pte(pmap_t pmap, vm_offset_t va, pd_entry_t **pdp,
- pt_entry_t **ptp)
+vm_paddr_t
+pmap_extract(pmap_t pmap, vm_offset_t va)
{
- struct l2_dtable *l2;
- pd_entry_t *pl1pd, l1pd;
- pt_entry_t *ptep;
- u_short l1idx;
-
- if (pmap->pm_l1 == NULL)
- return (FALSE);
-
- l1idx = L1_IDX(va);
- *pdp = pl1pd = &pmap->pm_l1->l1_kva[l1idx];
- l1pd = *pl1pd;
-
- if (l1pte_section_p(l1pd)) {
- *ptp = NULL;
- return (TRUE);
- }
-
- if (pmap->pm_l2 == NULL)
- return (FALSE);
-
- l2 = pmap->pm_l2[L2_IDX(l1idx)];
-
- if (l2 == NULL ||
- (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) {
- return (FALSE);
- }
+ vm_paddr_t pa;
+ pt1_entry_t pte1;
+ pt2_entry_t *pte2p;
- *ptp = &ptep[l2pte_index(va)];
- return (TRUE);
+ PMAP_LOCK(pmap);
+ pte1 = pte1_load(pmap_pte1(pmap, va));
+ if (pte1_is_section(pte1))
+ pa = pte1_pa(pte1) | (va & PTE1_OFFSET);
+ else if (pte1_is_link(pte1)) {
+ pte2p = pmap_pte2(pmap, va);
+ pa = pte2_pa(pte2_load(pte2p)) | (va & PTE2_OFFSET);
+ pmap_pte2_release(pte2p);
+ } else
+ pa = 0;
+ PMAP_UNLOCK(pmap);
+ return (pa);
}
/*
- * Routine: pmap_remove_all
- * Function:
- * Removes this physical page from
- * all physical maps in which it resides.
- * Reflects back modify bits to the pager.
- *
- * Notes:
- * Original versions of this routine were very
- * inefficient because they iteratively called
- * pmap_remove (slow...)
+ * Routine: pmap_extract_and_hold
+ * Function:
+ * Atomically extract and hold the physical page
+ * with the given pmap and virtual address pair
+ * if that mapping permits the given protection.
*/
-void
-pmap_remove_all(vm_page_t m)
-{
- struct md_page *pvh;
- pv_entry_t pv;
- pmap_t pmap;
- pt_entry_t *ptep;
- struct l2_bucket *l2b;
- boolean_t flush = FALSE;
- pmap_t curpmap;
- u_int is_exec = 0;
-
- KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("pmap_remove_all: page %p is not managed", m));
- rw_wlock(&pvh_global_lock);
- if ((m->flags & PG_FICTITIOUS) != 0)
- goto small_mappings;
- pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
- while ((pv = TAILQ_FIRST(&pvh->pv_list)) != NULL) {
- pmap = PV_PMAP(pv);
- PMAP_LOCK(pmap);
- pd_entry_t *pl1pd;
- pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(pv->pv_va)];
- KASSERT((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO,
- ("pmap_remove_all: valid section mapping expected"));
- (void)pmap_demote_section(pmap, pv->pv_va);
- PMAP_UNLOCK(pmap);
- }
-small_mappings:
- curpmap = vmspace_pmap(curproc->p_vmspace);
- while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
- pmap = PV_PMAP(pv);
- if (flush == FALSE && (pmap == curpmap ||
- pmap == pmap_kernel()))
- flush = TRUE;
-
- PMAP_LOCK(pmap);
- l2b = pmap_get_l2_bucket(pmap, pv->pv_va);
- KASSERT(l2b != NULL, ("No l2 bucket"));
- ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
- is_exec |= PTE_BEEN_EXECD(*ptep);
- *ptep = 0;
- if (pmap_is_current(pmap))
- PTE_SYNC(ptep);
- pmap_free_l2_bucket(pmap, l2b, 1);
- pmap->pm_stats.resident_count--;
- TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
- if (pv->pv_flags & PVF_WIRED)
- pmap->pm_stats.wired_count--;
- pmap_free_pv_entry(pmap, pv);
- PMAP_UNLOCK(pmap);
- }
-
- if (flush) {
- if (is_exec)
- cpu_tlb_flushID();
- else
- cpu_tlb_flushD();
- cpu_cpwait();
- }
- vm_page_aflag_clear(m, PGA_WRITEABLE);
- rw_wunlock(&pvh_global_lock);
-}
-
-int
-pmap_change_attr(vm_offset_t sva, vm_size_t len, int mode)
+vm_page_t
+pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
{
- vm_offset_t base, offset, tmpva;
- vm_size_t size;
- struct l2_bucket *l2b;
- pt_entry_t *ptep, pte;
- vm_offset_t next_bucket;
-
- PMAP_LOCK(kernel_pmap);
-
- base = trunc_page(sva);
- offset = sva & PAGE_MASK;
- size = roundup(offset + len, PAGE_SIZE);
-
- for (tmpva = base; tmpva < base + size; ) {
- next_bucket = L2_NEXT_BUCKET(tmpva);
- if (next_bucket > base + size)
- next_bucket = base + size;
+ vm_paddr_t pa, lockpa;
+ pt1_entry_t pte1;
+ pt2_entry_t pte2, *pte2p;
+ vm_page_t m;
- l2b = pmap_get_l2_bucket(kernel_pmap, tmpva);
- if (l2b == NULL) {
- tmpva = next_bucket;
- continue;
+ lockpa = 0;
+ m = NULL;
+ PMAP_LOCK(pmap);
+retry:
+ pte1 = pte1_load(pmap_pte1(pmap, va));
+ if (pte1_is_section(pte1)) {
+ if (!(pte1 & PTE1_RO) || !(prot & VM_PROT_WRITE)) {
+ pa = pte1_pa(pte1) | (va & PTE1_OFFSET);
+ if (vm_page_pa_tryrelock(pmap, pa, &lockpa))
+ goto retry;
+ m = PHYS_TO_VM_PAGE(pa);
+ vm_page_hold(m);
}
-
- ptep = &l2b->l2b_kva[l2pte_index(tmpva)];
-
- if (*ptep == 0) {
- PMAP_UNLOCK(kernel_pmap);
- return(EINVAL);
+ } else if (pte1_is_link(pte1)) {
+ pte2p = pmap_pte2(pmap, va);
+ pte2 = pte2_load(pte2p);
+ pmap_pte2_release(pte2p);
+ if (pte2_is_valid(pte2) &&
+ (!(pte2 & PTE2_RO) || !(prot & VM_PROT_WRITE))) {
+ pa = pte2_pa(pte2);
+ if (vm_page_pa_tryrelock(pmap, pa, &lockpa))
+ goto retry;
+ m = PHYS_TO_VM_PAGE(pa);
+ vm_page_hold(m);
}
-
- pte = *ptep &~ L2_S_CACHE_MASK;
- cpu_idcache_wbinv_range(tmpva, PAGE_SIZE);
- pmap_l2cache_wbinv_range(tmpva, pte & L2_S_FRAME, PAGE_SIZE);
- *ptep = pte;
- cpu_tlb_flushID_SE(tmpva);
- cpu_cpwait();
-
- dprintf("%s: for va:%x ptep:%x pte:%x\n",
- __func__, tmpva, (uint32_t)ptep, pte);
- tmpva += PAGE_SIZE;
}
-
- PMAP_UNLOCK(kernel_pmap);
-
- return (0);
+ PA_UNLOCK_COND(lockpa);
+ PMAP_UNLOCK(pmap);
+ return (m);
}
/*
- * Set the physical protection on the
- * specified range of this map as requested.
+ * Grow the number of kernel L2 page table entries, if needed.
*/
void
-pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
+pmap_growkernel(vm_offset_t addr)
{
- struct l2_bucket *l2b;
- struct md_page *pvh;
- struct pv_entry *pve;
- pd_entry_t *pl1pd, l1pd;
- pt_entry_t *ptep, pte;
- vm_offset_t next_bucket;
- u_int is_exec, is_refd;
- int flush;
-
- if ((prot & VM_PROT_READ) == 0) {
- pmap_remove(pmap, sva, eva);
- return;
- }
-
- if (prot & VM_PROT_WRITE) {
- /*
- * If this is a read->write transition, just ignore it and let
- * vm_fault() take care of it later.
- */
- return;
- }
-
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
+ vm_page_t m;
+ vm_paddr_t pt2pg_pa, pt2_pa;
+ pt1_entry_t pte1;
+ pt2_entry_t pte2;
+ PDEBUG(1, printf("%s: addr = %#x\n", __func__, addr));
/*
- * OK, at this point, we know we're doing write-protect operation.
- * If the pmap is active, write-back the range.
+ * All the time kernel_vm_end is first KVA for which underlying
+ * L2 page table is either not allocated or linked from L1 page table
+ * (not considering sections). Except for two possible cases:
+ *
+ * (1) in the very beginning as long as pmap_growkernel() was
+ * not called, it could be first unused KVA (which is not
+ * rounded up to PTE1_SIZE),
+ *
+ * (2) when all KVA space is mapped and kernel_map->max_offset
+ * address is not rounded up to PTE1_SIZE. (For example,
+ * it could be 0xFFFFFFFF.)
*/
-
- flush = ((eva - sva) >= (PAGE_SIZE * 4)) ? 0 : -1;
- is_exec = is_refd = 0;
-
- while (sva < eva) {
- next_bucket = L2_NEXT_BUCKET(sva);
- /*
- * Check for large page.
- */
- pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(sva)];
- l1pd = *pl1pd;
- if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
- KASSERT(pmap != pmap_kernel(),
- ("pmap_protect: trying to modify "
- "kernel section protections"));
- /*
- * Are we protecting the entire large page? If not,
- * demote the mapping and fall through.
- */
- if (sva + L1_S_SIZE == next_bucket &&
- eva >= next_bucket) {
- l1pd &= ~(L1_S_PROT_MASK | L1_S_XN);
- if (!(prot & VM_PROT_EXECUTE))
- l1pd |= L1_S_XN;
- /*
- * At this point we are always setting
- * write-protect bit.
- */
- l1pd |= L1_S_APX;
- /* All managed superpages are user pages. */
- l1pd |= L1_S_PROT_U;
- *pl1pd = l1pd;
- PTE_SYNC(pl1pd);
- pvh = pa_to_pvh(l1pd & L1_S_FRAME);
- pve = pmap_find_pv(pvh, pmap,
- trunc_1mpage(sva));
- pve->pv_flags &= ~PVF_WRITE;
- sva = next_bucket;
- continue;
- } else if (!pmap_demote_section(pmap, sva)) {
- /* The large page mapping was destroyed. */
- sva = next_bucket;
- continue;
+ kernel_vm_end = pte1_roundup(kernel_vm_end);
+ mtx_assert(&kernel_map->system_mtx, MA_OWNED);
+ addr = roundup2(addr, PTE1_SIZE);
+ if (addr - 1 >= kernel_map->max_offset)
+ addr = kernel_map->max_offset;
+ while (kernel_vm_end < addr) {
+ pte1 = pte1_load(kern_pte1(kernel_vm_end));
+ if (pte1_is_valid(pte1)) {
+ kernel_vm_end += PTE1_SIZE;
+ if (kernel_vm_end - 1 >= kernel_map->max_offset) {
+ kernel_vm_end = kernel_map->max_offset;
+ break;
}
- }
- if (next_bucket > eva)
- next_bucket = eva;
- l2b = pmap_get_l2_bucket(pmap, sva);
- if (l2b == NULL) {
- sva = next_bucket;
continue;
}
- ptep = &l2b->l2b_kva[l2pte_index(sva)];
-
- while (sva < next_bucket) {
- if ((pte = *ptep) != 0 && L2_S_WRITABLE(pte)) {
- struct vm_page *m;
-
- m = PHYS_TO_VM_PAGE(l2pte_pa(pte));
- pmap_set_prot(ptep, prot,
- !(pmap == pmap_kernel()));
- PTE_SYNC(ptep);
+ /*
+ * kernel_vm_end_new is used in pmap_pinit() when kernel
+ * mappings are entered to new pmap all at once to avoid race
+ * between pmap_kenter_pte1() and kernel_vm_end increase.
+ * The same aplies to pmap_kenter_pt2tab().
+ */
+ kernel_vm_end_new = kernel_vm_end + PTE1_SIZE;
- pmap_modify_pv(m, pmap, sva, PVF_WRITE, 0);
+ pte2 = pt2tab_load(kern_pt2tab_entry(kernel_vm_end));
+ if (!pte2_is_valid(pte2)) {
+ /*
+ * Install new PT2s page into kernel PT2TAB.
+ */
+ m = vm_page_alloc(NULL,
+ pte1_index(kernel_vm_end) & ~PT2PG_MASK,
+ VM_ALLOC_INTERRUPT | VM_ALLOC_NOOBJ |
+ VM_ALLOC_WIRED | VM_ALLOC_ZERO);
+ if (m == NULL)
+ panic("%s: no memory to grow kernel", __func__);
+ /*
+ * QQQ: To link all new L2 page tables from L1 page
+ * table now and so pmap_kenter_pte1() them
+ * at once together with pmap_kenter_pt2tab()
+ * could be nice speed up. However,
+ * pmap_growkernel() does not happen so often...
+ * QQQ: The other TTBR is another option.
+ */
+ pt2pg_pa = pmap_pt2pg_init(kernel_pmap, kernel_vm_end,
+ m);
+ } else
+ pt2pg_pa = pte2_pa(pte2);
- if (flush >= 0) {
- flush++;
- is_exec |= PTE_BEEN_EXECD(pte);
- is_refd |= PTE_BEEN_REFD(pte);
- } else {
- if (PTE_BEEN_EXECD(pte))
- cpu_tlb_flushID_SE(sva);
- else if (PTE_BEEN_REFD(pte))
- cpu_tlb_flushD_SE(sva);
- }
- }
+ pt2_pa = page_pt2pa(pt2pg_pa, pte1_index(kernel_vm_end));
+ pmap_kenter_pte1(kernel_vm_end, PTE1_LINK(pt2_pa));
- sva += PAGE_SIZE;
- ptep++;
+ kernel_vm_end = kernel_vm_end_new;
+ if (kernel_vm_end - 1 >= kernel_map->max_offset) {
+ kernel_vm_end = kernel_map->max_offset;
+ break;
}
}
-
-
- if (flush) {
- if (is_exec)
- cpu_tlb_flushID();
- else
- if (is_refd)
- cpu_tlb_flushD();
- cpu_cpwait();
- }
- rw_wunlock(&pvh_global_lock);
-
- PMAP_UNLOCK(pmap);
}
+static int
+kvm_size(SYSCTL_HANDLER_ARGS)
+{
+ unsigned long ksize = vm_max_kernel_address - KERNBASE;
-/*
- * Insert the given physical page (p) at
- * the specified virtual address (v) in the
- * target physical map with the protection requested.
- *
- * If specified, the page will be wired down, meaning
- * that the related pte can not be reclaimed.
- *
- * NB: This is the only routine which MAY NOT lazy-evaluate
- * or lose information. That is, this routine must actually
- * insert this page into the given map NOW.
- */
+ return (sysctl_handle_long(oidp, &ksize, 0, req));
+}
+SYSCTL_PROC(_vm, OID_AUTO, kvm_size, CTLTYPE_LONG|CTLFLAG_RD,
+ 0, 0, kvm_size, "IU", "Size of KVM");
-int
-pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
- u_int flags, int8_t psind __unused)
+static int
+kvm_free(SYSCTL_HANDLER_ARGS)
{
- struct l2_bucket *l2b;
- int rv;
+ unsigned long kfree = vm_max_kernel_address - kernel_vm_end;
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
- rv = pmap_enter_locked(pmap, va, m, prot, flags);
- if (rv == KERN_SUCCESS) {
- /*
- * If both the l2b_occupancy and the reservation are fully
- * populated, then attempt promotion.
- */
- l2b = pmap_get_l2_bucket(pmap, va);
- if (l2b != NULL && l2b->l2b_occupancy == L2_PTE_NUM_TOTAL &&
- sp_enabled && (m->flags & PG_FICTITIOUS) == 0 &&
- vm_reserv_level_iffullpop(m) == 0)
- pmap_promote_section(pmap, va);
- }
- PMAP_UNLOCK(pmap);
- rw_wunlock(&pvh_global_lock);
- return (rv);
+ return (sysctl_handle_long(oidp, &kfree, 0, req));
}
+SYSCTL_PROC(_vm, OID_AUTO, kvm_free, CTLTYPE_LONG|CTLFLAG_RD,
+ 0, 0, kvm_free, "IU", "Amount of KVM free");
+
+/***********************************************
+ *
+ * Pmap allocation/deallocation routines.
+ *
+ ***********************************************/
/*
- * The pvh global and pmap locks must be held.
+ * Initialize the pmap for the swapper process.
*/
-static int
-pmap_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
- u_int flags)
-{
- struct l2_bucket *l2b = NULL;
- struct vm_page *om;
- struct pv_entry *pve = NULL;
- pd_entry_t *pl1pd, l1pd;
- pt_entry_t *ptep, npte, opte;
- u_int nflags;
- u_int is_exec, is_refd;
- vm_paddr_t pa;
- u_char user;
-
- PMAP_ASSERT_LOCKED(pmap);
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- if (va == vector_page) {
- pa = systempage.pv_pa;
- m = NULL;
- } else {
- if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m))
- VM_OBJECT_ASSERT_LOCKED(m->object);
- pa = VM_PAGE_TO_PHYS(m);
- }
+void
+pmap_pinit0(pmap_t pmap)
+{
+ PDEBUG(1, printf("%s: pmap = %p\n", __func__, pmap));
- pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
- if ((va < VM_MAXUSER_ADDRESS) &&
- (*pl1pd & L1_TYPE_MASK) == L1_S_PROTO) {
- (void)pmap_demote_section(pmap, va);
- }
+ PMAP_LOCK_INIT(pmap);
- user = 0;
/*
- * Make sure userland mappings get the right permissions
+ * Kernel page table directory and pmap stuff around is already
+ * initialized, we are using it right now and here. So, finish
+ * only PMAP structures initialization for process0 ...
+ *
+ * Since the L1 page table and PT2TAB is shared with the kernel pmap,
+ * which is already included in the list "allpmaps", this pmap does
+ * not need to be inserted into that list.
*/
- if (pmap != pmap_kernel() && va != vector_page)
- user = 1;
+ pmap->pm_pt1 = kern_pt1;
+ pmap->pm_pt2tab = kern_pt2tab;
+ CPU_ZERO(&pmap->pm_active);
+ PCPU_SET(curpmap, pmap);
+ TAILQ_INIT(&pmap->pm_pvchunk);
+ bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
+ CPU_SET(0, &pmap->pm_active);
+}
- nflags = 0;
+static __inline void
+pte1_copy_nosync(pt1_entry_t *spte1p, pt1_entry_t *dpte1p, vm_offset_t sva,
+ vm_offset_t eva)
+{
+ u_int idx, count;
- if (prot & VM_PROT_WRITE)
- nflags |= PVF_WRITE;
- if ((flags & PMAP_ENTER_WIRED) != 0)
- nflags |= PVF_WIRED;
+ idx = pte1_index(sva);
+ count = (pte1_index(eva) - idx + 1) * sizeof(pt1_entry_t);
+ bcopy(spte1p + idx, dpte1p + idx, count);
+}
- PDEBUG(1, printf("pmap_enter: pmap = %08x, va = %08x, m = %08x, "
- "prot = %x, flags = %x\n", (uint32_t) pmap, va, (uint32_t) m,
- prot, flags));
+static __inline void
+pt2tab_copy_nosync(pt2_entry_t *spte2p, pt2_entry_t *dpte2p, vm_offset_t sva,
+ vm_offset_t eva)
+{
+ u_int idx, count;
- if (pmap == pmap_kernel()) {
- l2b = pmap_get_l2_bucket(pmap, va);
- if (l2b == NULL)
- l2b = pmap_grow_l2_bucket(pmap, va);
- } else {
-do_l2b_alloc:
- l2b = pmap_alloc_l2_bucket(pmap, va);
- if (l2b == NULL) {
- if ((flags & PMAP_ENTER_NOSLEEP) == 0) {
- PMAP_UNLOCK(pmap);
- rw_wunlock(&pvh_global_lock);
- VM_WAIT;
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
- goto do_l2b_alloc;
- }
- return (KERN_RESOURCE_SHORTAGE);
- }
- }
+ idx = pt2tab_index(sva);
+ count = (pt2tab_index(eva) - idx + 1) * sizeof(pt2_entry_t);
+ bcopy(spte2p + idx, dpte2p + idx, count);
+}
- pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
- if ((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO)
- panic("pmap_enter: attempt to enter on 1MB page, va: %#x", va);
+/*
+ * Initialize a preallocated and zeroed pmap structure,
+ * such as one in a vmspace structure.
+ */
+int
+pmap_pinit(pmap_t pmap)
+{
+ pt1_entry_t *pte1p;
+ pt2_entry_t *pte2p;
+ vm_paddr_t pa, pt2tab_pa;
+ u_int i;
- ptep = &l2b->l2b_kva[l2pte_index(va)];
+ PDEBUG(6, printf("%s: pmap = %p, pm_pt1 = %p\n", __func__, pmap,
+ pmap->pm_pt1));
- opte = *ptep;
- npte = pa;
- is_exec = is_refd = 0;
+ /*
+ * No need to allocate L2 page table space yet but we do need
+ * a valid L1 page table and PT2TAB table.
+ *
+ * Install shared kernel mappings to these tables. It's a little
+ * tricky as some parts of KVA are reserved for vectors, devices,
+ * and whatever else. These parts are supposed to be above
+ * vm_max_kernel_address. Thus two regions should be installed:
+ *
+ * (1) <KERNBASE, kernel_vm_end),
+ * (2) <vm_max_kernel_address, 0xFFFFFFFF>.
+ *
+ * QQQ: The second region should be stable enough to be installed
+ * only once in time when the tables are allocated.
+ * QQQ: Maybe copy of both regions at once could be faster ...
+ * QQQ: Maybe the other TTBR is an option.
+ *
+ * Finally, install own PT2TAB table to these tables.
+ */
- if (opte) {
- if (l2pte_pa(opte) == pa) {
- /*
- * We're changing the attrs of an existing mapping.
- */
- if (m != NULL)
- pmap_modify_pv(m, pmap, va,
- PVF_WRITE | PVF_WIRED, nflags);
- is_exec |= PTE_BEEN_EXECD(opte);
- is_refd |= PTE_BEEN_REFD(opte);
- goto validate;
- }
- if ((om = PHYS_TO_VM_PAGE(l2pte_pa(opte)))) {
+ if (pmap->pm_pt1 == NULL) {
+ pmap->pm_pt1 = (pt1_entry_t *)kmem_alloc_contig(kernel_arena,
+ NB_IN_PT1, M_NOWAIT | M_ZERO, 0, -1UL, NB_IN_PT1, 0,
+ pt_memattr);
+ if (pmap->pm_pt1 == NULL)
+ return (0);
+ }
+ if (pmap->pm_pt2tab == NULL) {
+ /*
+ * QQQ: (1) PT2TAB must be contiguous. If PT2TAB is one page
+ * only, what should be the only size for 32 bit systems,
+ * then we could allocate it with vm_page_alloc() and all
+ * the stuff needed as other L2 page table pages.
+ * (2) Note that a process PT2TAB is special L2 page table
+ * page. Its mapping in kernel_arena is permanent and can
+ * be used no matter which process is current. Its mapping
+ * in PT2MAP can be used only for current process.
+ */
+ pmap->pm_pt2tab = (pt2_entry_t *)kmem_alloc_attr(kernel_arena,
+ NB_IN_PT2TAB, M_NOWAIT | M_ZERO, 0, -1UL, pt_memattr);
+ if (pmap->pm_pt2tab == NULL) {
/*
- * Replacing an existing mapping with a new one.
- * It is part of our managed memory so we
- * must remove it from the PV list
+ * QQQ: As struct pmap is allocated from UMA with
+ * UMA_ZONE_NOFREE flag, it's important to leave
+ * no allocation in pmap if initialization failed.
*/
- if ((pve = pmap_remove_pv(om, pmap, va))) {
- is_exec |= PTE_BEEN_EXECD(opte);
- is_refd |= PTE_BEEN_REFD(opte);
-
- if (m && ((m->oflags & VPO_UNMANAGED)))
- pmap_free_pv_entry(pmap, pve);
- }
+ kmem_free(kernel_arena, (vm_offset_t)pmap->pm_pt1,
+ NB_IN_PT1);
+ pmap->pm_pt1 = NULL;
+ return (0);
}
-
- } else {
/*
- * Keep the stats up to date
+ * QQQ: Each L2 page table page vm_page_t has pindex set to
+ * pte1 index of virtual address mapped by this page.
+ * It's not valid for non kernel PT2TABs themselves.
+ * The pindex of these pages can not be altered because
+ * of the way how they are allocated now. However, it
+ * should not be a problem.
*/
- l2b->l2b_occupancy++;
- pmap->pm_stats.resident_count++;
}
+ mtx_lock_spin(&allpmaps_lock);
/*
- * Enter on the PV list if part of our managed memory.
+ * To avoid race with pmap_kenter_pte1() and pmap_kenter_pt2tab(),
+ * kernel_vm_end_new is used here instead of kernel_vm_end.
*/
- if ((m && !(m->oflags & VPO_UNMANAGED))) {
- if ((!pve) && (pve = pmap_get_pv_entry(pmap, FALSE)) == NULL)
- panic("pmap_enter: no pv entries");
+ pte1_copy_nosync(kern_pt1, pmap->pm_pt1, KERNBASE,
+ kernel_vm_end_new - 1);
+ pte1_copy_nosync(kern_pt1, pmap->pm_pt1, vm_max_kernel_address,
+ 0xFFFFFFFF);
+ pt2tab_copy_nosync(kern_pt2tab, pmap->pm_pt2tab, KERNBASE,
+ kernel_vm_end_new - 1);
+ pt2tab_copy_nosync(kern_pt2tab, pmap->pm_pt2tab, vm_max_kernel_address,
+ 0xFFFFFFFF);
+ LIST_INSERT_HEAD(&allpmaps, pmap, pm_list);
+ mtx_unlock_spin(&allpmaps_lock);
- KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
- ("pmap_enter: managed mapping within the clean submap"));
- KASSERT(pve != NULL, ("No pv"));
- pmap_enter_pv(m, pve, pmap, va, nflags);
- }
-
-validate:
- /* Make the new PTE valid */
- npte |= L2_S_PROTO;
-#ifdef SMP
- npte |= L2_SHARED;
-#endif
- /* Set defaults first - kernel read access */
- npte |= L2_APX;
- npte |= L2_S_PROT_R;
- /* Set "referenced" flag */
- npte |= L2_S_REF;
-
- /* Now tune APs as desired */
- if (user)
- npte |= L2_S_PROT_U;
/*
- * If this is not a vector_page
- * then continue setting mapping parameters
+ * Store PT2MAP PT2 pages (a.k.a. PT2TAB) in PT2TAB itself.
+ * I.e. self reference mapping. The PT2TAB is private, however mapped
+ * into shared PT2MAP space, so the mapping should be not global.
*/
- if (m != NULL) {
- if ((m->oflags & VPO_UNMANAGED) == 0) {
- if (prot & (VM_PROT_ALL)) {
- vm_page_aflag_set(m, PGA_REFERENCED);
- } else {
- /*
- * Need to do page referenced emulation.
- */
- npte &= ~L2_S_REF;
- }
- }
-
- if (prot & VM_PROT_WRITE) {
- if ((m->oflags & VPO_UNMANAGED) == 0) {
- vm_page_aflag_set(m, PGA_WRITEABLE);
- /*
- * XXX: Skip modified bit emulation for now.
- * The emulation reveals problems
- * that result in random failures
- * during memory allocation on some
- * platforms.
- * Therefore, the page is marked RW
- * immediately.
- */
- npte &= ~(L2_APX);
- vm_page_dirty(m);
- } else
- npte &= ~(L2_APX);
- }
- if (!(prot & VM_PROT_EXECUTE))
- npte |= L2_XN;
+ pt2tab_pa = vtophys(pmap->pm_pt2tab);
+ pte2p = pmap_pt2tab_entry(pmap, (vm_offset_t)PT2MAP);
+ for (pa = pt2tab_pa, i = 0; i < NPG_IN_PT2TAB; i++, pa += PTE2_SIZE) {
+ pt2tab_store(pte2p++, PTE2_KPT_NG(pa));
+ }
- if (m->md.pv_memattr != VM_MEMATTR_UNCACHEABLE)
- npte |= pte_l2_s_cache_mode;
+ /* Insert PT2MAP PT2s into pmap PT1. */
+ pte1p = pmap_pte1(pmap, (vm_offset_t)PT2MAP);
+ for (pa = pt2tab_pa, i = 0; i < NPT2_IN_PT2TAB; i++, pa += NB_IN_PT2) {
+ pte1_store(pte1p++, PTE1_LINK(pa));
}
- CTR5(KTR_PMAP,"enter: pmap:%p va:%x prot:%x pte:%x->%x",
- pmap, va, prot, opte, npte);
/*
- * If this is just a wiring change, the two PTEs will be
- * identical, so there's no need to update the page table.
+ * Now synchronize new mapping which was made above.
*/
- if (npte != opte) {
- boolean_t is_cached = pmap_is_current(pmap);
-
- *ptep = npte;
- PTE_SYNC(ptep);
- if (is_cached) {
- /*
- * We only need to frob the cache/tlb if this pmap
- * is current
- */
- if (L1_IDX(va) != L1_IDX(vector_page) &&
- l2pte_valid(npte)) {
- /*
- * This mapping is likely to be accessed as
- * soon as we return to userland. Fix up the
- * L1 entry to avoid taking another
- * page/domain fault.
- */
- l1pd = l2b->l2b_phys |
- L1_C_DOM(pmap->pm_domain) | L1_C_PROTO;
- if (*pl1pd != l1pd) {
- *pl1pd = l1pd;
- PTE_SYNC(pl1pd);
- }
- }
- }
+ pte1_sync_range(pmap->pm_pt1, NB_IN_PT1);
+ pte2_sync_range(pmap->pm_pt2tab, NB_IN_PT2TAB);
- if (is_exec)
- cpu_tlb_flushID_SE(va);
- else if (is_refd)
- cpu_tlb_flushD_SE(va);
- cpu_cpwait();
- }
+ CPU_ZERO(&pmap->pm_active);
+ TAILQ_INIT(&pmap->pm_pvchunk);
+ bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
- if ((pmap != pmap_kernel()) && (pmap == &curproc->p_vmspace->vm_pmap))
- cpu_icache_sync_range(va, PAGE_SIZE);
- return (KERN_SUCCESS);
+ return (1);
}
-/*
- * Maps a sequence of resident pages belonging to the same object.
- * The sequence begins with the given page m_start. This page is
- * mapped at the given virtual address start. Each subsequent page is
- * mapped at a virtual address that is offset from start by the same
- * amount as the page is offset from m_start within the object. The
- * last page in the sequence is the page with the largest offset from
- * m_start that can be mapped at a virtual address less than the given
- * virtual address end. Not every virtual page between start and end
- * is mapped; only those for which a resident page exists with the
- * corresponding offset from m_start are mapped.
- */
-void
-pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
- vm_page_t m_start, vm_prot_t prot)
+#ifdef INVARIANTS
+static boolean_t
+pt2tab_user_is_empty(pt2_entry_t *tab)
{
- vm_offset_t va;
- vm_page_t m;
- vm_pindex_t diff, psize;
+ u_int i, end;
- VM_OBJECT_ASSERT_LOCKED(m_start->object);
-
- psize = atop(end - start);
- m = m_start;
- prot &= VM_PROT_READ | VM_PROT_EXECUTE;
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
- while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
- va = start + ptoa(diff);
- if ((va & L1_S_OFFSET) == 0 && L2_NEXT_BUCKET(va) <= end &&
- m->psind == 1 && sp_enabled &&
- pmap_enter_section(pmap, va, m, prot))
- m = &m[L1_S_SIZE / PAGE_SIZE - 1];
- else
- pmap_enter_locked(pmap, va, m, prot,
- PMAP_ENTER_NOSLEEP);
- m = TAILQ_NEXT(m, listq);
- }
- PMAP_UNLOCK(pmap);
- rw_wunlock(&pvh_global_lock);
+ end = pt2tab_index(VM_MAXUSER_ADDRESS);
+ for (i = 0; i < end; i++)
+ if (tab[i] != 0) return (FALSE);
+ return (TRUE);
}
-
+#endif
/*
- * this code makes some *MAJOR* assumptions:
- * 1. Current pmap & pmap exists.
- * 2. Not wired.
- * 3. Read access.
- * 4. No page table pages.
- * but is *MUCH* faster than pmap_enter...
+ * Release any resources held by the given physical map.
+ * Called when a pmap initialized by pmap_pinit is being released.
+ * Should only be called if the map contains no valid mappings.
*/
-
void
-pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
+pmap_release(pmap_t pmap)
{
-
- prot &= VM_PROT_READ | VM_PROT_EXECUTE;
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
- pmap_enter_locked(pmap, va, m, prot, PMAP_ENTER_NOSLEEP);
- PMAP_UNLOCK(pmap);
- rw_wunlock(&pvh_global_lock);
+#ifdef INVARIANTS
+ vm_offset_t start, end;
+#endif
+ KASSERT(pmap->pm_stats.resident_count == 0,
+ ("%s: pmap resident count %ld != 0", __func__,
+ pmap->pm_stats.resident_count));
+ KASSERT(pt2tab_user_is_empty(pmap->pm_pt2tab),
+ ("%s: has allocated user PT2(s)", __func__));
+ KASSERT(CPU_EMPTY(&pmap->pm_active),
+ ("%s: pmap %p is active on some CPU(s)", __func__, pmap));
+
+ mtx_lock_spin(&allpmaps_lock);
+ LIST_REMOVE(pmap, pm_list);
+ mtx_unlock_spin(&allpmaps_lock);
+
+#ifdef INVARIANTS
+ start = pte1_index(KERNBASE) * sizeof(pt1_entry_t);
+ end = (pte1_index(0xFFFFFFFF) + 1) * sizeof(pt1_entry_t);
+ bzero((char *)pmap->pm_pt1 + start, end - start);
+
+ start = pt2tab_index(KERNBASE) * sizeof(pt2_entry_t);
+ end = (pt2tab_index(0xFFFFFFFF) + 1) * sizeof(pt2_entry_t);
+ bzero((char *)pmap->pm_pt2tab + start, end - start);
+#endif
+ /*
+ * We are leaving PT1 and PT2TAB allocated on released pmap,
+ * so hopefully UMA vmspace_zone will always be inited with
+ * UMA_ZONE_NOFREE flag.
+ */
}
+/*********************************************************
+ *
+ * L2 table pages and their pages management routines.
+ *
+ *********************************************************/
+
/*
- * Clear the wired attribute from the mappings for the specified range of
- * addresses in the given pmap. Every valid mapping within that range
- * must have the wired attribute set. In contrast, invalid mappings
- * cannot have the wired attribute set, so they are ignored.
+ * Virtual interface for L2 page table wire counting.
+ *
+ * Each L2 page table in a page has own counter which counts a number of
+ * valid mappings in a table. Global page counter counts mappings in all
+ * tables in a page plus a single itself mapping in PT2TAB.
*
- * XXX Wired mappings of unmanaged pages cannot be counted by this pmap
- * implementation.
+ * During a promotion we leave the associated L2 page table counter
+ * untouched, so the table (strictly speaking a page which holds it)
+ * is never freed if promoted.
+ *
+ * If a page m->wire_count == 1 then no valid mappings exist in any L2 page
+ * table in the page and the page itself is only mapped in PT2TAB.
*/
-void
-pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
-{
- struct l2_bucket *l2b;
- struct md_page *pvh;
- pd_entry_t l1pd;
- pt_entry_t *ptep, pte;
- pv_entry_t pv;
- vm_offset_t next_bucket;
- vm_paddr_t pa;
- vm_page_t m;
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
- while (sva < eva) {
- next_bucket = L2_NEXT_BUCKET(sva);
- l1pd = pmap->pm_l1->l1_kva[L1_IDX(sva)];
- if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
- pa = l1pd & L1_S_FRAME;
- m = PHYS_TO_VM_PAGE(pa);
- KASSERT(m != NULL && (m->oflags & VPO_UNMANAGED) == 0,
- ("pmap_unwire: unmanaged 1mpage %p", m));
- pvh = pa_to_pvh(pa);
- pv = pmap_find_pv(pvh, pmap, trunc_1mpage(sva));
- if ((pv->pv_flags & PVF_WIRED) == 0)
- panic("pmap_unwire: pv %p isn't wired", pv);
+static __inline void
+pt2_wirecount_init(vm_page_t m)
+{
+ u_int i;
- /*
- * Are we unwiring the entire large page? If not,
- * demote the mapping and fall through.
- */
- if (sva + L1_S_SIZE == next_bucket &&
- eva >= next_bucket) {
- pv->pv_flags &= ~PVF_WIRED;
- pmap->pm_stats.wired_count -= L2_PTE_NUM_TOTAL;
- sva = next_bucket;
- continue;
- } else if (!pmap_demote_section(pmap, sva))
- panic("pmap_unwire: demotion failed");
- }
- if (next_bucket > eva)
- next_bucket = eva;
- l2b = pmap_get_l2_bucket(pmap, sva);
- if (l2b == NULL) {
- sva = next_bucket;
- continue;
- }
- for (ptep = &l2b->l2b_kva[l2pte_index(sva)]; sva < next_bucket;
- sva += PAGE_SIZE, ptep++) {
- if ((pte = *ptep) == 0 ||
- (m = PHYS_TO_VM_PAGE(l2pte_pa(pte))) == NULL ||
- (m->oflags & VPO_UNMANAGED) != 0)
- continue;
- pv = pmap_find_pv(&m->md, pmap, sva);
- if ((pv->pv_flags & PVF_WIRED) == 0)
- panic("pmap_unwire: pv %p isn't wired", pv);
- pv->pv_flags &= ~PVF_WIRED;
- pmap->pm_stats.wired_count--;
- }
- }
- rw_wunlock(&pvh_global_lock);
- PMAP_UNLOCK(pmap);
+ /*
+ * Note: A page m is allocated with VM_ALLOC_WIRED flag and
+ * m->wire_count should be already set correctly.
+ * So, there is no need to set it again herein.
+ */
+ for (i = 0; i < NPT2_IN_PG; i++)
+ m->md.pt2_wirecount[i] = 0;
}
-
-/*
- * Copy the range specified by src_addr/len
- * from the source map to the range dst_addr/len
- * in the destination map.
- *
- * This routine is only advisory and need not do anything.
- */
-void
-pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr,
- vm_size_t len, vm_offset_t src_addr)
+static __inline void
+pt2_wirecount_inc(vm_page_t m, uint32_t pte1_idx)
{
-}
+ /*
+ * Note: A just modificated pte2 (i.e. already allocated)
+ * is acquiring one extra reference which must be
+ * explicitly cleared. It influences the KASSERTs herein.
+ * All L2 page tables in a page always belong to the same
+ * pmap, so we allow only one extra reference for the page.
+ */
+ KASSERT(m->md.pt2_wirecount[pte1_idx & PT2PG_MASK] < (NPTE2_IN_PT2 + 1),
+ ("%s: PT2 is overflowing ...", __func__));
+ KASSERT(m->wire_count <= (NPTE2_IN_PG + 1),
+ ("%s: PT2PG is overflowing ...", __func__));
+
+ m->wire_count++;
+ m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]++;
+}
-/*
- * Routine: pmap_extract
- * Function:
- * Extract the physical page address associated
- * with the given map/virtual_address pair.
- */
-vm_paddr_t
-pmap_extract(pmap_t pmap, vm_offset_t va)
+static __inline void
+pt2_wirecount_dec(vm_page_t m, uint32_t pte1_idx)
{
- vm_paddr_t pa;
- PMAP_LOCK(pmap);
- pa = pmap_extract_locked(pmap, va);
- PMAP_UNLOCK(pmap);
- return (pa);
+ KASSERT(m->md.pt2_wirecount[pte1_idx & PT2PG_MASK] != 0,
+ ("%s: PT2 is underflowing ...", __func__));
+ KASSERT(m->wire_count > 1,
+ ("%s: PT2PG is underflowing ...", __func__));
+
+ m->wire_count--;
+ m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]--;
}
-static vm_paddr_t
-pmap_extract_locked(pmap_t pmap, vm_offset_t va)
+static __inline void
+pt2_wirecount_set(vm_page_t m, uint32_t pte1_idx, uint16_t count)
{
- struct l2_dtable *l2;
- pd_entry_t l1pd;
- pt_entry_t *ptep, pte;
- vm_paddr_t pa;
- u_int l1idx;
-
- if (kernel_vm_end != 0 && pmap != kernel_pmap)
- PMAP_ASSERT_LOCKED(pmap);
- l1idx = L1_IDX(va);
- l1pd = pmap->pm_l1->l1_kva[l1idx];
- if (l1pte_section_p(l1pd)) {
- /* XXX: what to do about the bits > 32 ? */
- if (l1pd & L1_S_SUPERSEC)
- pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET);
- else
- pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET);
- } else {
- /*
- * Note that we can't rely on the validity of the L1
- * descriptor as an indication that a mapping exists.
- * We have to look it up in the L2 dtable.
- */
- l2 = pmap->pm_l2[L2_IDX(l1idx)];
- if (l2 == NULL ||
- (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL)
- return (0);
- pte = ptep[l2pte_index(va)];
- if (pte == 0)
- return (0);
- if ((pte & L2_TYPE_MASK) == L2_TYPE_L)
- pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET);
- else
- pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET);
- }
- return (pa);
+
+ KASSERT(count <= NPTE2_IN_PT2,
+ ("%s: invalid count %u", __func__, count));
+ KASSERT(m->wire_count > m->md.pt2_wirecount[pte1_idx & PT2PG_MASK],
+ ("%s: PT2PG corrupting (%u, %u) ...", __func__, m->wire_count,
+ m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]));
+
+ m->wire_count -= m->md.pt2_wirecount[pte1_idx & PT2PG_MASK];
+ m->wire_count += count;
+ m->md.pt2_wirecount[pte1_idx & PT2PG_MASK] = count;
+
+ KASSERT(m->wire_count <= (NPTE2_IN_PG + 1),
+ ("%s: PT2PG is overflowed (%u) ...", __func__, m->wire_count));
}
-/*
- * Atomically extract and hold the physical page with the given
- * pmap and virtual address pair if that mapping permits the given
- * protection.
- *
- */
-vm_page_t
-pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
+static __inline uint32_t
+pt2_wirecount_get(vm_page_t m, uint32_t pte1_idx)
{
- struct l2_dtable *l2;
- pd_entry_t l1pd;
- pt_entry_t *ptep, pte;
- vm_paddr_t pa, paddr;
- vm_page_t m = NULL;
- u_int l1idx;
- l1idx = L1_IDX(va);
- paddr = 0;
- PMAP_LOCK(pmap);
-retry:
- l1pd = pmap->pm_l1->l1_kva[l1idx];
- if (l1pte_section_p(l1pd)) {
- /* XXX: what to do about the bits > 32 ? */
- if (l1pd & L1_S_SUPERSEC)
- pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET);
- else
- pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET);
- if (vm_page_pa_tryrelock(pmap, pa & PG_FRAME, &paddr))
- goto retry;
- if (L1_S_WRITABLE(l1pd) || (prot & VM_PROT_WRITE) == 0) {
- m = PHYS_TO_VM_PAGE(pa);
- vm_page_hold(m);
- }
- } else {
- /*
- * Note that we can't rely on the validity of the L1
- * descriptor as an indication that a mapping exists.
- * We have to look it up in the L2 dtable.
- */
- l2 = pmap->pm_l2[L2_IDX(l1idx)];
+ return (m->md.pt2_wirecount[pte1_idx & PT2PG_MASK]);
+}
- if (l2 == NULL ||
- (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) {
- PMAP_UNLOCK(pmap);
- return (NULL);
- }
+static __inline boolean_t
+pt2_is_empty(vm_page_t m, vm_offset_t va)
+{
- ptep = &ptep[l2pte_index(va)];
- pte = *ptep;
+ return (m->md.pt2_wirecount[pte1_index(va) & PT2PG_MASK] == 0);
+}
- if (pte == 0) {
- PMAP_UNLOCK(pmap);
- return (NULL);
- } else if ((prot & VM_PROT_WRITE) && (pte & L2_APX)) {
- PMAP_UNLOCK(pmap);
- return (NULL);
- } else {
- if ((pte & L2_TYPE_MASK) == L2_TYPE_L)
- panic("extract and hold section mapping");
- else
- pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET);
- if (vm_page_pa_tryrelock(pmap, pa & PG_FRAME, &paddr))
- goto retry;
- m = PHYS_TO_VM_PAGE(pa);
- vm_page_hold(m);
- }
- }
+static __inline boolean_t
+pt2_is_full(vm_page_t m, vm_offset_t va)
+{
- PMAP_UNLOCK(pmap);
- PA_UNLOCK_COND(paddr);
- return (m);
+ return (m->md.pt2_wirecount[pte1_index(va) & PT2PG_MASK] ==
+ NPTE2_IN_PT2);
}
-vm_paddr_t
-pmap_dump_kextract(vm_offset_t va, pt2_entry_t *pte2p)
+static __inline boolean_t
+pt2pg_is_empty(vm_page_t m)
{
- struct l2_dtable *l2;
- pd_entry_t l1pd;
- pt_entry_t *ptep, pte;
- vm_paddr_t pa;
- u_int l1idx;
- l1idx = L1_IDX(va);
- l1pd = kernel_pmap->pm_l1->l1_kva[l1idx];
- if (l1pte_section_p(l1pd)) {
- if (l1pd & L1_S_SUPERSEC)
- pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET);
- else
- pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET);
- pte = L2_S_PROTO | pa |
- L2_S_PROT(PTE_KERNEL, VM_PROT_READ | VM_PROT_WRITE);
- } else {
- l2 = kernel_pmap->pm_l2[L2_IDX(l1idx)];
- if (l2 == NULL ||
- (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) {
- pte = 0;
- pa = 0;
- goto out;
- }
- pte = ptep[l2pte_index(va)];
- if (pte == 0) {
- pa = 0;
- goto out;
- }
- if ((pte & L2_TYPE_MASK) == L2_TYPE_L)
- pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET);
- else
- pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET);
- }
-out:
- if (pte2p != NULL)
- *pte2p = pte;
- return (pa);
+ return (m->wire_count == 1);
}
/*
- * Initialize a preallocated and zeroed pmap structure,
- * such as one in a vmspace structure.
+ * This routine is called if the L2 page table
+ * is not mapped correctly.
*/
-
-int
-pmap_pinit(pmap_t pmap)
+static vm_page_t
+_pmap_allocpte2(pmap_t pmap, vm_offset_t va, u_int flags)
{
- PDEBUG(1, printf("pmap_pinit: pmap = %08x\n", (uint32_t) pmap));
+ uint32_t pte1_idx;
+ pt1_entry_t *pte1p;
+ pt2_entry_t pte2;
+ vm_page_t m;
+ vm_paddr_t pt2pg_pa, pt2_pa;
- pmap_alloc_l1(pmap);
- bzero(pmap->pm_l2, sizeof(pmap->pm_l2));
+ pte1_idx = pte1_index(va);
+ pte1p = pmap->pm_pt1 + pte1_idx;
- CPU_ZERO(&pmap->pm_active);
+ KASSERT(pte1_load(pte1p) == 0,
+ ("%s: pm_pt1[%#x] is not zero: %#x", __func__, pte1_idx,
+ pte1_load(pte1p)));
- TAILQ_INIT(&pmap->pm_pvchunk);
- bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
- pmap->pm_stats.resident_count = 1;
- if (vector_page < KERNBASE) {
- pmap_enter(pmap, vector_page,
- PHYS_TO_VM_PAGE(systempage.pv_pa), VM_PROT_READ,
- PMAP_ENTER_WIRED, 0);
+ pte2 = pt2tab_load(pmap_pt2tab_entry(pmap, va));
+ if (!pte2_is_valid(pte2)) {
+ /*
+ * Install new PT2s page into pmap PT2TAB.
+ */
+ m = vm_page_alloc(NULL, pte1_idx & ~PT2PG_MASK,
+ VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
+ if (m == NULL) {
+ if ((flags & PMAP_ENTER_NOSLEEP) == 0) {
+ PMAP_UNLOCK(pmap);
+ rw_wunlock(&pvh_global_lock);
+ VM_WAIT;
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ }
+
+ /*
+ * Indicate the need to retry. While waiting,
+ * the L2 page table page may have been allocated.
+ */
+ return (NULL);
+ }
+ pmap->pm_stats.resident_count++;
+ pt2pg_pa = pmap_pt2pg_init(pmap, va, m);
+ } else {
+ pt2pg_pa = pte2_pa(pte2);
+ m = PHYS_TO_VM_PAGE(pt2pg_pa);
}
- return (1);
-}
+ pt2_wirecount_inc(m, pte1_idx);
+ pt2_pa = page_pt2pa(pt2pg_pa, pte1_idx);
+ pte1_store(pte1p, PTE1_LINK(pt2_pa));
-/***************************************************
- * Superpage management routines.
- ***************************************************/
+ return (m);
+}
-static PMAP_INLINE struct pv_entry *
-pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va)
+static vm_page_t
+pmap_allocpte2(pmap_t pmap, vm_offset_t va, u_int flags)
{
- pv_entry_t pv;
+ u_int pte1_idx;
+ pt1_entry_t *pte1p, pte1;
+ vm_page_t m;
- rw_assert(&pvh_global_lock, RA_WLOCKED);
+ pte1_idx = pte1_index(va);
+retry:
+ pte1p = pmap->pm_pt1 + pte1_idx;
+ pte1 = pte1_load(pte1p);
- pv = pmap_find_pv(pvh, pmap, va);
- if (pv != NULL)
- TAILQ_REMOVE(&pvh->pv_list, pv, pv_list);
+ /*
+ * This supports switching from a 1MB page to a
+ * normal 4K page.
+ */
+ if (pte1_is_section(pte1)) {
+ (void)pmap_demote_pte1(pmap, pte1p, va);
+ /*
+ * Reload pte1 after demotion.
+ *
+ * Note: Demotion can even fail as either PT2 is not find for
+ * the virtual address or PT2PG can not be allocated.
+ */
+ pte1 = pte1_load(pte1p);
+ }
- return (pv);
+ /*
+ * If the L2 page table page is mapped, we just increment the
+ * hold count, and activate it.
+ */
+ if (pte1_is_link(pte1)) {
+ m = PHYS_TO_VM_PAGE(pte1_link_pa(pte1));
+ pt2_wirecount_inc(m, pte1_idx);
+ } else {
+ /*
+ * Here if the PT2 isn't mapped, or if it has
+ * been deallocated.
+ */
+ m = _pmap_allocpte2(pmap, va, flags);
+ if (m == NULL && (flags & PMAP_ENTER_NOSLEEP) == 0)
+ goto retry;
+ }
+
+ return (m);
}
-static void
-pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va)
+static __inline void
+pmap_free_zero_pages(struct spglist *free)
{
- pv_entry_t pv;
+ vm_page_t m;
- pv = pmap_pvh_remove(pvh, pmap, va);
- KASSERT(pv != NULL, ("pmap_pvh_free: pv not found"));
- pmap_free_pv_entry(pmap, pv);
+ while ((m = SLIST_FIRST(free)) != NULL) {
+ SLIST_REMOVE_HEAD(free, plinks.s.ss);
+ /* Preserve the page's PG_ZERO setting. */
+ vm_page_free_toq(m);
+ }
}
-static boolean_t
-pmap_pv_insert_section(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
+/*
+ * Schedule the specified unused L2 page table page to be freed. Specifically,
+ * add the page to the specified list of pages that will be released to the
+ * physical memory manager after the TLB has been updated.
+ */
+static __inline void
+pmap_add_delayed_free_list(vm_page_t m, struct spglist *free)
{
- struct md_page *pvh;
- pv_entry_t pv;
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- if (pv_entry_count < pv_entry_high_water &&
- (pv = pmap_get_pv_entry(pmap, TRUE)) != NULL) {
- pv->pv_va = va;
- pvh = pa_to_pvh(pa);
- TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list);
- return (TRUE);
- } else
- return (FALSE);
+ /*
+ * Put page on a list so that it is released after
+ * *ALL* TLB shootdown is done
+ */
+#ifdef PMAP_DEBUG
+ pmap_zero_page_check(m);
+#endif
+ m->flags |= PG_ZERO;
+ SLIST_INSERT_HEAD(free, m, plinks.s.ss);
}
/*
- * Create the pv entries for each of the pages within a superpage.
+ * Unwire L2 page tables page.
*/
static void
-pmap_pv_demote_section(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
+pmap_unwire_pt2pg(pmap_t pmap, vm_offset_t va, vm_page_t m)
{
- struct md_page *pvh;
- pv_entry_t pve, pv;
- vm_offset_t va_last;
- vm_page_t m;
+ pt1_entry_t *pte1p, opte1 __unused;
+ pt2_entry_t *pte2p;
+ uint32_t i;
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- KASSERT((pa & L1_S_OFFSET) == 0,
- ("pmap_pv_demote_section: pa is not 1mpage aligned"));
+ KASSERT(pt2pg_is_empty(m),
+ ("%s: pmap %p PT2PG %p wired", __func__, pmap, m));
/*
- * Transfer the 1mpage's pv entry for this mapping to the first
- * page's pv list.
+ * Unmap all L2 page tables in the page from L1 page table.
+ *
+ * QQQ: Individual L2 page tables (except the last one) can be unmapped
+ * earlier. However, we are doing that this way.
*/
- pvh = pa_to_pvh(pa);
- va = trunc_1mpage(va);
- pv = pmap_pvh_remove(pvh, pmap, va);
- KASSERT(pv != NULL, ("pmap_pv_demote_section: pv not found"));
- m = PHYS_TO_VM_PAGE(pa);
- TAILQ_INSERT_HEAD(&m->md.pv_list, pv, pv_list);
- /* Instantiate the remaining pv entries. */
- va_last = L2_NEXT_BUCKET(va) - PAGE_SIZE;
- do {
- m++;
- KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("pmap_pv_demote_section: page %p is not managed", m));
- va += PAGE_SIZE;
- pve = pmap_get_pv_entry(pmap, FALSE);
- pmap_enter_pv(m, pve, pmap, va, pv->pv_flags);
- } while (va < va_last);
-}
+ KASSERT(m->pindex == (pte1_index(va) & ~PT2PG_MASK),
+ ("%s: pmap %p va %#x PT2PG %p bad index", __func__, pmap, va, m));
+ pte1p = pmap->pm_pt1 + m->pindex;
+ for (i = 0; i < NPT2_IN_PG; i++, pte1p++) {
+ KASSERT(m->md.pt2_wirecount[i] == 0,
+ ("%s: pmap %p PT2 %u (PG %p) wired", __func__, pmap, i, m));
+ opte1 = pte1_load(pte1p);
+ if (pte1_is_link(opte1)) {
+ pte1_clear(pte1p);
+ /*
+ * Flush intermediate TLB cache.
+ */
+ pmap_tlb_flush(pmap, (m->pindex + i) << PTE1_SHIFT);
+ }
+#ifdef INVARIANTS
+ else
+ KASSERT((opte1 == 0) || pte1_is_section(opte1),
+ ("%s: pmap %p va %#x bad pte1 %x at %u", __func__,
+ pmap, va, opte1, i));
+#endif
+ }
-static void
-pmap_pv_promote_section(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
-{
- struct md_page *pvh;
- pv_entry_t pv;
- vm_offset_t va_last;
- vm_page_t m;
+ /*
+ * Unmap the page from PT2TAB.
+ */
+ pte2p = pmap_pt2tab_entry(pmap, va);
+ (void)pt2tab_load_clear(pte2p);
+ pmap_tlb_flush(pmap, pt2map_pt2pg(va));
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- KASSERT((pa & L1_S_OFFSET) == 0,
- ("pmap_pv_promote_section: pa is not 1mpage aligned"));
+ m->wire_count = 0;
+ pmap->pm_stats.resident_count--;
/*
- * Transfer the first page's pv entry for this mapping to the
- * 1mpage's pv list. Aside from avoiding the cost of a call
- * to get_pv_entry(), a transfer avoids the possibility that
- * get_pv_entry() calls pmap_pv_reclaim() and that pmap_pv_reclaim()
- * removes one of the mappings that is being promoted.
+ * This is a release store so that the ordinary store unmapping
+ * the L2 page table page is globally performed before TLB shoot-
+ * down is begun.
*/
- m = PHYS_TO_VM_PAGE(pa);
- va = trunc_1mpage(va);
- pv = pmap_pvh_remove(&m->md, pmap, va);
- KASSERT(pv != NULL, ("pmap_pv_promote_section: pv not found"));
- pvh = pa_to_pvh(pa);
- TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list);
- /* Free the remaining pv entries in the newly mapped section pages */
- va_last = L2_NEXT_BUCKET(va) - PAGE_SIZE;
- do {
- m++;
- va += PAGE_SIZE;
- /*
- * Don't care the flags, first pv contains sufficient
- * information for all of the pages so nothing is really lost.
- */
- pmap_pvh_free(&m->md, pmap, va);
- } while (va < va_last);
+ atomic_subtract_rel_int(&vm_cnt.v_wire_count, 1);
}
/*
- * Tries to create a 1MB page mapping. Returns TRUE if successful and
- * FALSE otherwise. Fails if (1) page is unmanageg, kernel pmap or vectors
- * page, (2) a mapping already exists at the specified virtual address, or
- * (3) a pv entry cannot be allocated without reclaiming another pv entry.
+ * Decrements a L2 page table page's wire count, which is used to record the
+ * number of valid page table entries within the page. If the wire count
+ * drops to zero, then the page table page is unmapped. Returns TRUE if the
+ * page table page was unmapped and FALSE otherwise.
*/
-static boolean_t
-pmap_enter_section(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
+static __inline boolean_t
+pmap_unwire_pt2(pmap_t pmap, vm_offset_t va, vm_page_t m, struct spglist *free)
{
- pd_entry_t *pl1pd;
- vm_offset_t pa;
- struct l2_bucket *l2b;
-
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- PMAP_ASSERT_LOCKED(pmap);
-
- /* Skip kernel, vectors page and unmanaged mappings */
- if ((pmap == pmap_kernel()) || (L1_IDX(va) == L1_IDX(vector_page)) ||
- ((m->oflags & VPO_UNMANAGED) != 0)) {
- CTR2(KTR_PMAP, "pmap_enter_section: failure for va %#lx"
- " in pmap %p", va, pmap);
- return (FALSE);
- }
- /*
- * Check whether this is a valid section superpage entry or
- * there is a l2_bucket associated with that L1 page directory.
- */
- va = trunc_1mpage(va);
- pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
- l2b = pmap_get_l2_bucket(pmap, va);
- if ((*pl1pd & L1_S_PROTO) || (l2b != NULL)) {
- CTR2(KTR_PMAP, "pmap_enter_section: failure for va %#lx"
- " in pmap %p", va, pmap);
- return (FALSE);
- }
- pa = VM_PAGE_TO_PHYS(m);
- /*
- * Abort this mapping if its PV entry could not be created.
- */
- if (!pmap_pv_insert_section(pmap, va, VM_PAGE_TO_PHYS(m))) {
- CTR2(KTR_PMAP, "pmap_enter_section: failure for va %#lx"
- " in pmap %p", va, pmap);
+ pt2_wirecount_dec(m, pte1_index(va));
+ if (pt2pg_is_empty(m)) {
+ /*
+ * QQQ: Wire count is zero, so whole page should be zero and
+ * we can set PG_ZERO flag to it.
+ * Note that when promotion is enabled, it takes some
+ * more efforts. See pmap_unwire_pt2_all() below.
+ */
+ pmap_unwire_pt2pg(pmap, va, m);
+ pmap_add_delayed_free_list(m, free);
+ return (TRUE);
+ } else
return (FALSE);
- }
- /*
- * Increment counters.
- */
- pmap->pm_stats.resident_count += L2_PTE_NUM_TOTAL;
- /*
- * Despite permissions, mark the superpage read-only.
- */
- prot &= ~VM_PROT_WRITE;
- /*
- * Map the superpage.
- */
- pmap_map_section(pmap, va, pa, prot, FALSE);
-
- pmap_section_mappings++;
- CTR2(KTR_PMAP, "pmap_enter_section: success for va %#lx"
- " in pmap %p", va, pmap);
- return (TRUE);
}
/*
- * pmap_remove_section: do the things to unmap a superpage in a process
+ * Drop a L2 page table page's wire count at once, which is used to record
+ * the number of valid L2 page table entries within the page. If the wire
+ * count drops to zero, then the L2 page table page is unmapped.
*/
-static void
-pmap_remove_section(pmap_t pmap, vm_offset_t sva)
+static __inline void
+pmap_unwire_pt2_all(pmap_t pmap, vm_offset_t va, vm_page_t m,
+ struct spglist *free)
{
- struct md_page *pvh;
- struct l2_bucket *l2b;
- pd_entry_t *pl1pd, l1pd;
- vm_offset_t eva, va;
- vm_page_t m;
-
- PMAP_ASSERT_LOCKED(pmap);
- if ((pmap == pmap_kernel()) || (L1_IDX(sva) == L1_IDX(vector_page)))
- return;
+ u_int pte1_idx = pte1_index(va);
- KASSERT((sva & L1_S_OFFSET) == 0,
- ("pmap_remove_section: sva is not 1mpage aligned"));
+ KASSERT(m->pindex == (pte1_idx & ~PT2PG_MASK),
+ ("%s: PT2 page's pindex is wrong", __func__));
+ KASSERT(m->wire_count > pt2_wirecount_get(m, pte1_idx),
+ ("%s: bad pt2 wire count %u > %u", __func__, m->wire_count,
+ pt2_wirecount_get(m, pte1_idx)));
- pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(sva)];
- l1pd = *pl1pd;
-
- m = PHYS_TO_VM_PAGE(l1pd & L1_S_FRAME);
- KASSERT((m != NULL && ((m->oflags & VPO_UNMANAGED) == 0)),
- ("pmap_remove_section: no corresponding vm_page or "
- "page unmanaged"));
+ /*
+ * It's possible that the L2 page table was never used.
+ * It happened in case that a section was created without promotion.
+ */
+ if (pt2_is_full(m, va)) {
+ pt2_wirecount_set(m, pte1_idx, 0);
- pmap->pm_stats.resident_count -= L2_PTE_NUM_TOTAL;
- pvh = pa_to_pvh(l1pd & L1_S_FRAME);
- pmap_pvh_free(pvh, pmap, sva);
- eva = L2_NEXT_BUCKET(sva);
- for (va = sva, m = PHYS_TO_VM_PAGE(l1pd & L1_S_FRAME);
- va < eva; va += PAGE_SIZE, m++) {
/*
- * Mark base pages referenced but skip marking them dirty.
- * If the superpage is writeable, hence all base pages were
- * already marked as dirty in pmap_fault_fixup() before
- * promotion. Reference bit however, might not have been set
- * for each base page when the superpage was created at once,
- * not as a result of promotion.
+ * QQQ: We clear L2 page table now, so when L2 page table page
+ * is going to be freed, we can set it PG_ZERO flag ...
+ * This function is called only on section mappings, so
+ * hopefully it's not to big overload.
+ *
+ * XXX: If pmap is current, existing PT2MAP mapping could be
+ * used for zeroing.
*/
- if (L1_S_REFERENCED(l1pd))
- vm_page_aflag_set(m, PGA_REFERENCED);
- if (TAILQ_EMPTY(&m->md.pv_list) &&
- TAILQ_EMPTY(&pvh->pv_list))
- vm_page_aflag_clear(m, PGA_WRITEABLE);
- }
-
- l2b = pmap_get_l2_bucket(pmap, sva);
- if (l2b != NULL) {
- KASSERT(l2b->l2b_occupancy == L2_PTE_NUM_TOTAL,
- ("pmap_remove_section: l2_bucket occupancy error"));
- pmap_free_l2_bucket(pmap, l2b, L2_PTE_NUM_TOTAL);
+ pmap_zero_page_area(m, page_pt2off(pte1_idx), NB_IN_PT2);
}
- /* Now invalidate L1 slot */
- *pl1pd = 0;
- PTE_SYNC(pl1pd);
- if (L1_S_EXECUTABLE(l1pd))
- cpu_tlb_flushID_SE(sva);
+#ifdef INVARIANTS
else
- cpu_tlb_flushD_SE(sva);
- cpu_cpwait();
+ KASSERT(pt2_is_empty(m, va), ("%s: PT2 is not empty (%u)",
+ __func__, pt2_wirecount_get(m, pte1_idx)));
+#endif
+ if (pt2pg_is_empty(m)) {
+ pmap_unwire_pt2pg(pmap, va, m);
+ pmap_add_delayed_free_list(m, free);
+ }
}
/*
- * Tries to promote the 256, contiguous 4KB page mappings that are
- * within a single l2_bucket to a single 1MB section mapping.
- * For promotion to occur, two conditions must be met: (1) the 4KB page
- * mappings must map aligned, contiguous physical memory and (2) the 4KB page
- * mappings must have identical characteristics.
+ * After removing a L2 page table entry, this routine is used to
+ * conditionally free the page, and manage the hold/wire counts.
*/
-static void
-pmap_promote_section(pmap_t pmap, vm_offset_t va)
+static boolean_t
+pmap_unuse_pt2(pmap_t pmap, vm_offset_t va, struct spglist *free)
{
- pt_entry_t *firstptep, firstpte, oldpte, pa, *pte;
- vm_page_t m, oldm;
- vm_offset_t first_va, old_va;
- struct l2_bucket *l2b = NULL;
- vm_prot_t prot;
- struct pv_entry *pve, *first_pve;
+ pt1_entry_t pte1;
+ vm_page_t mpte;
- PMAP_ASSERT_LOCKED(pmap);
+ if (va >= VM_MAXUSER_ADDRESS)
+ return (FALSE);
+ pte1 = pte1_load(pmap_pte1(pmap, va));
+ mpte = PHYS_TO_VM_PAGE(pte1_link_pa(pte1));
+ return (pmap_unwire_pt2(pmap, va, mpte, free));
+}
- prot = VM_PROT_ALL;
- /*
- * Skip promoting kernel pages. This is justified by following:
- * 1. Kernel is already mapped using section mappings in each pmap
- * 2. Managed mappings within the kernel are not to be promoted anyway
- */
- if (pmap == pmap_kernel()) {
- pmap_section_p_failures++;
- CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x"
- " in pmap %p", va, pmap);
- return;
- }
- /* Do not attemp to promote vectors pages */
- if (L1_IDX(va) == L1_IDX(vector_page)) {
- pmap_section_p_failures++;
- CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x"
- " in pmap %p", va, pmap);
- return;
- }
- /*
- * Examine the first PTE in the specified l2_bucket. Abort if this PTE
- * is either invalid, unused, or does not map the first 4KB physical
- * page within 1MB page.
- */
- first_va = trunc_1mpage(va);
- l2b = pmap_get_l2_bucket(pmap, first_va);
- KASSERT(l2b != NULL, ("pmap_promote_section: trying to promote "
- "not existing l2 bucket"));
- firstptep = &l2b->l2b_kva[0];
-
- firstpte = *firstptep;
- if ((l2pte_pa(firstpte) & L1_S_OFFSET) != 0) {
- pmap_section_p_failures++;
- CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x"
- " in pmap %p", va, pmap);
- return;
- }
+/*************************************
+ *
+ * Page management routines.
+ *
+ *************************************/
- if ((firstpte & (L2_S_PROTO | L2_S_REF)) != (L2_S_PROTO | L2_S_REF)) {
- pmap_section_p_failures++;
- CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x"
- " in pmap %p", va, pmap);
- return;
- }
- /*
- * ARM uses pv_entry to mark particular mapping WIRED so don't promote
- * unmanaged pages since it is impossible to determine, whether the
- * page is wired or not if there is no corresponding pv_entry.
- */
- m = PHYS_TO_VM_PAGE(l2pte_pa(firstpte));
- if (m && ((m->oflags & VPO_UNMANAGED) != 0)) {
- pmap_section_p_failures++;
- CTR2(KTR_PMAP, "pmap_promote_section: failure for va %#x"
- " in pmap %p", va, pmap);
- return;
- }
- first_pve = pmap_find_pv(&m->md, pmap, first_va);
- /*
- * PTE is modified only on write due to modified bit
- * emulation. If the entry is referenced and writable
- * then it is modified and we don't clear write enable.
- * Otherwise, writing is disabled in PTE anyway and
- * we just configure protections for the section mapping
- * that is going to be created.
- */
- if ((first_pve->pv_flags & PVF_WRITE) != 0) {
- if (!L2_S_WRITABLE(firstpte)) {
- first_pve->pv_flags &= ~PVF_WRITE;
- prot &= ~VM_PROT_WRITE;
- }
- } else
- prot &= ~VM_PROT_WRITE;
+CTASSERT(sizeof(struct pv_chunk) == PAGE_SIZE);
+CTASSERT(_NPCM == 11);
+CTASSERT(_NPCPV == 336);
- if (!L2_S_EXECUTABLE(firstpte))
- prot &= ~VM_PROT_EXECUTE;
+static __inline struct pv_chunk *
+pv_to_chunk(pv_entry_t pv)
+{
- /*
- * Examine each of the other PTEs in the specified l2_bucket.
- * Abort if this PTE maps an unexpected 4KB physical page or
- * does not have identical characteristics to the first PTE.
- */
- pa = l2pte_pa(firstpte) + ((L2_PTE_NUM_TOTAL - 1) * PAGE_SIZE);
- old_va = L2_NEXT_BUCKET(first_va) - PAGE_SIZE;
-
- for (pte = (firstptep + L2_PTE_NUM_TOTAL - 1); pte > firstptep; pte--) {
- oldpte = *pte;
- if (l2pte_pa(oldpte) != pa) {
- pmap_section_p_failures++;
- CTR2(KTR_PMAP, "pmap_promote_section: failure for "
- "va %#x in pmap %p", va, pmap);
- return;
- }
- if ((oldpte & L2_S_PROMOTE) != (firstpte & L2_S_PROMOTE)) {
- pmap_section_p_failures++;
- CTR2(KTR_PMAP, "pmap_promote_section: failure for "
- "va %#x in pmap %p", va, pmap);
- return;
- }
- oldm = PHYS_TO_VM_PAGE(l2pte_pa(oldpte));
- if (oldm && ((oldm->oflags & VPO_UNMANAGED) != 0)) {
- pmap_section_p_failures++;
- CTR2(KTR_PMAP, "pmap_promote_section: failure for "
- "va %#x in pmap %p", va, pmap);
- return;
- }
+ return ((struct pv_chunk *)((uintptr_t)pv & ~(uintptr_t)PAGE_MASK));
+}
- pve = pmap_find_pv(&oldm->md, pmap, old_va);
- if (pve == NULL) {
- pmap_section_p_failures++;
- CTR2(KTR_PMAP, "pmap_promote_section: failure for "
- "va %#x old_va %x - no pve", va, old_va);
- return;
- }
+#define PV_PMAP(pv) (pv_to_chunk(pv)->pc_pmap)
- if (!L2_S_WRITABLE(oldpte) && (pve->pv_flags & PVF_WRITE))
- pve->pv_flags &= ~PVF_WRITE;
- if (pve->pv_flags != first_pve->pv_flags) {
- pmap_section_p_failures++;
- CTR2(KTR_PMAP, "pmap_promote_section: failure for "
- "va %#x in pmap %p", va, pmap);
- return;
- }
+#define PC_FREE0_9 0xfffffffful /* Free values for index 0 through 9 */
+#define PC_FREE10 0x0000fffful /* Free values for index 10 */
- old_va -= PAGE_SIZE;
- pa -= PAGE_SIZE;
- }
- /*
- * Promote the pv entries.
- */
- pmap_pv_promote_section(pmap, first_va, l2pte_pa(firstpte));
- /*
- * Map the superpage.
- */
- pmap_map_section(pmap, first_va, l2pte_pa(firstpte), prot, TRUE);
- /*
- * Invalidate all possible TLB mappings for small
- * pages within the newly created superpage.
- * Rely on the first PTE's attributes since they
- * have to be consistent across all of the base pages
- * within the superpage. If page is not executable it
- * is at least referenced.
- * The fastest way to do that is to invalidate whole
- * TLB at once instead of executing 256 CP15 TLB
- * invalidations by single entry. TLBs usually maintain
- * several dozen entries so loss of unrelated entries is
- * still a less agresive approach.
- */
- if (L2_S_EXECUTABLE(firstpte))
- cpu_tlb_flushID();
- else
- cpu_tlb_flushD();
- cpu_cpwait();
+static const uint32_t pc_freemask[_NPCM] = {
+ PC_FREE0_9, PC_FREE0_9, PC_FREE0_9,
+ PC_FREE0_9, PC_FREE0_9, PC_FREE0_9,
+ PC_FREE0_9, PC_FREE0_9, PC_FREE0_9,
+ PC_FREE0_9, PC_FREE10
+};
- pmap_section_promotions++;
- CTR2(KTR_PMAP, "pmap_promote_section: success for va %#x"
- " in pmap %p", first_va, pmap);
-}
+SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_count, CTLFLAG_RD, &pv_entry_count, 0,
+ "Current number of pv entries");
-/*
- * Fills a l2_bucket with mappings to consecutive physical pages.
- */
-static void
-pmap_fill_l2b(struct l2_bucket *l2b, pt_entry_t newpte)
-{
- pt_entry_t *ptep;
- int i;
+#ifdef PV_STATS
+static int pc_chunk_count, pc_chunk_allocs, pc_chunk_frees, pc_chunk_tryfail;
- for (i = 0; i < L2_PTE_NUM_TOTAL; i++) {
- ptep = &l2b->l2b_kva[i];
- *ptep = newpte;
- PTE_SYNC(ptep);
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_count, CTLFLAG_RD, &pc_chunk_count, 0,
+ "Current number of pv entry chunks");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_allocs, CTLFLAG_RD, &pc_chunk_allocs, 0,
+ "Current number of pv entry chunks allocated");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_frees, CTLFLAG_RD, &pc_chunk_frees, 0,
+ "Current number of pv entry chunks frees");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_tryfail, CTLFLAG_RD, &pc_chunk_tryfail,
+ 0, "Number of times tried to get a chunk page but failed.");
- newpte += PAGE_SIZE;
- }
+static long pv_entry_frees, pv_entry_allocs;
+static int pv_entry_spare;
- l2b->l2b_occupancy = L2_PTE_NUM_TOTAL;
-}
+SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_frees, CTLFLAG_RD, &pv_entry_frees, 0,
+ "Current number of pv entry frees");
+SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_allocs, CTLFLAG_RD, &pv_entry_allocs,
+ 0, "Current number of pv entry allocs");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_spare, CTLFLAG_RD, &pv_entry_spare, 0,
+ "Current number of spare pv entries");
+#endif
/*
- * Tries to demote a 1MB section mapping. If demotion fails, the
- * 1MB section mapping is invalidated.
+ * Is given page managed?
*/
-static boolean_t
-pmap_demote_section(pmap_t pmap, vm_offset_t va)
+static __inline boolean_t
+is_managed(vm_paddr_t pa)
{
- struct l2_bucket *l2b;
- struct pv_entry *l1pdpve;
- struct md_page *pvh;
- pd_entry_t *pl1pd, l1pd, newl1pd;
- pt_entry_t *firstptep, newpte;
- vm_offset_t pa;
+ vm_offset_t pgnum;
vm_page_t m;
- PMAP_ASSERT_LOCKED(pmap);
- /*
- * According to assumptions described in pmap_promote_section,
- * kernel is and always should be mapped using 1MB section mappings.
- * What more, managed kernel pages were not to be promoted.
- */
- KASSERT(pmap != pmap_kernel() && L1_IDX(va) != L1_IDX(vector_page),
- ("pmap_demote_section: forbidden section mapping"));
-
- va = trunc_1mpage(va);
- pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
- l1pd = *pl1pd;
- KASSERT((l1pd & L1_TYPE_MASK) == L1_S_PROTO,
- ("pmap_demote_section: not section or invalid section"));
-
- pa = l1pd & L1_S_FRAME;
- m = PHYS_TO_VM_PAGE(pa);
- KASSERT((m != NULL && (m->oflags & VPO_UNMANAGED) == 0),
- ("pmap_demote_section: no vm_page for selected superpage or"
- "unmanaged"));
-
- pvh = pa_to_pvh(pa);
- l1pdpve = pmap_find_pv(pvh, pmap, va);
- KASSERT(l1pdpve != NULL, ("pmap_demote_section: no pv entry for "
- "managed page"));
-
- l2b = pmap_get_l2_bucket(pmap, va);
- if (l2b == NULL) {
- KASSERT((l1pdpve->pv_flags & PVF_WIRED) == 0,
- ("pmap_demote_section: No l2_bucket for wired mapping"));
- /*
- * Invalidate the 1MB section mapping and return
- * "failure" if the mapping was never accessed or the
- * allocation of the new l2_bucket fails.
- */
- if (!L1_S_REFERENCED(l1pd) ||
- (l2b = pmap_alloc_l2_bucket(pmap, va)) == NULL) {
- /* Unmap and invalidate superpage. */
- pmap_remove_section(pmap, trunc_1mpage(va));
- CTR2(KTR_PMAP, "pmap_demote_section: failure for "
- "va %#x in pmap %p", va, pmap);
+ pgnum = atop(pa);
+ if (pgnum >= first_page) {
+ m = PHYS_TO_VM_PAGE(pa);
+ if (m == NULL)
return (FALSE);
- }
+ if ((m->oflags & VPO_UNMANAGED) == 0)
+ return (TRUE);
}
+ return (FALSE);
+}
- /*
- * Now we should have corresponding l2_bucket available.
- * Let's process it to recreate 256 PTEs for each base page
- * within superpage.
- */
- newpte = pa | L1_S_DEMOTE(l1pd);
- if (m->md.pv_memattr != VM_MEMATTR_UNCACHEABLE)
- newpte |= pte_l2_s_cache_mode;
+static __inline boolean_t
+pte1_is_managed(pt1_entry_t pte1)
+{
- /*
- * If the l2_bucket is new, initialize it.
- */
- if (l2b->l2b_occupancy == 0)
- pmap_fill_l2b(l2b, newpte);
- else {
- firstptep = &l2b->l2b_kva[0];
- KASSERT(l2pte_pa(*firstptep) == (pa),
- ("pmap_demote_section: firstpte and newpte map different "
- "physical addresses"));
- /*
- * If the mapping has changed attributes, update the page table
- * entries.
- */
- if ((*firstptep & L2_S_PROMOTE) != (L1_S_DEMOTE(l1pd)))
- pmap_fill_l2b(l2b, newpte);
- }
- /* Demote PV entry */
- pmap_pv_demote_section(pmap, va, pa);
-
- /* Now fix-up L1 */
- newl1pd = l2b->l2b_phys | L1_C_DOM(pmap->pm_domain) | L1_C_PROTO;
- *pl1pd = newl1pd;
- PTE_SYNC(pl1pd);
- /* Invalidate old TLB mapping */
- if (L1_S_EXECUTABLE(l1pd))
- cpu_tlb_flushID_SE(va);
- else if (L1_S_REFERENCED(l1pd))
- cpu_tlb_flushD_SE(va);
- cpu_cpwait();
-
- pmap_section_demotions++;
- CTR2(KTR_PMAP, "pmap_demote_section: success for va %#x"
- " in pmap %p", va, pmap);
- return (TRUE);
+ return (is_managed(pte1_pa(pte1)));
}
-/***************************************************
- * page management routines.
- ***************************************************/
+static __inline boolean_t
+pte2_is_managed(pt2_entry_t pte2)
+{
+
+ return (is_managed(pte2_pa(pte2)));
+}
/*
- * We are in a serious low memory condition. Resort to
- * drastic measures to free some pages so we can allocate
- * another pv entry chunk.
+ * We are in a serious low memory condition. Resort to
+ * drastic measures to free some pages so we can allocate
+ * another pv entry chunk.
*/
static vm_page_t
pmap_pv_reclaim(pmap_t locked_pmap)
{
struct pch newtail;
struct pv_chunk *pc;
- struct l2_bucket *l2b = NULL;
+ struct md_page *pvh;
+ pt1_entry_t *pte1p;
pmap_t pmap;
- pd_entry_t *pl1pd;
- pt_entry_t *ptep;
+ pt2_entry_t *pte2p, tpte2;
pv_entry_t pv;
vm_offset_t va;
- vm_page_t free, m, m_pc;
+ vm_page_t m, m_pc;
+ struct spglist free;
uint32_t inuse;
- int bit, field, freed, idx;
+ int bit, field, freed;
- PMAP_ASSERT_LOCKED(locked_pmap);
+ PMAP_LOCK_ASSERT(locked_pmap, MA_OWNED);
pmap = NULL;
- free = m_pc = NULL;
+ m_pc = NULL;
+ SLIST_INIT(&free);
TAILQ_INIT(&newtail);
while ((pc = TAILQ_FIRST(&pv_chunks)) != NULL && (pv_vafree == 0 ||
- free == NULL)) {
+ SLIST_EMPTY(&free))) {
TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
if (pmap != pc->pc_pmap) {
if (pmap != NULL) {
- cpu_tlb_flushID();
- cpu_cpwait();
if (pmap != locked_pmap)
PMAP_UNLOCK(pmap);
}
@@ -4203,33 +2825,41 @@ pmap_pv_reclaim(pmap_t locked_pmap)
for (inuse = ~pc->pc_map[field] & pc_freemask[field];
inuse != 0; inuse &= ~(1UL << bit)) {
bit = ffs(inuse) - 1;
- idx = field * sizeof(inuse) * NBBY + bit;
- pv = &pc->pc_pventry[idx];
+ pv = &pc->pc_pventry[field * 32 + bit];
va = pv->pv_va;
-
- pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
- if ((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO)
+ pte1p = pmap_pte1(pmap, va);
+ if (pte1_is_section(pte1_load(pte1p)))
continue;
- if (pv->pv_flags & PVF_WIRED)
+ pte2p = pmap_pte2(pmap, va);
+ tpte2 = pte2_load(pte2p);
+ if ((tpte2 & PTE2_W) == 0)
+ tpte2 = pte2_load_clear(pte2p);
+ pmap_pte2_release(pte2p);
+ if ((tpte2 & PTE2_W) != 0)
continue;
-
- l2b = pmap_get_l2_bucket(pmap, va);
- KASSERT(l2b != NULL, ("No l2 bucket"));
- ptep = &l2b->l2b_kva[l2pte_index(va)];
- m = PHYS_TO_VM_PAGE(l2pte_pa(*ptep));
- KASSERT((vm_offset_t)m >= KERNBASE,
- ("Trying to access non-existent page "
- "va %x pte %x", va, *ptep));
- *ptep = 0;
- PTE_SYNC(ptep);
- TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
- if (TAILQ_EMPTY(&m->md.pv_list))
- vm_page_aflag_clear(m, PGA_WRITEABLE);
+ KASSERT(tpte2 != 0,
+ ("pmap_pv_reclaim: pmap %p va %#x zero pte",
+ pmap, va));
+ pmap_tlb_flush(pmap, va);
+ m = PHYS_TO_VM_PAGE(pte2_pa(tpte2));
+ if (pte2_is_dirty(tpte2))
+ vm_page_dirty(m);
+ if ((tpte2 & PTE2_A) != 0)
+ vm_page_aflag_set(m, PGA_REFERENCED);
+ TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
+ if (TAILQ_EMPTY(&m->md.pv_list) &&
+ (m->flags & PG_FICTITIOUS) == 0) {
+ pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ if (TAILQ_EMPTY(&pvh->pv_list)) {
+ vm_page_aflag_clear(m,
+ PGA_WRITEABLE);
+ }
+ }
pc->pc_map[field] |= 1UL << bit;
+ pmap_unuse_pt2(pmap, va, &free);
freed++;
}
}
-
if (freed == 0) {
TAILQ_INSERT_TAIL(&newtail, pc, pc_lru);
continue;
@@ -4261,39 +2891,62 @@ pmap_pv_reclaim(pmap_t locked_pmap)
/* Entire chunk is free; return it. */
m_pc = PHYS_TO_VM_PAGE(pmap_kextract((vm_offset_t)pc));
pmap_qremove((vm_offset_t)pc, 1);
- pmap_ptelist_free(&pv_vafree, (vm_offset_t)pc);
+ pmap_pte2list_free(&pv_vafree, (vm_offset_t)pc);
break;
}
}
out:
TAILQ_CONCAT(&pv_chunks, &newtail, pc_lru);
if (pmap != NULL) {
- cpu_tlb_flushID();
- cpu_cpwait();
if (pmap != locked_pmap)
PMAP_UNLOCK(pmap);
}
+ if (m_pc == NULL && pv_vafree != 0 && SLIST_EMPTY(&free)) {
+ m_pc = SLIST_FIRST(&free);
+ SLIST_REMOVE_HEAD(&free, plinks.s.ss);
+ /* Recycle a freed page table page. */
+ m_pc->wire_count = 1;
+ atomic_add_int(&vm_cnt.v_wire_count, 1);
+ }
+ pmap_free_zero_pages(&free);
return (m_pc);
}
+static void
+free_pv_chunk(struct pv_chunk *pc)
+{
+ vm_page_t m;
+
+ TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
+ PV_STAT(pv_entry_spare -= _NPCPV);
+ PV_STAT(pc_chunk_count--);
+ PV_STAT(pc_chunk_frees++);
+ /* entire chunk is free, return it */
+ m = PHYS_TO_VM_PAGE(pmap_kextract((vm_offset_t)pc));
+ pmap_qremove((vm_offset_t)pc, 1);
+ vm_page_unwire(m, PQ_NONE);
+ vm_page_free(m);
+ pmap_pte2list_free(&pv_vafree, (vm_offset_t)pc);
+}
+
/*
- * free the pv_entry back to the free list
+ * Free the pv_entry back to the free list.
*/
static void
-pmap_free_pv_entry(pmap_t pmap, pv_entry_t pv)
+free_pv_entry(pmap_t pmap, pv_entry_t pv)
{
struct pv_chunk *pc;
- int bit, field, idx;
+ int idx, field, bit;
rw_assert(&pvh_global_lock, RA_WLOCKED);
- PMAP_ASSERT_LOCKED(pmap);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
PV_STAT(pv_entry_frees++);
PV_STAT(pv_entry_spare++);
pv_entry_count--;
pc = pv_to_chunk(pv);
idx = pv - &pc->pc_pventry[0];
- field = idx / (sizeof(u_long) * NBBY);
- bit = idx % (sizeof(u_long) * NBBY);
+ field = idx / 32;
+ bit = idx % 32;
pc->pc_map[field] |= 1ul << bit;
for (idx = 0; idx < _NPCM; idx++)
if (pc->pc_map[idx] != pc_freemask[idx]) {
@@ -4310,46 +2963,32 @@ pmap_free_pv_entry(pmap_t pmap, pv_entry_t pv)
return;
}
TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
- pmap_free_pv_chunk(pc);
-}
-
-static void
-pmap_free_pv_chunk(struct pv_chunk *pc)
-{
- vm_page_t m;
-
- TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
- PV_STAT(pv_entry_spare -= _NPCPV);
- PV_STAT(pc_chunk_count--);
- PV_STAT(pc_chunk_frees++);
- /* entire chunk is free, return it */
- m = PHYS_TO_VM_PAGE(pmap_kextract((vm_offset_t)pc));
- pmap_qremove((vm_offset_t)pc, 1);
- vm_page_unwire(m, PQ_NONE);
- vm_page_free(m);
- pmap_ptelist_free(&pv_vafree, (vm_offset_t)pc);
-
+ free_pv_chunk(pc);
}
+/*
+ * Get a new pv_entry, allocating a block from the system
+ * when needed.
+ */
static pv_entry_t
-pmap_get_pv_entry(pmap_t pmap, boolean_t try)
+get_pv_entry(pmap_t pmap, boolean_t try)
{
static const struct timeval printinterval = { 60, 0 };
static struct timeval lastprint;
- struct pv_chunk *pc;
+ int bit, field;
pv_entry_t pv;
+ struct pv_chunk *pc;
vm_page_t m;
- int bit, field, idx;
rw_assert(&pvh_global_lock, RA_WLOCKED);
- PMAP_ASSERT_LOCKED(pmap);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
PV_STAT(pv_entry_allocs++);
pv_entry_count++;
-
if (pv_entry_count > pv_entry_high_water)
if (ratecheck(&lastprint, &printinterval))
- printf("%s: Approaching the limit on PV entries.\n",
- __func__);
+ printf("Approaching the limit on PV entries, consider "
+ "increasing either the vm.pmap.shpgperproc or the "
+ "vm.pmap.pv_entry_max tunable.\n");
retry:
pc = TAILQ_FIRST(&pmap->pm_pvchunk);
if (pc != NULL) {
@@ -4360,8 +2999,7 @@ retry:
}
}
if (field < _NPCM) {
- idx = field * sizeof(pc->pc_map[field]) * NBBY + bit;
- pv = &pc->pc_pventry[idx];
+ pv = &pc->pc_pventry[field * 32 + bit];
pc->pc_map[field] &= ~(1ul << bit);
/* If this was the last item, move it to tail */
for (field = 0; field < _NPCM; field++)
@@ -4376,9 +3014,9 @@ retry:
}
}
/*
- * Access to the ptelist "pv_vafree" is synchronized by the pvh
+ * Access to the pte2list "pv_vafree" is synchronized by the pvh
* global lock. If "pv_vafree" is currently non-empty, it will
- * remain non-empty until pmap_ptelist_alloc() completes.
+ * remain non-empty until pmap_pte2list_alloc() completes.
*/
if (pv_vafree == 0 || (m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL |
VM_ALLOC_NOOBJ | VM_ALLOC_WIRED)) == NULL) {
@@ -4393,7 +3031,7 @@ retry:
}
PV_STAT(pc_chunk_count++);
PV_STAT(pc_chunk_allocs++);
- pc = (struct pv_chunk *)pmap_ptelist_alloc(&pv_vafree);
+ pc = (struct pv_chunk *)pmap_pte2list_alloc(&pv_vafree);
pmap_qenter((vm_offset_t)pc, &m, 1);
pc->pc_pmap = pmap;
pc->pc_map[0] = pc_freemask[0] & ~1ul; /* preallocated bit 0 */
@@ -4407,418 +3045,1818 @@ retry:
}
/*
- * Remove the given range of addresses from the specified map.
- *
- * It is assumed that the start and end are properly
- * rounded to the page size.
+ * Create a pv entry for page at pa for
+ * (pmap, va).
*/
-#define PMAP_REMOVE_CLEAN_LIST_SIZE 3
-void
-pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
+static void
+pmap_insert_entry(pmap_t pmap, vm_offset_t va, vm_page_t m)
+{
+ pv_entry_t pv;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ pv = get_pv_entry(pmap, FALSE);
+ pv->pv_va = va;
+ TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
+}
+
+static __inline pv_entry_t
+pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va)
+{
+ pv_entry_t pv;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
+ if (pmap == PV_PMAP(pv) && va == pv->pv_va) {
+ TAILQ_REMOVE(&pvh->pv_list, pv, pv_next);
+ break;
+ }
+ }
+ return (pv);
+}
+
+static void
+pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va)
+{
+ pv_entry_t pv;
+
+ pv = pmap_pvh_remove(pvh, pmap, va);
+ KASSERT(pv != NULL, ("pmap_pvh_free: pv not found"));
+ free_pv_entry(pmap, pv);
+}
+
+static void
+pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va)
{
- struct l2_bucket *l2b;
- vm_offset_t next_bucket;
- pd_entry_t l1pd;
- pt_entry_t *ptep;
- u_int total;
- u_int mappings, is_exec, is_refd;
- int flushall = 0;
+ struct md_page *pvh;
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ pmap_pvh_free(&m->md, pmap, va);
+ if (TAILQ_EMPTY(&m->md.pv_list) && (m->flags & PG_FICTITIOUS) == 0) {
+ pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ if (TAILQ_EMPTY(&pvh->pv_list))
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ }
+}
+
+static void
+pmap_pv_demote_pte1(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
+{
+ struct md_page *pvh;
+ pv_entry_t pv;
+ vm_offset_t va_last;
+ vm_page_t m;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ KASSERT((pa & PTE1_OFFSET) == 0,
+ ("pmap_pv_demote_pte1: pa is not 1mpage aligned"));
/*
- * we lock in the pmap => pv_head direction
+ * Transfer the 1mpage's pv entry for this mapping to the first
+ * page's pv list.
*/
+ pvh = pa_to_pvh(pa);
+ va = pte1_trunc(va);
+ pv = pmap_pvh_remove(pvh, pmap, va);
+ KASSERT(pv != NULL, ("pmap_pv_demote_pte1: pv not found"));
+ m = PHYS_TO_VM_PAGE(pa);
+ TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
+ /* Instantiate the remaining NPTE2_IN_PT2 - 1 pv entries. */
+ va_last = va + PTE1_SIZE - PAGE_SIZE;
+ do {
+ m++;
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_pv_demote_pte1: page %p is not managed", m));
+ va += PAGE_SIZE;
+ pmap_insert_entry(pmap, va, m);
+ } while (va < va_last);
+}
- rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap);
- total = 0;
- while (sva < eva) {
- next_bucket = L2_NEXT_BUCKET(sva);
+static void
+pmap_pv_promote_pte1(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
+{
+ struct md_page *pvh;
+ pv_entry_t pv;
+ vm_offset_t va_last;
+ vm_page_t m;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ KASSERT((pa & PTE1_OFFSET) == 0,
+ ("pmap_pv_promote_pte1: pa is not 1mpage aligned"));
+
+ /*
+ * Transfer the first page's pv entry for this mapping to the
+ * 1mpage's pv list. Aside from avoiding the cost of a call
+ * to get_pv_entry(), a transfer avoids the possibility that
+ * get_pv_entry() calls pmap_pv_reclaim() and that pmap_pv_reclaim()
+ * removes one of the mappings that is being promoted.
+ */
+ m = PHYS_TO_VM_PAGE(pa);
+ va = pte1_trunc(va);
+ pv = pmap_pvh_remove(&m->md, pmap, va);
+ KASSERT(pv != NULL, ("pmap_pv_promote_pte1: pv not found"));
+ pvh = pa_to_pvh(pa);
+ TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next);
+ /* Free the remaining NPTE2_IN_PT2 - 1 pv entries. */
+ va_last = va + PTE1_SIZE - PAGE_SIZE;
+ do {
+ m++;
+ va += PAGE_SIZE;
+ pmap_pvh_free(&m->md, pmap, va);
+ } while (va < va_last);
+}
+
+/*
+ * Conditionally create a pv entry.
+ */
+static boolean_t
+pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m)
+{
+ pv_entry_t pv;
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ if (pv_entry_count < pv_entry_high_water &&
+ (pv = get_pv_entry(pmap, TRUE)) != NULL) {
+ pv->pv_va = va;
+ TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
+ return (TRUE);
+ } else
+ return (FALSE);
+}
+
+/*
+ * Create the pv entries for each of the pages within a section.
+ */
+static boolean_t
+pmap_pv_insert_pte1(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
+{
+ struct md_page *pvh;
+ pv_entry_t pv;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ if (pv_entry_count < pv_entry_high_water &&
+ (pv = get_pv_entry(pmap, TRUE)) != NULL) {
+ pv->pv_va = va;
+ pvh = pa_to_pvh(pa);
+ TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next);
+ return (TRUE);
+ } else
+ return (FALSE);
+}
+
+/*
+ * Tries to promote the NPTE2_IN_PT2, contiguous 4KB page mappings that are
+ * within a single page table page (PT2) to a single 1MB page mapping.
+ * For promotion to occur, two conditions must be met: (1) the 4KB page
+ * mappings must map aligned, contiguous physical memory and (2) the 4KB page
+ * mappings must have identical characteristics.
+ *
+ * Managed (PG_MANAGED) mappings within the kernel address space are not
+ * promoted. The reason is that kernel PTE1s are replicated in each pmap but
+ * pmap_remove_write(), pmap_clear_modify(), and pmap_clear_reference() only
+ * read the PTE1 from the kernel pmap.
+ */
+static void
+pmap_promote_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t va)
+{
+ pt1_entry_t npte1;
+ pt2_entry_t *fpte2p, fpte2, fpte2_fav;
+ pt2_entry_t *pte2p, pte2;
+ vm_offset_t pteva __unused;
+ vm_page_t m __unused;
+
+ PDEBUG(6, printf("%s(%p): try for va %#x pte1 %#x at %p\n", __func__,
+ pmap, va, pte1_load(pte1p), pte1p));
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+
+ /*
+ * Examine the first PTE2 in the specified PT2. Abort if this PTE2 is
+ * either invalid, unused, or does not map the first 4KB physical page
+ * within a 1MB page.
+ */
+ fpte2p = pmap_pte2_quick(pmap, pte1_trunc(va));
+setpte1:
+ fpte2 = pte2_load(fpte2p);
+ if ((fpte2 & ((PTE2_FRAME & PTE1_OFFSET) | PTE2_A | PTE2_V)) !=
+ (PTE2_A | PTE2_V)) {
+ pmap_pte1_p_failures++;
+ CTR3(KTR_PMAP, "%s: failure(1) for va %#x in pmap %p",
+ __func__, va, pmap);
+ return;
+ }
+ if (pte2_is_managed(fpte2) && pmap == kernel_pmap) {
+ pmap_pte1_p_failures++;
+ CTR3(KTR_PMAP, "%s: failure(2) for va %#x in pmap %p",
+ __func__, va, pmap);
+ return;
+ }
+ if ((fpte2 & (PTE2_NM | PTE2_RO)) == PTE2_NM) {
/*
- * Check for large page.
+ * When page is not modified, PTE2_RO can be set without
+ * a TLB invalidation.
+ *
+ * Note: When modified bit is being set, then in hardware case,
+ * the TLB entry is re-read (updated) from PT2, and in
+ * software case (abort), the PTE2 is read from PT2 and
+ * TLB flushed if changed. The following cmpset() solves
+ * any race with setting this bit in both cases.
*/
- l1pd = pmap->pm_l1->l1_kva[L1_IDX(sva)];
- if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
- KASSERT((l1pd & L1_S_DOM_MASK) !=
- L1_S_DOM(PMAP_DOMAIN_KERNEL), ("pmap_remove: "
- "Trying to remove kernel section mapping"));
+ if (!pte2_cmpset(fpte2p, fpte2, fpte2 | PTE2_RO))
+ goto setpte1;
+ fpte2 |= PTE2_RO;
+ }
+
+ /*
+ * Examine each of the other PTE2s in the specified PT2. Abort if this
+ * PTE2 maps an unexpected 4KB physical page or does not have identical
+ * characteristics to the first PTE2.
+ */
+ fpte2_fav = (fpte2 & (PTE2_FRAME | PTE2_A | PTE2_V));
+ fpte2_fav += PTE1_SIZE - PTE2_SIZE; /* examine from the end */
+ for (pte2p = fpte2p + NPTE2_IN_PT2 - 1; pte2p > fpte2p; pte2p--) {
+setpte2:
+ pte2 = pte2_load(pte2p);
+ if ((pte2 & (PTE2_FRAME | PTE2_A | PTE2_V)) != fpte2_fav) {
+ pmap_pte1_p_failures++;
+ CTR3(KTR_PMAP, "%s: failure(3) for va %#x in pmap %p",
+ __func__, va, pmap);
+ return;
+ }
+ if ((pte2 & (PTE2_NM | PTE2_RO)) == PTE2_NM) {
/*
- * Are we removing the entire large page? If not,
- * demote the mapping and fall through.
+ * When page is not modified, PTE2_RO can be set
+ * without a TLB invalidation. See note above.
*/
- if (sva + L1_S_SIZE == next_bucket &&
- eva >= next_bucket) {
- pmap_remove_section(pmap, sva);
- sva = next_bucket;
- continue;
- } else if (!pmap_demote_section(pmap, sva)) {
- /* The large page mapping was destroyed. */
- sva = next_bucket;
- continue;
- }
+ if (!pte2_cmpset(pte2p, pte2, pte2 | PTE2_RO))
+ goto setpte2;
+ pte2 |= PTE2_RO;
+ pteva = pte1_trunc(va) | (pte2 & PTE1_OFFSET &
+ PTE2_FRAME);
+ CTR3(KTR_PMAP, "%s: protect for va %#x in pmap %p",
+ __func__, pteva, pmap);
+ }
+ if ((pte2 & PTE2_PROMOTE) != (fpte2 & PTE2_PROMOTE)) {
+ pmap_pte1_p_failures++;
+ CTR3(KTR_PMAP, "%s: failure(4) for va %#x in pmap %p",
+ __func__, va, pmap);
+ return;
}
+
+ fpte2_fav -= PTE2_SIZE;
+ }
+ /*
+ * The page table page in its current state will stay in PT2TAB
+ * until the PTE1 mapping the section is demoted by pmap_demote_pte1()
+ * or destroyed by pmap_remove_pte1().
+ *
+ * Note that L2 page table size is not equal to PAGE_SIZE.
+ */
+ m = PHYS_TO_VM_PAGE(trunc_page(pte1_link_pa(pte1_load(pte1p))));
+ KASSERT(m >= vm_page_array && m < &vm_page_array[vm_page_array_size],
+ ("%s: PT2 page is out of range", __func__));
+ KASSERT(m->pindex == (pte1_index(va) & ~PT2PG_MASK),
+ ("%s: PT2 page's pindex is wrong", __func__));
+
+ /*
+ * Get pte1 from pte2 format.
+ */
+ npte1 = (fpte2 & PTE1_FRAME) | ATTR_TO_L1(fpte2) | PTE1_V;
+
+ /*
+ * Promote the pv entries.
+ */
+ if (pte2_is_managed(fpte2))
+ pmap_pv_promote_pte1(pmap, va, pte1_pa(npte1));
+
+ /*
+ * Map the section.
+ */
+ if (pmap == kernel_pmap)
+ pmap_kenter_pte1(va, npte1);
+ else
+ pte1_store(pte1p, npte1);
+ /*
+ * Flush old small mappings. We call single pmap_tlb_flush() in
+ * pmap_demote_pte1() and pmap_remove_pte1(), so we must be sure that
+ * no small mappings survive. We assume that given pmap is current and
+ * don't play game with PTE2_NG.
+ */
+ pmap_tlb_flush_range(pmap, pte1_trunc(va), PTE1_SIZE);
+
+ pmap_pte1_promotions++;
+ CTR3(KTR_PMAP, "%s: success for va %#x in pmap %p",
+ __func__, va, pmap);
+
+ PDEBUG(6, printf("%s(%p): success for va %#x pte1 %#x(%#x) at %p\n",
+ __func__, pmap, va, npte1, pte1_load(pte1p), pte1p));
+}
+
+/*
+ * Zero L2 page table page.
+ */
+static __inline void
+pmap_clear_pt2(pt2_entry_t *fpte2p)
+{
+ pt2_entry_t *pte2p;
+
+ for (pte2p = fpte2p; pte2p < fpte2p + NPTE2_IN_PT2; pte2p++)
+ pte2_clear(pte2p);
+
+}
+
+/*
+ * Removes a 1MB page mapping from the kernel pmap.
+ */
+static void
+pmap_remove_kernel_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t va)
+{
+ vm_page_t m;
+ uint32_t pte1_idx;
+ pt2_entry_t *fpte2p;
+ vm_paddr_t pt2_pa;
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ m = pmap_pt2_page(pmap, va);
+ if (m == NULL)
/*
- * Do one L2 bucket's worth at a time.
+ * QQQ: Is this function called only on promoted pte1?
+ * We certainly do section mappings directly
+ * (without promotion) in kernel !!!
*/
- if (next_bucket > eva)
- next_bucket = eva;
+ panic("%s: missing pt2 page", __func__);
- l2b = pmap_get_l2_bucket(pmap, sva);
- if (l2b == NULL) {
- sva = next_bucket;
- continue;
+ pte1_idx = pte1_index(va);
+
+ /*
+ * Initialize the L2 page table.
+ */
+ fpte2p = page_pt2(pt2map_pt2pg(va), pte1_idx);
+ pmap_clear_pt2(fpte2p);
+
+ /*
+ * Remove the mapping.
+ */
+ pt2_pa = page_pt2pa(VM_PAGE_TO_PHYS(m), pte1_idx);
+ pmap_kenter_pte1(va, PTE1_LINK(pt2_pa));
+
+ /*
+ * QQQ: We do not need to invalidate PT2MAP mapping
+ * as we did not change it. I.e. the L2 page table page
+ * was and still is mapped the same way.
+ */
+}
+
+/*
+ * Do the things to unmap a section in a process
+ */
+static void
+pmap_remove_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t sva,
+ struct spglist *free)
+{
+ pt1_entry_t opte1;
+ struct md_page *pvh;
+ vm_offset_t eva, va;
+ vm_page_t m;
+
+ PDEBUG(6, printf("%s(%p): va %#x pte1 %#x at %p\n", __func__, pmap, sva,
+ pte1_load(pte1p), pte1p));
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ KASSERT((sva & PTE1_OFFSET) == 0,
+ ("%s: sva is not 1mpage aligned", __func__));
+
+ /*
+ * Clear and invalidate the mapping. It should occupy one and only TLB
+ * entry. So, pmap_tlb_flush() called with aligned address should be
+ * sufficient.
+ */
+ opte1 = pte1_load_clear(pte1p);
+ pmap_tlb_flush(pmap, sva);
+
+ if (pte1_is_wired(opte1))
+ pmap->pm_stats.wired_count -= PTE1_SIZE / PAGE_SIZE;
+ pmap->pm_stats.resident_count -= PTE1_SIZE / PAGE_SIZE;
+ if (pte1_is_managed(opte1)) {
+ pvh = pa_to_pvh(pte1_pa(opte1));
+ pmap_pvh_free(pvh, pmap, sva);
+ eva = sva + PTE1_SIZE;
+ for (va = sva, m = PHYS_TO_VM_PAGE(pte1_pa(opte1));
+ va < eva; va += PAGE_SIZE, m++) {
+ if (pte1_is_dirty(opte1))
+ vm_page_dirty(m);
+ if (opte1 & PTE1_A)
+ vm_page_aflag_set(m, PGA_REFERENCED);
+ if (TAILQ_EMPTY(&m->md.pv_list) &&
+ TAILQ_EMPTY(&pvh->pv_list))
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
+ }
+ if (pmap == kernel_pmap) {
+ /*
+ * L2 page table(s) can't be removed from kernel map as
+ * kernel counts on it (stuff around pmap_growkernel()).
+ */
+ pmap_remove_kernel_pte1(pmap, pte1p, sva);
+ } else {
+ /*
+ * Get associated L2 page table page.
+ * It's possible that the page was never allocated.
+ */
+ m = pmap_pt2_page(pmap, sva);
+ if (m != NULL)
+ pmap_unwire_pt2_all(pmap, sva, m, free);
+ }
+}
- ptep = &l2b->l2b_kva[l2pte_index(sva)];
- mappings = 0;
+/*
+ * Fills L2 page table page with mappings to consecutive physical pages.
+ */
+static __inline void
+pmap_fill_pt2(pt2_entry_t *fpte2p, pt2_entry_t npte2)
+{
+ pt2_entry_t *pte2p;
- while (sva < next_bucket) {
- struct vm_page *m;
- pt_entry_t pte;
- vm_paddr_t pa;
+ for (pte2p = fpte2p; pte2p < fpte2p + NPTE2_IN_PT2; pte2p++) {
+ pte2_store(pte2p, npte2);
+ npte2 += PTE2_SIZE;
+ }
+}
- pte = *ptep;
+/*
+ * Tries to demote a 1MB page mapping. If demotion fails, the
+ * 1MB page mapping is invalidated.
+ */
+static boolean_t
+pmap_demote_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t va)
+{
+ pt1_entry_t opte1, npte1;
+ pt2_entry_t *fpte2p, npte2;
+ vm_paddr_t pt2pg_pa, pt2_pa;
+ vm_page_t m;
+ struct spglist free;
+ uint32_t pte1_idx, isnew = 0;
- if (pte == 0) {
- /*
- * Nothing here, move along
- */
- sva += PAGE_SIZE;
- ptep++;
- continue;
- }
+ PDEBUG(6, printf("%s(%p): try for va %#x pte1 %#x at %p\n", __func__,
+ pmap, va, pte1_load(pte1p), pte1p));
- pmap->pm_stats.resident_count--;
- pa = l2pte_pa(pte);
- is_exec = 0;
- is_refd = 1;
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
- /*
- * Update flags. In a number of circumstances,
- * we could cluster a lot of these and do a
- * number of sequential pages in one go.
- */
- if ((m = PHYS_TO_VM_PAGE(pa)) != NULL) {
- struct pv_entry *pve;
-
- pve = pmap_remove_pv(m, pmap, sva);
- if (pve) {
- is_exec = PTE_BEEN_EXECD(pte);
- is_refd = PTE_BEEN_REFD(pte);
- pmap_free_pv_entry(pmap, pve);
- }
- }
+ opte1 = pte1_load(pte1p);
+ KASSERT(pte1_is_section(opte1), ("%s: opte1 not a section", __func__));
- *ptep = 0;
- PTE_SYNC(ptep);
- if (pmap_is_current(pmap)) {
- total++;
- if (total < PMAP_REMOVE_CLEAN_LIST_SIZE) {
- if (is_exec)
- cpu_tlb_flushID_SE(sva);
- else if (is_refd)
- cpu_tlb_flushD_SE(sva);
- } else if (total == PMAP_REMOVE_CLEAN_LIST_SIZE)
- flushall = 1;
- }
+ if ((opte1 & PTE1_A) == 0 || (m = pmap_pt2_page(pmap, va)) == NULL) {
+ KASSERT(!pte1_is_wired(opte1),
+ ("%s: PT2 page for a wired mapping is missing", __func__));
- sva += PAGE_SIZE;
- ptep++;
- mappings++;
+ /*
+ * Invalidate the 1MB page mapping and return
+ * "failure" if the mapping was never accessed or the
+ * allocation of the new page table page fails.
+ */
+ if ((opte1 & PTE1_A) == 0 || (m = vm_page_alloc(NULL,
+ pte1_index(va) & ~PT2PG_MASK, VM_ALLOC_NOOBJ |
+ VM_ALLOC_NORMAL | VM_ALLOC_WIRED)) == NULL) {
+ SLIST_INIT(&free);
+ pmap_remove_pte1(pmap, pte1p, pte1_trunc(va), &free);
+ pmap_free_zero_pages(&free);
+ CTR3(KTR_PMAP, "%s: failure for va %#x in pmap %p",
+ __func__, va, pmap);
+ return (FALSE);
}
+ if (va < VM_MAXUSER_ADDRESS)
+ pmap->pm_stats.resident_count++;
- pmap_free_l2_bucket(pmap, l2b, mappings);
+ isnew = 1;
+
+ /*
+ * We init all L2 page tables in the page even if
+ * we are going to change everything for one L2 page
+ * table in a while.
+ */
+ pt2pg_pa = pmap_pt2pg_init(pmap, va, m);
+ } else {
+ if (va < VM_MAXUSER_ADDRESS) {
+ if (pt2_is_empty(m, va))
+ isnew = 1; /* Demoting section w/o promotion. */
+#ifdef INVARIANTS
+ else
+ KASSERT(pt2_is_full(m, va), ("%s: bad PT2 wire"
+ " count %u", __func__,
+ pt2_wirecount_get(m, pte1_index(va))));
+#endif
+ }
}
- rw_wunlock(&pvh_global_lock);
- if (flushall)
- cpu_tlb_flushID();
- cpu_cpwait();
+ pt2pg_pa = VM_PAGE_TO_PHYS(m);
+ pte1_idx = pte1_index(va);
+ /*
+ * If the pmap is current, then the PT2MAP can provide access to
+ * the page table page (promoted L2 page tables are not unmapped).
+ * Otherwise, temporarily map the L2 page table page (m) into
+ * the kernel's address space at either PADDR1 or PADDR2.
+ *
+ * Note that L2 page table size is not equal to PAGE_SIZE.
+ */
+ if (pmap_is_current(pmap))
+ fpte2p = page_pt2(pt2map_pt2pg(va), pte1_idx);
+ else if (curthread->td_pinned > 0 && rw_wowned(&pvh_global_lock)) {
+ if (pte2_pa(pte2_load(PMAP1)) != pt2pg_pa) {
+ pte2_store(PMAP1, PTE2_KPT(pt2pg_pa));
+#ifdef SMP
+ PMAP1cpu = PCPU_GET(cpuid);
+#endif
+ tlb_flush_local((vm_offset_t)PADDR1);
+ PMAP1changed++;
+ } else
+#ifdef SMP
+ if (PMAP1cpu != PCPU_GET(cpuid)) {
+ PMAP1cpu = PCPU_GET(cpuid);
+ tlb_flush_local((vm_offset_t)PADDR1);
+ PMAP1changedcpu++;
+ } else
+#endif
+ PMAP1unchanged++;
+ fpte2p = page_pt2((vm_offset_t)PADDR1, pte1_idx);
+ } else {
+ mtx_lock(&PMAP2mutex);
+ if (pte2_pa(pte2_load(PMAP2)) != pt2pg_pa) {
+ pte2_store(PMAP2, PTE2_KPT(pt2pg_pa));
+ tlb_flush((vm_offset_t)PADDR2);
+ }
+ fpte2p = page_pt2((vm_offset_t)PADDR2, pte1_idx);
+ }
+ pt2_pa = page_pt2pa(pt2pg_pa, pte1_idx);
+ npte1 = PTE1_LINK(pt2_pa);
- PMAP_UNLOCK(pmap);
+ KASSERT((opte1 & PTE1_A) != 0,
+ ("%s: opte1 is missing PTE1_A", __func__));
+ KASSERT((opte1 & (PTE1_NM | PTE1_RO)) != PTE1_NM,
+ ("%s: opte1 has PTE1_NM", __func__));
+
+ /*
+ * Get pte2 from pte1 format.
+ */
+ npte2 = pte1_pa(opte1) | ATTR_TO_L2(opte1) | PTE2_V;
+
+ /*
+ * If the L2 page table page is new, initialize it. If the mapping
+ * has changed attributes, update the page table entries.
+ */
+ if (isnew != 0) {
+ pt2_wirecount_set(m, pte1_idx, NPTE2_IN_PT2);
+ pmap_fill_pt2(fpte2p, npte2);
+ } else if ((pte2_load(fpte2p) & PTE2_PROMOTE) !=
+ (npte2 & PTE2_PROMOTE))
+ pmap_fill_pt2(fpte2p, npte2);
+
+ KASSERT(pte2_pa(pte2_load(fpte2p)) == pte2_pa(npte2),
+ ("%s: fpte2p and npte2 map different physical addresses",
+ __func__));
+
+ if (fpte2p == PADDR2)
+ mtx_unlock(&PMAP2mutex);
+
+ /*
+ * Demote the mapping. This pmap is locked. The old PTE1 has
+ * PTE1_A set. If the old PTE1 has not PTE1_RO set, it also
+ * has not PTE1_NM set. Thus, there is no danger of a race with
+ * another processor changing the setting of PTE1_A and/or PTE1_NM
+ * between the read above and the store below.
+ */
+ if (pmap == kernel_pmap)
+ pmap_kenter_pte1(va, npte1);
+ else
+ pte1_store(pte1p, npte1);
+
+ /*
+ * Flush old big mapping. The mapping should occupy one and only
+ * TLB entry. So, pmap_tlb_flush() called with aligned address
+ * should be sufficient.
+ */
+ pmap_tlb_flush(pmap, pte1_trunc(va));
+
+ /*
+ * Demote the pv entry. This depends on the earlier demotion
+ * of the mapping. Specifically, the (re)creation of a per-
+ * page pv entry might trigger the execution of pmap_pv_reclaim(),
+ * which might reclaim a newly (re)created per-page pv entry
+ * and destroy the associated mapping. In order to destroy
+ * the mapping, the PTE1 must have already changed from mapping
+ * the 1mpage to referencing the page table page.
+ */
+ if (pte1_is_managed(opte1))
+ pmap_pv_demote_pte1(pmap, va, pte1_pa(opte1));
+
+ pmap_pte1_demotions++;
+ CTR3(KTR_PMAP, "%s: success for va %#x in pmap %p",
+ __func__, va, pmap);
+
+ PDEBUG(6, printf("%s(%p): success for va %#x pte1 %#x(%#x) at %p\n",
+ __func__, pmap, va, npte1, pte1_load(pte1p), pte1p));
+ return (TRUE);
}
/*
- * pmap_zero_page()
+ * Insert the given physical page (p) at
+ * the specified virtual address (v) in the
+ * target physical map with the protection requested.
*
- * Zero a given physical page by mapping it at a page hook point.
- * In doing the zero page op, the page we zero is mapped cachable, as with
- * StrongARM accesses to non-cached pages are non-burst making writing
- * _any_ bulk data very slow.
+ * If specified, the page will be wired down, meaning
+ * that the related pte can not be reclaimed.
+ *
+ * NB: This is the only routine which MAY NOT lazy-evaluate
+ * or lose information. That is, this routine must actually
+ * insert this page into the given map NOW.
*/
-static void
-pmap_zero_page_gen(vm_page_t m, int off, int size)
+int
+pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
+ u_int flags, int8_t psind)
{
- struct czpages *czp;
+ pt1_entry_t *pte1p;
+ pt2_entry_t *pte2p;
+ pt2_entry_t npte2, opte2;
+ pv_entry_t pv;
+ vm_paddr_t opa, pa;
+ vm_page_t mpte2, om;
+ boolean_t wired;
- KASSERT(TAILQ_EMPTY(&m->md.pv_list),
- ("pmap_zero_page_gen: page has mappings"));
+ va = trunc_page(va);
+ mpte2 = NULL;
+ wired = (flags & PMAP_ENTER_WIRED) != 0;
- vm_paddr_t phys = VM_PAGE_TO_PHYS(m);
+ KASSERT(va <= vm_max_kernel_address, ("%s: toobig", __func__));
+ KASSERT(va < UPT2V_MIN_ADDRESS || va >= UPT2V_MAX_ADDRESS,
+ ("%s: invalid to pmap_enter page table pages (va: 0x%x)", __func__,
+ va));
+ if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m))
+ VM_OBJECT_ASSERT_LOCKED(m->object);
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
sched_pin();
- czp = &cpu_czpages[PCPU_GET(cpuid)];
- mtx_lock(&czp->lock);
/*
- * Hook in the page, zero it.
+ * In the case that a page table page is not
+ * resident, we are creating it here.
*/
- *czp->dstptep = L2_S_PROTO | phys | pte_l2_s_cache_mode | L2_S_REF;
- pmap_set_prot(czp->dstptep, VM_PROT_WRITE, 0);
- PTE_SYNC(czp->dstptep);
- cpu_tlb_flushD_SE(czp->dstva);
- cpu_cpwait();
-
- if (off || size != PAGE_SIZE)
- bzero((void *)(czp->dstva + off), size);
- else
- bzero_page(czp->dstva);
+ if (va < VM_MAXUSER_ADDRESS) {
+ mpte2 = pmap_allocpte2(pmap, va, flags);
+ if (mpte2 == NULL) {
+ KASSERT((flags & PMAP_ENTER_NOSLEEP) != 0,
+ ("pmap_allocpte2 failed with sleep allowed"));
+ sched_unpin();
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+ return (KERN_RESOURCE_SHORTAGE);
+ }
+ }
+ pte1p = pmap_pte1(pmap, va);
+ if (pte1_is_section(pte1_load(pte1p)))
+ panic("%s: attempted on 1MB page", __func__);
+ pte2p = pmap_pte2_quick(pmap, va);
+ if (pte2p == NULL)
+ panic("%s: invalid L1 page table entry va=%#x", __func__, va);
+
+ om = NULL;
+ pa = VM_PAGE_TO_PHYS(m);
+ opte2 = pte2_load(pte2p);
+ opa = pte2_pa(opte2);
+ /*
+ * Mapping has not changed, must be protection or wiring change.
+ */
+ if (pte2_is_valid(opte2) && (opa == pa)) {
+ /*
+ * Wiring change, just update stats. We don't worry about
+ * wiring PT2 pages as they remain resident as long as there
+ * are valid mappings in them. Hence, if a user page is wired,
+ * the PT2 page will be also.
+ */
+ if (wired && !pte2_is_wired(opte2))
+ pmap->pm_stats.wired_count++;
+ else if (!wired && pte2_is_wired(opte2))
+ pmap->pm_stats.wired_count--;
+
+ /*
+ * Remove extra pte2 reference
+ */
+ if (mpte2)
+ pt2_wirecount_dec(mpte2, pte1_index(va));
+ if (pte2_is_managed(opte2))
+ om = m;
+ goto validate;
+ }
+
+ /*
+ * QQQ: We think that changing physical address on writeable mapping
+ * is not safe. Well, maybe on kernel address space with correct
+ * locking, it can make a sense. However, we have no idea why
+ * anyone should do that on user address space. Are we wrong?
+ */
+ KASSERT((opa == 0) || (opa == pa) ||
+ !pte2_is_valid(opte2) || ((opte2 & PTE2_RO) != 0),
+ ("%s: pmap %p va %#x(%#x) opa %#x pa %#x - gotcha %#x %#x!",
+ __func__, pmap, va, opte2, opa, pa, flags, prot));
+
+ pv = NULL;
+
+ /*
+ * Mapping has changed, invalidate old range and fall through to
+ * handle validating new mapping.
+ */
+ if (opa) {
+ if (pte2_is_wired(opte2))
+ pmap->pm_stats.wired_count--;
+ if (pte2_is_managed(opte2)) {
+ om = PHYS_TO_VM_PAGE(opa);
+ pv = pmap_pvh_remove(&om->md, pmap, va);
+ }
+ /*
+ * Remove extra pte2 reference
+ */
+ if (mpte2 != NULL)
+ pt2_wirecount_dec(mpte2, va >> PTE1_SHIFT);
+ } else
+ pmap->pm_stats.resident_count++;
+
+ /*
+ * Enter on the PV list if part of our managed memory.
+ */
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
+ KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
+ ("%s: managed mapping within the clean submap", __func__));
+ if (pv == NULL)
+ pv = get_pv_entry(pmap, FALSE);
+ pv->pv_va = va;
+ TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
+ } else if (pv != NULL)
+ free_pv_entry(pmap, pv);
/*
- * Although aliasing is not possible, if we use temporary mappings with
- * memory that will be mapped later as non-cached or with write-through
- * caches, we might end up overwriting it when calling wbinv_all. So
- * make sure caches are clean after the operation.
+ * Increment counters
*/
- cpu_idcache_wbinv_range(czp->dstva, size);
- pmap_l2cache_wbinv_range(czp->dstva, phys, size);
+ if (wired)
+ pmap->pm_stats.wired_count++;
- mtx_unlock(&czp->lock);
+validate:
+ /*
+ * Now validate mapping with desired protection/wiring.
+ */
+ npte2 = PTE2(pa, PTE2_NM, vm_page_pte2_attr(m));
+ if (prot & VM_PROT_WRITE) {
+ if (pte2_is_managed(npte2))
+ vm_page_aflag_set(m, PGA_WRITEABLE);
+ }
+ else
+ npte2 |= PTE2_RO;
+ if ((prot & VM_PROT_EXECUTE) == 0)
+ npte2 |= PTE2_NX;
+ if (wired)
+ npte2 |= PTE2_W;
+ if (va < VM_MAXUSER_ADDRESS)
+ npte2 |= PTE2_U;
+ if (pmap != kernel_pmap)
+ npte2 |= PTE2_NG;
+
+ /*
+ * If the mapping or permission bits are different, we need
+ * to update the pte2.
+ *
+ * QQQ: Think again and again what to do
+ * if the mapping is going to be changed!
+ */
+ if ((opte2 & ~(PTE2_NM | PTE2_A)) != (npte2 & ~(PTE2_NM | PTE2_A))) {
+ /*
+ * Sync icache if exec permission and attribute VM_MEMATTR_WB_WA
+ * is set. Do it now, before the mapping is stored and made
+ * valid for hardware table walk. If done later, there is a race
+ * for other threads of current process in lazy loading case.
+ * Don't do it for kernel memory which is mapped with exec
+ * permission even if the memory isn't going to hold executable
+ * code. The only time when icache sync is needed is after
+ * kernel module is loaded and the relocation info is processed.
+ * And it's done in elf_cpu_load_file().
+ *
+ * QQQ: (1) Does it exist any better way where
+ * or how to sync icache?
+ * (2) Now, we do it on a page basis.
+ */
+ if ((prot & VM_PROT_EXECUTE) && pmap != kernel_pmap &&
+ m->md.pat_mode == VM_MEMATTR_WB_WA &&
+ (opa != pa || (opte2 & PTE2_NX)))
+ cache_icache_sync_fresh(va, pa, PAGE_SIZE);
+
+ npte2 |= PTE2_A;
+ if (flags & VM_PROT_WRITE)
+ npte2 &= ~PTE2_NM;
+ if (opte2 & PTE2_V) {
+ /* Change mapping with break-before-make approach. */
+ opte2 = pte2_load_clear(pte2p);
+ pmap_tlb_flush(pmap, va);
+ pte2_store(pte2p, npte2);
+ if (opte2 & PTE2_A) {
+ if (pte2_is_managed(opte2))
+ vm_page_aflag_set(om, PGA_REFERENCED);
+ }
+ if (pte2_is_dirty(opte2)) {
+ if (pte2_is_managed(opte2))
+ vm_page_dirty(om);
+ }
+ if (pte2_is_managed(opte2) &&
+ TAILQ_EMPTY(&om->md.pv_list) &&
+ ((om->flags & PG_FICTITIOUS) != 0 ||
+ TAILQ_EMPTY(&pa_to_pvh(opa)->pv_list)))
+ vm_page_aflag_clear(om, PGA_WRITEABLE);
+ } else
+ pte2_store(pte2p, npte2);
+ }
+#if 0
+ else {
+ /*
+ * QQQ: In time when both access and not mofified bits are
+ * emulated by software, this should not happen. Some
+ * analysis is need, if this really happen. Missing
+ * tlb flush somewhere could be the reason.
+ */
+ panic("%s: pmap %p va %#x opte2 %x npte2 %x !!", __func__, pmap,
+ va, opte2, npte2);
+ }
+#endif
+ /*
+ * If both the L2 page table page and the reservation are fully
+ * populated, then attempt promotion.
+ */
+ if ((mpte2 == NULL || pt2_is_full(mpte2, va)) &&
+ sp_enabled && (m->flags & PG_FICTITIOUS) == 0 &&
+ vm_reserv_level_iffullpop(m) == 0)
+ pmap_promote_pte1(pmap, pte1p, va);
sched_unpin();
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+ return (KERN_SUCCESS);
}
/*
- * pmap_zero_page zeros the specified hardware page by mapping
- * the page into KVM and using bzero to clear its contents.
+ * Do the things to unmap a page in a process.
*/
-void
-pmap_zero_page(vm_page_t m)
+static int
+pmap_remove_pte2(pmap_t pmap, pt2_entry_t *pte2p, vm_offset_t va,
+ struct spglist *free)
{
- pmap_zero_page_gen(m, 0, PAGE_SIZE);
+ pt2_entry_t opte2;
+ vm_page_t m;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+
+ /* Clear and invalidate the mapping. */
+ opte2 = pte2_load_clear(pte2p);
+ pmap_tlb_flush(pmap, va);
+
+ KASSERT(pte2_is_valid(opte2), ("%s: pmap %p va %#x not link pte2 %#x",
+ __func__, pmap, va, opte2));
+
+ if (opte2 & PTE2_W)
+ pmap->pm_stats.wired_count -= 1;
+ pmap->pm_stats.resident_count -= 1;
+ if (pte2_is_managed(opte2)) {
+ m = PHYS_TO_VM_PAGE(pte2_pa(opte2));
+ if (pte2_is_dirty(opte2))
+ vm_page_dirty(m);
+ if (opte2 & PTE2_A)
+ vm_page_aflag_set(m, PGA_REFERENCED);
+ pmap_remove_entry(pmap, m, va);
+ }
+ return (pmap_unuse_pt2(pmap, va, free));
}
+/*
+ * Remove a single page from a process address space.
+ */
+static void
+pmap_remove_page(pmap_t pmap, vm_offset_t va, struct spglist *free)
+{
+ pt2_entry_t *pte2p;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ KASSERT(curthread->td_pinned > 0,
+ ("%s: curthread not pinned", __func__));
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ if ((pte2p = pmap_pte2_quick(pmap, va)) == NULL ||
+ !pte2_is_valid(pte2_load(pte2p)))
+ return;
+ pmap_remove_pte2(pmap, pte2p, va, free);
+}
/*
- * pmap_zero_page_area zeros the specified hardware page by mapping
- * the page into KVM and using bzero to clear its contents.
+ * Remove the given range of addresses from the specified map.
*
- * off and size may not cover an area beyond a single hardware page.
+ * It is assumed that the start and end are properly
+ * rounded to the page size.
*/
void
-pmap_zero_page_area(vm_page_t m, int off, int size)
+pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
{
+ vm_offset_t nextva;
+ pt1_entry_t *pte1p, pte1;
+ pt2_entry_t *pte2p, pte2;
+ struct spglist free;
- pmap_zero_page_gen(m, off, size);
-}
+ /*
+ * Perform an unsynchronized read. This is, however, safe.
+ */
+ if (pmap->pm_stats.resident_count == 0)
+ return;
+
+ SLIST_INIT(&free);
+
+ rw_wlock(&pvh_global_lock);
+ sched_pin();
+ PMAP_LOCK(pmap);
+
+ /*
+ * Special handling of removing one page. A very common
+ * operation and easy to short circuit some code.
+ */
+ if (sva + PAGE_SIZE == eva) {
+ pte1 = pte1_load(pmap_pte1(pmap, sva));
+ if (pte1_is_link(pte1)) {
+ pmap_remove_page(pmap, sva, &free);
+ goto out;
+ }
+ }
+
+ for (; sva < eva; sva = nextva) {
+ /*
+ * Calculate address for next L2 page table.
+ */
+ nextva = pte1_trunc(sva + PTE1_SIZE);
+ if (nextva < sva)
+ nextva = eva;
+ if (pmap->pm_stats.resident_count == 0)
+ break;
+
+ pte1p = pmap_pte1(pmap, sva);
+ pte1 = pte1_load(pte1p);
+ /*
+ * Weed out invalid mappings. Note: we assume that the L1 page
+ * table is always allocated, and in kernel virtual.
+ */
+ if (pte1 == 0)
+ continue;
+
+ if (pte1_is_section(pte1)) {
+ /*
+ * Are we removing the entire large page? If not,
+ * demote the mapping and fall through.
+ */
+ if (sva + PTE1_SIZE == nextva && eva >= nextva) {
+ pmap_remove_pte1(pmap, pte1p, sva, &free);
+ continue;
+ } else if (!pmap_demote_pte1(pmap, pte1p, sva)) {
+ /* The large page mapping was destroyed. */
+ continue;
+ }
+#ifdef INVARIANTS
+ else {
+ /* Update pte1 after demotion. */
+ pte1 = pte1_load(pte1p);
+ }
+#endif
+ }
+
+ KASSERT(pte1_is_link(pte1), ("%s: pmap %p va %#x pte1 %#x at %p"
+ " is not link", __func__, pmap, sva, pte1, pte1p));
+
+ /*
+ * Limit our scan to either the end of the va represented
+ * by the current L2 page table page, or to the end of the
+ * range being removed.
+ */
+ if (nextva > eva)
+ nextva = eva;
+
+ for (pte2p = pmap_pte2_quick(pmap, sva); sva != nextva;
+ pte2p++, sva += PAGE_SIZE) {
+ pte2 = pte2_load(pte2p);
+ if (!pte2_is_valid(pte2))
+ continue;
+ if (pmap_remove_pte2(pmap, pte2p, sva, &free))
+ break;
+ }
+ }
+out:
+ sched_unpin();
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+ pmap_free_zero_pages(&free);
+}
/*
- * pmap_zero_page_idle zeros the specified hardware page by mapping
- * the page into KVM and using bzero to clear its contents. This
- * is intended to be called from the vm_pagezero process only and
- * outside of Giant.
+ * Routine: pmap_remove_all
+ * Function:
+ * Removes this physical page from
+ * all physical maps in which it resides.
+ * Reflects back modify bits to the pager.
+ *
+ * Notes:
+ * Original versions of this routine were very
+ * inefficient because they iteratively called
+ * pmap_remove (slow...)
*/
+
void
-pmap_zero_page_idle(vm_page_t m)
+pmap_remove_all(vm_page_t m)
{
+ struct md_page *pvh;
+ pv_entry_t pv;
+ pmap_t pmap;
+ pt2_entry_t *pte2p, opte2;
+ pt1_entry_t *pte1p;
+ vm_offset_t va;
+ struct spglist free;
- pmap_zero_page(m);
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("%s: page %p is not managed", __func__, m));
+ SLIST_INIT(&free);
+ rw_wlock(&pvh_global_lock);
+ sched_pin();
+ if ((m->flags & PG_FICTITIOUS) != 0)
+ goto small_mappings;
+ pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ while ((pv = TAILQ_FIRST(&pvh->pv_list)) != NULL) {
+ va = pv->pv_va;
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte1p = pmap_pte1(pmap, va);
+ (void)pmap_demote_pte1(pmap, pte1p, va);
+ PMAP_UNLOCK(pmap);
+ }
+small_mappings:
+ while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pmap->pm_stats.resident_count--;
+ pte1p = pmap_pte1(pmap, pv->pv_va);
+ KASSERT(!pte1_is_section(pte1_load(pte1p)), ("%s: found "
+ "a 1mpage in page %p's pv list", __func__, m));
+ pte2p = pmap_pte2_quick(pmap, pv->pv_va);
+ opte2 = pte2_load_clear(pte2p);
+ pmap_tlb_flush(pmap, pv->pv_va);
+ KASSERT(pte2_is_valid(opte2), ("%s: pmap %p va %x zero pte2",
+ __func__, pmap, pv->pv_va));
+ if (pte2_is_wired(opte2))
+ pmap->pm_stats.wired_count--;
+ if (opte2 & PTE2_A)
+ vm_page_aflag_set(m, PGA_REFERENCED);
+
+ /*
+ * Update the vm_page_t clean and reference bits.
+ */
+ if (pte2_is_dirty(opte2))
+ vm_page_dirty(m);
+ pmap_unuse_pt2(pmap, pv->pv_va, &free);
+ TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
+ free_pv_entry(pmap, pv);
+ PMAP_UNLOCK(pmap);
+ }
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ sched_unpin();
+ rw_wunlock(&pvh_global_lock);
+ pmap_free_zero_pages(&free);
}
/*
- * pmap_copy_page copies the specified (machine independent)
- * page by mapping the page into virtual memory and using
- * bcopy to copy the page, one machine dependent page at a
- * time.
+ * Just subroutine for pmap_remove_pages() to reasonably satisfy
+ * good coding style, a.k.a. 80 character line width limit hell.
*/
+static __inline void
+pmap_remove_pte1_quick(pmap_t pmap, pt1_entry_t pte1, pv_entry_t pv,
+ struct spglist *free)
+{
+ vm_paddr_t pa;
+ vm_page_t m, mt, mpt2pg;
+ struct md_page *pvh;
+
+ pa = pte1_pa(pte1);
+ m = PHYS_TO_VM_PAGE(pa);
+
+ KASSERT(m->phys_addr == pa, ("%s: vm_page_t %p addr mismatch %#x %#x",
+ __func__, m, m->phys_addr, pa));
+ KASSERT((m->flags & PG_FICTITIOUS) != 0 ||
+ m < &vm_page_array[vm_page_array_size],
+ ("%s: bad pte1 %#x", __func__, pte1));
+
+ if (pte1_is_dirty(pte1)) {
+ for (mt = m; mt < &m[PTE1_SIZE / PAGE_SIZE]; mt++)
+ vm_page_dirty(mt);
+ }
+
+ pmap->pm_stats.resident_count -= PTE1_SIZE / PAGE_SIZE;
+ pvh = pa_to_pvh(pa);
+ TAILQ_REMOVE(&pvh->pv_list, pv, pv_next);
+ if (TAILQ_EMPTY(&pvh->pv_list)) {
+ for (mt = m; mt < &m[PTE1_SIZE / PAGE_SIZE]; mt++)
+ if (TAILQ_EMPTY(&mt->md.pv_list))
+ vm_page_aflag_clear(mt, PGA_WRITEABLE);
+ }
+ mpt2pg = pmap_pt2_page(pmap, pv->pv_va);
+ if (mpt2pg != NULL)
+ pmap_unwire_pt2_all(pmap, pv->pv_va, mpt2pg, free);
+}
/*
- * pmap_copy_page()
- *
- * Copy one physical page into another, by mapping the pages into
- * hook points. The same comment regarding cachability as in
- * pmap_zero_page also applies here.
+ * Just subroutine for pmap_remove_pages() to reasonably satisfy
+ * good coding style, a.k.a. 80 character line width limit hell.
+ */
+static __inline void
+pmap_remove_pte2_quick(pmap_t pmap, pt2_entry_t pte2, pv_entry_t pv,
+ struct spglist *free)
+{
+ vm_paddr_t pa;
+ vm_page_t m;
+ struct md_page *pvh;
+
+ pa = pte2_pa(pte2);
+ m = PHYS_TO_VM_PAGE(pa);
+
+ KASSERT(m->phys_addr == pa, ("%s: vm_page_t %p addr mismatch %#x %#x",
+ __func__, m, m->phys_addr, pa));
+ KASSERT((m->flags & PG_FICTITIOUS) != 0 ||
+ m < &vm_page_array[vm_page_array_size],
+ ("%s: bad pte2 %#x", __func__, pte2));
+
+ if (pte2_is_dirty(pte2))
+ vm_page_dirty(m);
+
+ pmap->pm_stats.resident_count--;
+ TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
+ if (TAILQ_EMPTY(&m->md.pv_list) && (m->flags & PG_FICTITIOUS) == 0) {
+ pvh = pa_to_pvh(pa);
+ if (TAILQ_EMPTY(&pvh->pv_list))
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ }
+ pmap_unuse_pt2(pmap, pv->pv_va, free);
+}
+
+/*
+ * Remove all pages from specified address space this aids process
+ * exit speeds. Also, this code is special cased for current process
+ * only, but can have the more generic (and slightly slower) mode enabled.
+ * This is much faster than pmap_remove in the case of running down
+ * an entire address space.
*/
void
-pmap_copy_page_generic(vm_paddr_t src, vm_paddr_t dst)
+pmap_remove_pages(pmap_t pmap)
{
- struct czpages *czp;
+ pt1_entry_t *pte1p, pte1;
+ pt2_entry_t *pte2p, pte2;
+ pv_entry_t pv;
+ struct pv_chunk *pc, *npc;
+ struct spglist free;
+ int field, idx;
+ int32_t bit;
+ uint32_t inuse, bitmask;
+ boolean_t allfree;
+ /*
+ * Assert that the given pmap is only active on the current
+ * CPU. Unfortunately, we cannot block another CPU from
+ * activating the pmap while this function is executing.
+ */
+ KASSERT(pmap == vmspace_pmap(curthread->td_proc->p_vmspace),
+ ("%s: non-current pmap %p", __func__, pmap));
+#if defined(SMP) && defined(INVARIANTS)
+ {
+ cpuset_t other_cpus;
+
+ sched_pin();
+ other_cpus = pmap->pm_active;
+ CPU_CLR(PCPU_GET(cpuid), &other_cpus);
+ sched_unpin();
+ KASSERT(CPU_EMPTY(&other_cpus),
+ ("%s: pmap %p active on other cpus", __func__, pmap));
+ }
+#endif
+ SLIST_INIT(&free);
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
sched_pin();
- czp = &cpu_czpages[PCPU_GET(cpuid)];
- mtx_lock(&czp->lock);
+ TAILQ_FOREACH_SAFE(pc, &pmap->pm_pvchunk, pc_list, npc) {
+ KASSERT(pc->pc_pmap == pmap, ("%s: wrong pmap %p %p",
+ __func__, pmap, pc->pc_pmap));
+ allfree = TRUE;
+ for (field = 0; field < _NPCM; field++) {
+ inuse = (~(pc->pc_map[field])) & pc_freemask[field];
+ while (inuse != 0) {
+ bit = ffs(inuse) - 1;
+ bitmask = 1UL << bit;
+ idx = field * 32 + bit;
+ pv = &pc->pc_pventry[idx];
+ inuse &= ~bitmask;
+
+ /*
+ * Note that we cannot remove wired pages
+ * from a process' mapping at this time
+ */
+ pte1p = pmap_pte1(pmap, pv->pv_va);
+ pte1 = pte1_load(pte1p);
+ if (pte1_is_section(pte1)) {
+ if (pte1_is_wired(pte1)) {
+ allfree = FALSE;
+ continue;
+ }
+ pte1_clear(pte1p);
+ pmap_remove_pte1_quick(pmap, pte1, pv,
+ &free);
+ }
+ else if (pte1_is_link(pte1)) {
+ pte2p = pt2map_entry(pv->pv_va);
+ pte2 = pte2_load(pte2p);
+
+ if (!pte2_is_valid(pte2)) {
+ printf("%s: pmap %p va %#x "
+ "pte2 %#x\n", __func__,
+ pmap, pv->pv_va, pte2);
+ panic("bad pte2");
+ }
+
+ if (pte2_is_wired(pte2)) {
+ allfree = FALSE;
+ continue;
+ }
+ pte2_clear(pte2p);
+ pmap_remove_pte2_quick(pmap, pte2, pv,
+ &free);
+ } else {
+ printf("%s: pmap %p va %#x pte1 %#x\n",
+ __func__, pmap, pv->pv_va, pte1);
+ panic("bad pte1");
+ }
+
+ /* Mark free */
+ PV_STAT(pv_entry_frees++);
+ PV_STAT(pv_entry_spare++);
+ pv_entry_count--;
+ pc->pc_map[field] |= bitmask;
+ }
+ }
+ if (allfree) {
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ free_pv_chunk(pc);
+ }
+ }
+ tlb_flush_all_ng_local();
+ sched_unpin();
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+ pmap_free_zero_pages(&free);
+}
+
+/*
+ * This code makes some *MAJOR* assumptions:
+ * 1. Current pmap & pmap exists.
+ * 2. Not wired.
+ * 3. Read access.
+ * 4. No L2 page table pages.
+ * but is *MUCH* faster than pmap_enter...
+ */
+static vm_page_t
+pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
+ vm_prot_t prot, vm_page_t mpt2pg)
+{
+ pt2_entry_t *pte2p, pte2;
+ vm_paddr_t pa;
+ struct spglist free;
+ uint32_t l2prot;
+
+ KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva ||
+ (m->oflags & VPO_UNMANAGED) != 0,
+ ("%s: managed mapping within the clean submap", __func__));
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+
+ /*
+ * In the case that a L2 page table page is not
+ * resident, we are creating it here.
+ */
+ if (va < VM_MAXUSER_ADDRESS) {
+ u_int pte1_idx;
+ pt1_entry_t pte1, *pte1p;
+ vm_paddr_t pt2_pa;
+
+ /*
+ * Get L1 page table things.
+ */
+ pte1_idx = pte1_index(va);
+ pte1p = pmap_pte1(pmap, va);
+ pte1 = pte1_load(pte1p);
+
+ if (mpt2pg && (mpt2pg->pindex == (pte1_idx & ~PT2PG_MASK))) {
+ /*
+ * Each of NPT2_IN_PG L2 page tables on the page can
+ * come here. Make sure that associated L1 page table
+ * link is established.
+ *
+ * QQQ: It comes that we don't establish all links to
+ * L2 page tables for newly allocated L2 page
+ * tables page.
+ */
+ KASSERT(!pte1_is_section(pte1),
+ ("%s: pte1 %#x is section", __func__, pte1));
+ if (!pte1_is_link(pte1)) {
+ pt2_pa = page_pt2pa(VM_PAGE_TO_PHYS(mpt2pg),
+ pte1_idx);
+ pte1_store(pte1p, PTE1_LINK(pt2_pa));
+ }
+ pt2_wirecount_inc(mpt2pg, pte1_idx);
+ } else {
+ /*
+ * If the L2 page table page is mapped, we just
+ * increment the hold count, and activate it.
+ */
+ if (pte1_is_section(pte1)) {
+ return (NULL);
+ } else if (pte1_is_link(pte1)) {
+ mpt2pg = PHYS_TO_VM_PAGE(pte1_link_pa(pte1));
+ pt2_wirecount_inc(mpt2pg, pte1_idx);
+ } else {
+ mpt2pg = _pmap_allocpte2(pmap, va,
+ PMAP_ENTER_NOSLEEP);
+ if (mpt2pg == NULL)
+ return (NULL);
+ }
+ }
+ } else {
+ mpt2pg = NULL;
+ }
/*
- * Map the pages into the page hook points, copy them, and purge the
- * cache for the appropriate page.
+ * This call to pt2map_entry() makes the assumption that we are
+ * entering the page into the current pmap. In order to support
+ * quick entry into any pmap, one would likely use pmap_pte2_quick().
+ * But that isn't as quick as pt2map_entry().
*/
- *czp->srcptep = L2_S_PROTO | src | pte_l2_s_cache_mode | L2_S_REF;
- pmap_set_prot(czp->srcptep, VM_PROT_READ, 0);
- PTE_SYNC(czp->srcptep);
- cpu_tlb_flushD_SE(czp->srcva);
- *czp->dstptep = L2_S_PROTO | dst | pte_l2_s_cache_mode | L2_S_REF;
- pmap_set_prot(czp->dstptep, VM_PROT_READ | VM_PROT_WRITE, 0);
- PTE_SYNC(czp->dstptep);
- cpu_tlb_flushD_SE(czp->dstva);
- cpu_cpwait();
-
- bcopy_page(czp->srcva, czp->dstva);
+ pte2p = pt2map_entry(va);
+ pte2 = pte2_load(pte2p);
+ if (pte2_is_valid(pte2)) {
+ if (mpt2pg != NULL) {
+ /*
+ * Remove extra pte2 reference
+ */
+ pt2_wirecount_dec(mpt2pg, pte1_index(va));
+ mpt2pg = NULL;
+ }
+ return (NULL);
+ }
/*
- * Although aliasing is not possible, if we use temporary mappings with
- * memory that will be mapped later as non-cached or with write-through
- * caches, we might end up overwriting it when calling wbinv_all. So
- * make sure caches are clean after the operation.
+ * Enter on the PV list if part of our managed memory.
*/
- cpu_idcache_wbinv_range(czp->dstva, PAGE_SIZE);
- pmap_l2cache_wbinv_range(czp->dstva, dst, PAGE_SIZE);
+ if ((m->oflags & VPO_UNMANAGED) == 0 &&
+ !pmap_try_insert_pv_entry(pmap, va, m)) {
+ if (mpt2pg != NULL) {
+ SLIST_INIT(&free);
+ if (pmap_unwire_pt2(pmap, va, mpt2pg, &free)) {
+ pmap_tlb_flush(pmap, va);
+ pmap_free_zero_pages(&free);
+ }
- mtx_unlock(&czp->lock);
- sched_unpin();
-}
+ mpt2pg = NULL;
+ }
+ return (NULL);
+ }
-int unmapped_buf_allowed = 1;
+ /*
+ * Increment counters
+ */
+ pmap->pm_stats.resident_count++;
+
+ /*
+ * Now validate mapping with RO protection
+ */
+ pa = VM_PAGE_TO_PHYS(m);
+ l2prot = PTE2_RO | PTE2_NM;
+ if (va < VM_MAXUSER_ADDRESS)
+ l2prot |= PTE2_U | PTE2_NG;
+ if ((prot & VM_PROT_EXECUTE) == 0)
+ l2prot |= PTE2_NX;
+ else if (m->md.pat_mode == VM_MEMATTR_WB_WA && pmap != kernel_pmap) {
+ /*
+ * Sync icache if exec permission and attribute VM_MEMATTR_WB_WA
+ * is set. QQQ: For more info, see comments in pmap_enter().
+ */
+ cache_icache_sync_fresh(va, pa, PAGE_SIZE);
+ }
+ pte2_store(pte2p, PTE2(pa, l2prot, vm_page_pte2_attr(m)));
+
+ return (mpt2pg);
+}
void
-pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
- vm_offset_t b_offset, int xfersize)
+pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
{
- vm_page_t a_pg, b_pg;
- vm_offset_t a_pg_offset, b_pg_offset;
- int cnt;
- struct czpages *czp;
- sched_pin();
- czp = &cpu_czpages[PCPU_GET(cpuid)];
- mtx_lock(&czp->lock);
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ (void)pmap_enter_quick_locked(pmap, va, m, prot, NULL);
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+}
- while (xfersize > 0) {
- a_pg = ma[a_offset >> PAGE_SHIFT];
- a_pg_offset = a_offset & PAGE_MASK;
- cnt = min(xfersize, PAGE_SIZE - a_pg_offset);
- b_pg = mb[b_offset >> PAGE_SHIFT];
- b_pg_offset = b_offset & PAGE_MASK;
- cnt = min(cnt, PAGE_SIZE - b_pg_offset);
- *czp->srcptep = L2_S_PROTO | VM_PAGE_TO_PHYS(a_pg) |
- pte_l2_s_cache_mode | L2_S_REF;
- pmap_set_prot(czp->srcptep, VM_PROT_READ, 0);
- PTE_SYNC(czp->srcptep);
- cpu_tlb_flushD_SE(czp->srcva);
- *czp->dstptep = L2_S_PROTO | VM_PAGE_TO_PHYS(b_pg) |
- pte_l2_s_cache_mode | L2_S_REF;
- pmap_set_prot(czp->dstptep, VM_PROT_READ | VM_PROT_WRITE, 0);
- PTE_SYNC(czp->dstptep);
- cpu_tlb_flushD_SE(czp->dstva);
- cpu_cpwait();
- bcopy((char *)czp->srcva + a_pg_offset, (char *)czp->dstva + b_pg_offset,
- cnt);
- cpu_idcache_wbinv_range(czp->dstva + b_pg_offset, cnt);
- pmap_l2cache_wbinv_range(czp->dstva + b_pg_offset,
- VM_PAGE_TO_PHYS(b_pg) + b_pg_offset, cnt);
- xfersize -= cnt;
- a_offset += cnt;
- b_offset += cnt;
+/*
+ * Tries to create 1MB page mapping. Returns TRUE if successful and
+ * FALSE otherwise. Fails if (1) a page table page cannot be allocated without
+ * blocking, (2) a mapping already exists at the specified virtual address, or
+ * (3) a pv entry cannot be allocated without reclaiming another pv entry.
+ */
+static boolean_t
+pmap_enter_pte1(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
+{
+ pt1_entry_t *pte1p;
+ vm_paddr_t pa;
+ uint32_t l1prot;
+
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ pte1p = pmap_pte1(pmap, va);
+ if (pte1_is_valid(pte1_load(pte1p))) {
+ CTR3(KTR_PMAP, "%s: failure for va %#lx in pmap %p", __func__,
+ va, pmap);
+ return (FALSE);
+ }
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
+ /*
+ * Abort this mapping if its PV entry could not be created.
+ */
+ if (!pmap_pv_insert_pte1(pmap, va, VM_PAGE_TO_PHYS(m))) {
+ CTR3(KTR_PMAP, "%s: failure for va %#lx in pmap %p",
+ __func__, va, pmap);
+ return (FALSE);
+ }
}
+ /*
+ * Increment counters.
+ */
+ pmap->pm_stats.resident_count += PTE1_SIZE / PAGE_SIZE;
- mtx_unlock(&czp->lock);
- sched_unpin();
+ /*
+ * Map the section.
+ *
+ * QQQ: Why VM_PROT_WRITE is not evaluated and the mapping is
+ * made readonly?
+ */
+ pa = VM_PAGE_TO_PHYS(m);
+ l1prot = PTE1_RO | PTE1_NM;
+ if (va < VM_MAXUSER_ADDRESS)
+ l1prot |= PTE1_U | PTE1_NG;
+ if ((prot & VM_PROT_EXECUTE) == 0)
+ l1prot |= PTE1_NX;
+ else if (m->md.pat_mode == VM_MEMATTR_WB_WA && pmap != kernel_pmap) {
+ /*
+ * Sync icache if exec permission and attribute VM_MEMATTR_WB_WA
+ * is set. QQQ: For more info, see comments in pmap_enter().
+ */
+ cache_icache_sync_fresh(va, pa, PTE1_SIZE);
+ }
+ pte1_store(pte1p, PTE1(pa, l1prot, ATTR_TO_L1(vm_page_pte2_attr(m))));
+
+ pmap_pte1_mappings++;
+ CTR3(KTR_PMAP, "%s: success for va %#lx in pmap %p", __func__, va,
+ pmap);
+ return (TRUE);
}
+/*
+ * Maps a sequence of resident pages belonging to the same object.
+ * The sequence begins with the given page m_start. This page is
+ * mapped at the given virtual address start. Each subsequent page is
+ * mapped at a virtual address that is offset from start by the same
+ * amount as the page is offset from m_start within the object. The
+ * last page in the sequence is the page with the largest offset from
+ * m_start that can be mapped at a virtual address less than the given
+ * virtual address end. Not every virtual page between start and end
+ * is mapped; only those for which a resident page exists with the
+ * corresponding offset from m_start are mapped.
+ */
void
-pmap_copy_page(vm_page_t src, vm_page_t dst)
+pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
+ vm_page_t m_start, vm_prot_t prot)
{
+ vm_offset_t va;
+ vm_page_t m, mpt2pg;
+ vm_pindex_t diff, psize;
- if (_arm_memcpy && PAGE_SIZE >= _min_memcpy_size &&
- _arm_memcpy((void *)VM_PAGE_TO_PHYS(dst),
- (void *)VM_PAGE_TO_PHYS(src), PAGE_SIZE, IS_PHYSICAL) == 0)
- return;
+ PDEBUG(6, printf("%s: pmap %p start %#x end %#x m %p prot %#x\n",
+ __func__, pmap, start, end, m_start, prot));
- pmap_copy_page_generic(VM_PAGE_TO_PHYS(src), VM_PAGE_TO_PHYS(dst));
+ VM_OBJECT_ASSERT_LOCKED(m_start->object);
+ psize = atop(end - start);
+ mpt2pg = NULL;
+ m = m_start;
+ rw_wlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
+ va = start + ptoa(diff);
+ if ((va & PTE1_OFFSET) == 0 && va + PTE1_SIZE <= end &&
+ m->psind == 1 && sp_enabled &&
+ pmap_enter_pte1(pmap, va, m, prot))
+ m = &m[PTE1_SIZE / PAGE_SIZE - 1];
+ else
+ mpt2pg = pmap_enter_quick_locked(pmap, va, m, prot,
+ mpt2pg);
+ m = TAILQ_NEXT(m, listq);
+ }
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
}
-vm_offset_t
-pmap_quick_enter_page(vm_page_t m)
+/*
+ * This code maps large physical mmap regions into the
+ * processor address space. Note that some shortcuts
+ * are taken, but the code works.
+ */
+void
+pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object,
+ vm_pindex_t pindex, vm_size_t size)
{
- pt_entry_t *qmap_pte;
- vm_offset_t qmap_addr;
+ pt1_entry_t *pte1p;
+ vm_paddr_t pa, pte2_pa;
+ vm_page_t p;
+ vm_memattr_t pat_mode;
+ u_int l1attr, l1prot;
- critical_enter();
+ VM_OBJECT_ASSERT_WLOCKED(object);
+ KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG,
+ ("%s: non-device object", __func__));
+ if ((addr & PTE1_OFFSET) == 0 && (size & PTE1_OFFSET) == 0) {
+ if (!vm_object_populate(object, pindex, pindex + atop(size)))
+ return;
+ p = vm_page_lookup(object, pindex);
+ KASSERT(p->valid == VM_PAGE_BITS_ALL,
+ ("%s: invalid page %p", __func__, p));
+ pat_mode = p->md.pat_mode;
- qmap_addr = PCPU_GET(qmap_addr);
- qmap_pte = PCPU_GET(qmap_pte);
+ /*
+ * Abort the mapping if the first page is not physically
+ * aligned to a 1MB page boundary.
+ */
+ pte2_pa = VM_PAGE_TO_PHYS(p);
+ if (pte2_pa & PTE1_OFFSET)
+ return;
- KASSERT(*qmap_pte == 0, ("pmap_quick_enter_page: PTE busy"));
+ /*
+ * Skip the first page. Abort the mapping if the rest of
+ * the pages are not physically contiguous or have differing
+ * memory attributes.
+ */
+ p = TAILQ_NEXT(p, listq);
+ for (pa = pte2_pa + PAGE_SIZE; pa < pte2_pa + size;
+ pa += PAGE_SIZE) {
+ KASSERT(p->valid == VM_PAGE_BITS_ALL,
+ ("%s: invalid page %p", __func__, p));
+ if (pa != VM_PAGE_TO_PHYS(p) ||
+ pat_mode != p->md.pat_mode)
+ return;
+ p = TAILQ_NEXT(p, listq);
+ }
- *qmap_pte = L2_S_PROTO | VM_PAGE_TO_PHYS(m) | L2_S_REF;
- if (m->md.pv_memattr != VM_MEMATTR_UNCACHEABLE)
- *qmap_pte |= pte_l2_s_cache_mode;
- pmap_set_prot(qmap_pte, VM_PROT_READ | VM_PROT_WRITE, 0);
- PTE_SYNC(qmap_pte);
- cpu_tlb_flushD_SE(qmap_addr);
- cpu_cpwait();
+ /*
+ * Map using 1MB pages.
+ *
+ * QQQ: Well, we are mapping a section, so same condition must
+ * be hold like during promotion. It looks that only RW mapping
+ * is done here, so readonly mapping must be done elsewhere.
+ */
+ l1prot = PTE1_U | PTE1_NG | PTE1_RW | PTE1_M | PTE1_A;
+ l1attr = ATTR_TO_L1(vm_memattr_to_pte2(pat_mode));
+ PMAP_LOCK(pmap);
+ for (pa = pte2_pa; pa < pte2_pa + size; pa += PTE1_SIZE) {
+ pte1p = pmap_pte1(pmap, addr);
+ if (!pte1_is_valid(pte1_load(pte1p))) {
+ pte1_store(pte1p, PTE1(pa, l1prot, l1attr));
+ pmap->pm_stats.resident_count += PTE1_SIZE /
+ PAGE_SIZE;
+ pmap_pte1_mappings++;
+ }
+ /* Else continue on if the PTE1 is already valid. */
+ addr += PTE1_SIZE;
+ }
+ PMAP_UNLOCK(pmap);
+ }
+}
- return (qmap_addr);
+/*
+ * Do the things to protect a 1mpage in a process.
+ */
+static void
+pmap_protect_pte1(pmap_t pmap, pt1_entry_t *pte1p, vm_offset_t sva,
+ vm_prot_t prot)
+{
+ pt1_entry_t npte1, opte1;
+ vm_offset_t eva, va;
+ vm_page_t m;
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ KASSERT((sva & PTE1_OFFSET) == 0,
+ ("%s: sva is not 1mpage aligned", __func__));
+retry:
+ opte1 = npte1 = pte1_load(pte1p);
+ if (pte1_is_managed(opte1)) {
+ eva = sva + PTE1_SIZE;
+ for (va = sva, m = PHYS_TO_VM_PAGE(pte1_pa(opte1));
+ va < eva; va += PAGE_SIZE, m++)
+ if (pte1_is_dirty(opte1))
+ vm_page_dirty(m);
+ }
+ if ((prot & VM_PROT_WRITE) == 0)
+ npte1 |= PTE1_RO | PTE1_NM;
+ if ((prot & VM_PROT_EXECUTE) == 0)
+ npte1 |= PTE1_NX;
+
+ /*
+ * QQQ: Herein, execute permission is never set.
+ * It only can be cleared. So, no icache
+ * syncing is needed.
+ */
+
+ if (npte1 != opte1) {
+ if (!pte1_cmpset(pte1p, opte1, npte1))
+ goto retry;
+ pmap_tlb_flush(pmap, sva);
+ }
}
+/*
+ * Set the physical protection on the
+ * specified range of this map as requested.
+ */
void
-pmap_quick_remove_page(vm_offset_t addr)
+pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
{
- pt_entry_t *qmap_pte;
+ boolean_t pv_lists_locked;
+ vm_offset_t nextva;
+ pt1_entry_t *pte1p, pte1;
+ pt2_entry_t *pte2p, opte2, npte2;
- qmap_pte = PCPU_GET(qmap_pte);
+ KASSERT((prot & ~VM_PROT_ALL) == 0, ("invalid prot %x", prot));
+ if (prot == VM_PROT_NONE) {
+ pmap_remove(pmap, sva, eva);
+ return;
+ }
- KASSERT(addr == PCPU_GET(qmap_addr),
- ("pmap_quick_remove_page: invalid address"));
- KASSERT(*qmap_pte != 0,
- ("pmap_quick_remove_page: PTE not in use"));
+ if ((prot & (VM_PROT_WRITE | VM_PROT_EXECUTE)) ==
+ (VM_PROT_WRITE | VM_PROT_EXECUTE))
+ return;
- cpu_idcache_wbinv_range(addr, PAGE_SIZE);
- pmap_l2cache_wbinv_range(addr, *qmap_pte & L2_S_FRAME, PAGE_SIZE);
- *qmap_pte = 0;
- PTE_SYNC(qmap_pte);
- critical_exit();
+ if (pmap_is_current(pmap))
+ pv_lists_locked = FALSE;
+ else {
+ pv_lists_locked = TRUE;
+resume:
+ rw_wlock(&pvh_global_lock);
+ sched_pin();
+ }
+
+ PMAP_LOCK(pmap);
+ for (; sva < eva; sva = nextva) {
+ /*
+ * Calculate address for next L2 page table.
+ */
+ nextva = pte1_trunc(sva + PTE1_SIZE);
+ if (nextva < sva)
+ nextva = eva;
+
+ pte1p = pmap_pte1(pmap, sva);
+ pte1 = pte1_load(pte1p);
+
+ /*
+ * Weed out invalid mappings. Note: we assume that L1 page
+ * page table is always allocated, and in kernel virtual.
+ */
+ if (pte1 == 0)
+ continue;
+
+ if (pte1_is_section(pte1)) {
+ /*
+ * Are we protecting the entire large page? If not,
+ * demote the mapping and fall through.
+ */
+ if (sva + PTE1_SIZE == nextva && eva >= nextva) {
+ pmap_protect_pte1(pmap, pte1p, sva, prot);
+ continue;
+ } else {
+ if (!pv_lists_locked) {
+ pv_lists_locked = TRUE;
+ if (!rw_try_wlock(&pvh_global_lock)) {
+ PMAP_UNLOCK(pmap);
+ goto resume;
+ }
+ sched_pin();
+ }
+ if (!pmap_demote_pte1(pmap, pte1p, sva)) {
+ /*
+ * The large page mapping
+ * was destroyed.
+ */
+ continue;
+ }
+#ifdef INVARIANTS
+ else {
+ /* Update pte1 after demotion */
+ pte1 = pte1_load(pte1p);
+ }
+#endif
+ }
+ }
+
+ KASSERT(pte1_is_link(pte1), ("%s: pmap %p va %#x pte1 %#x at %p"
+ " is not link", __func__, pmap, sva, pte1, pte1p));
+
+ /*
+ * Limit our scan to either the end of the va represented
+ * by the current L2 page table page, or to the end of the
+ * range being protected.
+ */
+ if (nextva > eva)
+ nextva = eva;
+
+ for (pte2p = pmap_pte2_quick(pmap, sva); sva != nextva; pte2p++,
+ sva += PAGE_SIZE) {
+ vm_page_t m;
+retry:
+ opte2 = npte2 = pte2_load(pte2p);
+ if (!pte2_is_valid(opte2))
+ continue;
+
+ if ((prot & VM_PROT_WRITE) == 0) {
+ if (pte2_is_managed(opte2) &&
+ pte2_is_dirty(opte2)) {
+ m = PHYS_TO_VM_PAGE(pte2_pa(opte2));
+ vm_page_dirty(m);
+ }
+ npte2 |= PTE2_RO | PTE2_NM;
+ }
+
+ if ((prot & VM_PROT_EXECUTE) == 0)
+ npte2 |= PTE2_NX;
+
+ /*
+ * QQQ: Herein, execute permission is never set.
+ * It only can be cleared. So, no icache
+ * syncing is needed.
+ */
+
+ if (npte2 != opte2) {
+
+ if (!pte2_cmpset(pte2p, opte2, npte2))
+ goto retry;
+ pmap_tlb_flush(pmap, sva);
+ }
+ }
+ }
+ if (pv_lists_locked) {
+ sched_unpin();
+ rw_wunlock(&pvh_global_lock);
+ }
+ PMAP_UNLOCK(pmap);
}
/*
- * this routine returns true if a physical page resides
- * in the given pmap.
+ * pmap_pvh_wired_mappings:
+ *
+ * Return the updated number "count" of managed mappings that are wired.
*/
-boolean_t
-pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
+static int
+pmap_pvh_wired_mappings(struct md_page *pvh, int count)
{
- struct md_page *pvh;
+ pmap_t pmap;
+ pt1_entry_t pte1;
+ pt2_entry_t pte2;
pv_entry_t pv;
- int loops = 0;
- boolean_t rv;
- KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("pmap_page_exists_quick: page %p is not managed", m));
- rv = FALSE;
- rw_wlock(&pvh_global_lock);
- TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
- if (PV_PMAP(pv) == pmap) {
- rv = TRUE;
- break;
- }
- loops++;
- if (loops >= 16)
- break;
- }
- if (!rv && loops < 16 && (m->flags & PG_FICTITIOUS) == 0) {
- pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
- TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
- if (PV_PMAP(pv) == pmap) {
- rv = TRUE;
- break;
- }
- loops++;
- if (loops >= 16)
- break;
+ rw_assert(&pvh_global_lock, RA_WLOCKED);
+ sched_pin();
+ TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte1 = pte1_load(pmap_pte1(pmap, pv->pv_va));
+ if (pte1_is_section(pte1)) {
+ if (pte1_is_wired(pte1))
+ count++;
+ } else {
+ KASSERT(pte1_is_link(pte1),
+ ("%s: pte1 %#x is not link", __func__, pte1));
+ pte2 = pte2_load(pmap_pte2_quick(pmap, pv->pv_va));
+ if (pte2_is_wired(pte2))
+ count++;
}
+ PMAP_UNLOCK(pmap);
}
- rw_wunlock(&pvh_global_lock);
- return (rv);
+ sched_unpin();
+ return (count);
}
/*
@@ -4838,62 +4876,136 @@ pmap_page_wired_mappings(vm_page_t m)
rw_wlock(&pvh_global_lock);
count = pmap_pvh_wired_mappings(&m->md, count);
if ((m->flags & PG_FICTITIOUS) == 0) {
- count = pmap_pvh_wired_mappings(pa_to_pvh(VM_PAGE_TO_PHYS(m)),
- count);
+ count = pmap_pvh_wired_mappings(pa_to_pvh(VM_PAGE_TO_PHYS(m)),
+ count);
}
rw_wunlock(&pvh_global_lock);
return (count);
}
/*
- * pmap_pvh_wired_mappings:
- *
- * Return the updated number "count" of managed mappings that are wired.
+ * Returns TRUE if any of the given mappings were used to modify
+ * physical memory. Otherwise, returns FALSE. Both page and 1mpage
+ * mappings are supported.
*/
-static int
-pmap_pvh_wired_mappings(struct md_page *pvh, int count)
+static boolean_t
+pmap_is_modified_pvh(struct md_page *pvh)
{
pv_entry_t pv;
+ pt1_entry_t pte1;
+ pt2_entry_t pte2;
+ pmap_t pmap;
+ boolean_t rv;
rw_assert(&pvh_global_lock, RA_WLOCKED);
- TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
- if ((pv->pv_flags & PVF_WIRED) != 0)
- count++;
+ rv = FALSE;
+ sched_pin();
+ TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte1 = pte1_load(pmap_pte1(pmap, pv->pv_va));
+ if (pte1_is_section(pte1)) {
+ rv = pte1_is_dirty(pte1);
+ } else {
+ KASSERT(pte1_is_link(pte1),
+ ("%s: pte1 %#x is not link", __func__, pte1));
+ pte2 = pte2_load(pmap_pte2_quick(pmap, pv->pv_va));
+ rv = pte2_is_dirty(pte2);
+ }
+ PMAP_UNLOCK(pmap);
+ if (rv)
+ break;
}
- return (count);
+ sched_unpin();
+ return (rv);
+}
+
+/*
+ * pmap_is_modified:
+ *
+ * Return whether or not the specified physical page was modified
+ * in any physical maps.
+ */
+boolean_t
+pmap_is_modified(vm_page_t m)
+{
+ boolean_t rv;
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("%s: page %p is not managed", __func__, m));
+
+ /*
+ * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
+ * concurrently set while the object is locked. Thus, if PGA_WRITEABLE
+ * is clear, no PTE2s can have PG_M set.
+ */
+ VM_OBJECT_ASSERT_WLOCKED(m->object);
+ if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
+ return (FALSE);
+ rw_wlock(&pvh_global_lock);
+ rv = pmap_is_modified_pvh(&m->md) ||
+ ((m->flags & PG_FICTITIOUS) == 0 &&
+ pmap_is_modified_pvh(pa_to_pvh(VM_PAGE_TO_PHYS(m))));
+ rw_wunlock(&pvh_global_lock);
+ return (rv);
+}
+
+/*
+ * pmap_is_prefaultable:
+ *
+ * Return whether or not the specified virtual address is eligible
+ * for prefault.
+ */
+boolean_t
+pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr)
+{
+ pt1_entry_t pte1;
+ pt2_entry_t pte2;
+ boolean_t rv;
+
+ rv = FALSE;
+ PMAP_LOCK(pmap);
+ pte1 = pte1_load(pmap_pte1(pmap, addr));
+ if (pte1_is_link(pte1)) {
+ pte2 = pte2_load(pt2map_entry(addr));
+ rv = !pte2_is_valid(pte2) ;
+ }
+ PMAP_UNLOCK(pmap);
+ return (rv);
}
/*
- * Returns TRUE if any of the given mappings were referenced and FALSE
- * otherwise. Both page and section mappings are supported.
+ * Returns TRUE if any of the given mappings were referenced and FALSE
+ * otherwise. Both page and 1mpage mappings are supported.
*/
static boolean_t
pmap_is_referenced_pvh(struct md_page *pvh)
{
- struct l2_bucket *l2b;
+
pv_entry_t pv;
- pd_entry_t *pl1pd;
- pt_entry_t *ptep;
+ pt1_entry_t pte1;
+ pt2_entry_t pte2;
pmap_t pmap;
boolean_t rv;
rw_assert(&pvh_global_lock, RA_WLOCKED);
rv = FALSE;
- TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
+ sched_pin();
+ TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
pmap = PV_PMAP(pv);
PMAP_LOCK(pmap);
- pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(pv->pv_va)];
- if ((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO)
- rv = L1_S_REFERENCED(*pl1pd);
- else {
- l2b = pmap_get_l2_bucket(pmap, pv->pv_va);
- ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
- rv = L2_S_REFERENCED(*ptep);
+ pte1 = pte1_load(pmap_pte1(pmap, pv->pv_va));
+ if (pte1_is_section(pte1)) {
+ rv = (pte1 & (PTE1_A | PTE1_V)) == (PTE1_A | PTE1_V);
+ } else {
+ pte2 = pte2_load(pmap_pte2_quick(pmap, pv->pv_va));
+ rv = (pte2 & (PTE2_A | PTE2_V)) == (PTE2_A | PTE2_V);
}
PMAP_UNLOCK(pmap);
if (rv)
break;
}
+ sched_unpin();
return (rv);
}
@@ -4909,7 +5021,7 @@ pmap_is_referenced(vm_page_t m)
boolean_t rv;
KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("pmap_is_referenced: page %p is not managed", m));
+ ("%s: page %p is not managed", __func__, m));
rw_wlock(&pvh_global_lock);
rv = pmap_is_referenced_pvh(&m->md) ||
((m->flags & PG_FICTITIOUS) == 0 &&
@@ -4918,190 +5030,382 @@ pmap_is_referenced(vm_page_t m)
return (rv);
}
+#define PMAP_TS_REFERENCED_MAX 5
+
/*
* pmap_ts_referenced:
*
- * Return the count of reference bits for a page, clearing all of them.
+ * Return a count of reference bits for a page, clearing those bits.
+ * It is not necessary for every reference bit to be cleared, but it
+ * is necessary that 0 only be returned when there are truly no
+ * reference bits set.
+ *
+ * XXX: The exact number of bits to check and clear is a matter that
+ * should be tested and standardized at some point in the future for
+ * optimal aging of shared pages.
*/
int
pmap_ts_referenced(vm_page_t m)
{
+ struct md_page *pvh;
+ pv_entry_t pv, pvf;
+ pmap_t pmap;
+ pt1_entry_t *pte1p, opte1;
+ pt2_entry_t *pte2p;
+ vm_paddr_t pa;
+ int rtval = 0;
KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("pmap_ts_referenced: page %p is not managed", m));
- return (pmap_clearbit(m, PVF_REF));
+ ("%s: page %p is not managed", __func__, m));
+ pa = VM_PAGE_TO_PHYS(m);
+ pvh = pa_to_pvh(pa);
+ rw_wlock(&pvh_global_lock);
+ sched_pin();
+ if ((m->flags & PG_FICTITIOUS) != 0 ||
+ (pvf = TAILQ_FIRST(&pvh->pv_list)) == NULL)
+ goto small_mappings;
+ pv = pvf;
+ do {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte1p = pmap_pte1(pmap, pv->pv_va);
+ opte1 = pte1_load(pte1p);
+ if ((opte1 & PTE1_A) != 0) {
+ /*
+ * Since this reference bit is shared by 256 4KB pages,
+ * it should not be cleared every time it is tested.
+ * Apply a simple "hash" function on the physical page
+ * number, the virtual section number, and the pmap
+ * address to select one 4KB page out of the 256
+ * on which testing the reference bit will result
+ * in clearing that bit. This function is designed
+ * to avoid the selection of the same 4KB page
+ * for every 1MB page mapping.
+ *
+ * On demotion, a mapping that hasn't been referenced
+ * is simply destroyed. To avoid the possibility of a
+ * subsequent page fault on a demoted wired mapping,
+ * always leave its reference bit set. Moreover,
+ * since the section is wired, the current state of
+ * its reference bit won't affect page replacement.
+ */
+ if ((((pa >> PAGE_SHIFT) ^ (pv->pv_va >> PTE1_SHIFT) ^
+ (uintptr_t)pmap) & (NPTE2_IN_PG - 1)) == 0 &&
+ !pte1_is_wired(opte1)) {
+ pte1_clear_bit(pte1p, PTE1_A);
+ pmap_tlb_flush(pmap, pv->pv_va);
+ }
+ rtval++;
+ }
+ PMAP_UNLOCK(pmap);
+ /* Rotate the PV list if it has more than one entry. */
+ if (TAILQ_NEXT(pv, pv_next) != NULL) {
+ TAILQ_REMOVE(&pvh->pv_list, pv, pv_next);
+ TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next);
+ }
+ if (rtval >= PMAP_TS_REFERENCED_MAX)
+ goto out;
+ } while ((pv = TAILQ_FIRST(&pvh->pv_list)) != pvf);
+small_mappings:
+ if ((pvf = TAILQ_FIRST(&m->md.pv_list)) == NULL)
+ goto out;
+ pv = pvf;
+ do {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte1p = pmap_pte1(pmap, pv->pv_va);
+ KASSERT(pte1_is_link(pte1_load(pte1p)),
+ ("%s: not found a link in page %p's pv list", __func__, m));
+
+ pte2p = pmap_pte2_quick(pmap, pv->pv_va);
+ if ((pte2_load(pte2p) & PTE2_A) != 0) {
+ pte2_clear_bit(pte2p, PTE2_A);
+ pmap_tlb_flush(pmap, pv->pv_va);
+ rtval++;
+ }
+ PMAP_UNLOCK(pmap);
+ /* Rotate the PV list if it has more than one entry. */
+ if (TAILQ_NEXT(pv, pv_next) != NULL) {
+ TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
+ TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
+ }
+ } while ((pv = TAILQ_FIRST(&m->md.pv_list)) != pvf && rtval <
+ PMAP_TS_REFERENCED_MAX);
+out:
+ sched_unpin();
+ rw_wunlock(&pvh_global_lock);
+ return (rtval);
}
/*
- * Returns TRUE if any of the given mappings were used to modify
- * physical memory. Otherwise, returns FALSE. Both page and 1MB section
- * mappings are supported.
+ * Clear the wired attribute from the mappings for the specified range of
+ * addresses in the given pmap. Every valid mapping within that range
+ * must have the wired attribute set. In contrast, invalid mappings
+ * cannot have the wired attribute set, so they are ignored.
+ *
+ * The wired attribute of the page table entry is not a hardware feature,
+ * so there is no need to invalidate any TLB entries.
*/
-static boolean_t
-pmap_is_modified_pvh(struct md_page *pvh)
+void
+pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
{
- pd_entry_t *pl1pd;
- struct l2_bucket *l2b;
- pv_entry_t pv;
- pt_entry_t *ptep;
- pmap_t pmap;
- boolean_t rv;
+ vm_offset_t nextva;
+ pt1_entry_t *pte1p, pte1;
+ pt2_entry_t *pte2p, pte2;
+ boolean_t pv_lists_locked;
- rw_assert(&pvh_global_lock, RA_WLOCKED);
- rv = FALSE;
+ if (pmap_is_current(pmap))
+ pv_lists_locked = FALSE;
+ else {
+ pv_lists_locked = TRUE;
+resume:
+ rw_wlock(&pvh_global_lock);
+ sched_pin();
+ }
+ PMAP_LOCK(pmap);
+ for (; sva < eva; sva = nextva) {
+ nextva = pte1_trunc(sva + PTE1_SIZE);
+ if (nextva < sva)
+ nextva = eva;
- TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
- pmap = PV_PMAP(pv);
- PMAP_LOCK(pmap);
- pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(pv->pv_va)];
- if ((*pl1pd & L1_TYPE_MASK) == L1_S_PROTO)
- rv = L1_S_WRITABLE(*pl1pd);
- else {
- l2b = pmap_get_l2_bucket(pmap, pv->pv_va);
- ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
- rv = L2_S_WRITABLE(*ptep);
+ pte1p = pmap_pte1(pmap, sva);
+ pte1 = pte1_load(pte1p);
+
+ /*
+ * Weed out invalid mappings. Note: we assume that L1 page
+ * page table is always allocated, and in kernel virtual.
+ */
+ if (pte1 == 0)
+ continue;
+
+ if (pte1_is_section(pte1)) {
+ if (!pte1_is_wired(pte1))
+ panic("%s: pte1 %#x not wired", __func__, pte1);
+
+ /*
+ * Are we unwiring the entire large page? If not,
+ * demote the mapping and fall through.
+ */
+ if (sva + PTE1_SIZE == nextva && eva >= nextva) {
+ pte1_clear_bit(pte1p, PTE1_W);
+ pmap->pm_stats.wired_count -= PTE1_SIZE /
+ PAGE_SIZE;
+ continue;
+ } else {
+ if (!pv_lists_locked) {
+ pv_lists_locked = TRUE;
+ if (!rw_try_wlock(&pvh_global_lock)) {
+ PMAP_UNLOCK(pmap);
+ /* Repeat sva. */
+ goto resume;
+ }
+ sched_pin();
+ }
+ if (!pmap_demote_pte1(pmap, pte1p, sva))
+ panic("%s: demotion failed", __func__);
+#ifdef INVARIANTS
+ else {
+ /* Update pte1 after demotion */
+ pte1 = pte1_load(pte1p);
+ }
+#endif
+ }
}
- PMAP_UNLOCK(pmap);
- if (rv)
- break;
- }
- return (rv);
+ KASSERT(pte1_is_link(pte1), ("%s: pmap %p va %#x pte1 %#x at %p"
+ " is not link", __func__, pmap, sva, pte1, pte1p));
+
+ /*
+ * Limit our scan to either the end of the va represented
+ * by the current L2 page table page, or to the end of the
+ * range being protected.
+ */
+ if (nextva > eva)
+ nextva = eva;
+
+ for (pte2p = pmap_pte2_quick(pmap, sva); sva != nextva; pte2p++,
+ sva += PAGE_SIZE) {
+ pte2 = pte2_load(pte2p);
+ if (!pte2_is_valid(pte2))
+ continue;
+ if (!pte2_is_wired(pte2))
+ panic("%s: pte2 %#x is missing PTE2_W",
+ __func__, pte2);
+
+ /*
+ * PTE2_W must be cleared atomically. Although the pmap
+ * lock synchronizes access to PTE2_W, another processor
+ * could be changing PTE2_NM and/or PTE2_A concurrently.
+ */
+ pte2_clear_bit(pte2p, PTE2_W);
+ pmap->pm_stats.wired_count--;
+ }
+ }
+ if (pv_lists_locked) {
+ sched_unpin();
+ rw_wunlock(&pvh_global_lock);
+ }
+ PMAP_UNLOCK(pmap);
}
-boolean_t
-pmap_is_modified(vm_page_t m)
+/*
+ * Clear the write and modified bits in each of the given page's mappings.
+ */
+void
+pmap_remove_write(vm_page_t m)
{
- boolean_t rv;
+ struct md_page *pvh;
+ pv_entry_t next_pv, pv;
+ pmap_t pmap;
+ pt1_entry_t *pte1p;
+ pt2_entry_t *pte2p, opte2;
+ vm_offset_t va;
KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("pmap_is_modified: page %p is not managed", m));
+ ("%s: page %p is not managed", __func__, m));
+
/*
* If the page is not exclusive busied, then PGA_WRITEABLE cannot be
- * concurrently set while the object is locked. Thus, if PGA_WRITEABLE
- * is clear, no PTEs can have APX cleared.
+ * set by another thread while the object is locked. Thus,
+ * if PGA_WRITEABLE is clear, no page table entries need updating.
*/
VM_OBJECT_ASSERT_WLOCKED(m->object);
if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
- return (FALSE);
+ return;
rw_wlock(&pvh_global_lock);
- rv = pmap_is_modified_pvh(&m->md) ||
- ((m->flags & PG_FICTITIOUS) == 0 &&
- pmap_is_modified_pvh(pa_to_pvh(VM_PAGE_TO_PHYS(m))));
+ sched_pin();
+ if ((m->flags & PG_FICTITIOUS) != 0)
+ goto small_mappings;
+ pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) {
+ va = pv->pv_va;
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte1p = pmap_pte1(pmap, va);
+ if (!(pte1_load(pte1p) & PTE1_RO))
+ (void)pmap_demote_pte1(pmap, pte1p, va);
+ PMAP_UNLOCK(pmap);
+ }
+small_mappings:
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte1p = pmap_pte1(pmap, pv->pv_va);
+ KASSERT(!pte1_is_section(pte1_load(pte1p)), ("%s: found"
+ " a section in page %p's pv list", __func__, m));
+ pte2p = pmap_pte2_quick(pmap, pv->pv_va);
+retry:
+ opte2 = pte2_load(pte2p);
+ if (!(opte2 & PTE2_RO)) {
+ if (!pte2_cmpset(pte2p, opte2,
+ opte2 | (PTE2_RO | PTE2_NM)))
+ goto retry;
+ if (pte2_is_dirty(opte2))
+ vm_page_dirty(m);
+ pmap_tlb_flush(pmap, pv->pv_va);
+ }
+ PMAP_UNLOCK(pmap);
+ }
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ sched_unpin();
rw_wunlock(&pvh_global_lock);
- return (rv);
}
/*
* Apply the given advice to the specified range of addresses within the
* given pmap. Depending on the advice, clear the referenced and/or
- * modified flags in each mapping.
+ * modified flags in each mapping and set the mapped page's dirty field.
*/
void
pmap_advise(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, int advice)
{
- struct l2_bucket *l2b;
- struct pv_entry *pve;
- pd_entry_t l1pd;
- pt_entry_t *ptep, opte, pte;
- vm_offset_t next_bucket;
+ pt1_entry_t *pte1p, opte1;
+ pt2_entry_t *pte2p, pte2;
+ vm_offset_t pdnxt;
vm_page_t m;
+ boolean_t pv_lists_locked;
if (advice != MADV_DONTNEED && advice != MADV_FREE)
return;
- rw_wlock(&pvh_global_lock);
+ if (pmap_is_current(pmap))
+ pv_lists_locked = FALSE;
+ else {
+ pv_lists_locked = TRUE;
+resume:
+ rw_wlock(&pvh_global_lock);
+ sched_pin();
+ }
PMAP_LOCK(pmap);
- for (; sva < eva; sva = next_bucket) {
- next_bucket = L2_NEXT_BUCKET(sva);
- if (next_bucket < sva)
- next_bucket = eva;
- l1pd = pmap->pm_l1->l1_kva[L1_IDX(sva)];
- if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
- if (pmap == pmap_kernel())
+ for (; sva < eva; sva = pdnxt) {
+ pdnxt = pte1_trunc(sva + PTE1_SIZE);
+ if (pdnxt < sva)
+ pdnxt = eva;
+ pte1p = pmap_pte1(pmap, sva);
+ opte1 = pte1_load(pte1p);
+ if (!pte1_is_valid(opte1)) /* XXX */
+ continue;
+ else if (pte1_is_section(opte1)) {
+ if (!pte1_is_managed(opte1))
continue;
- if (!pmap_demote_section(pmap, sva)) {
+ if (!pv_lists_locked) {
+ pv_lists_locked = TRUE;
+ if (!rw_try_wlock(&pvh_global_lock)) {
+ PMAP_UNLOCK(pmap);
+ goto resume;
+ }
+ sched_pin();
+ }
+ if (!pmap_demote_pte1(pmap, pte1p, sva)) {
/*
* The large page mapping was destroyed.
*/
continue;
}
+
/*
* Unless the page mappings are wired, remove the
* mapping to a single page so that a subsequent
- * access may repromote. Since the underlying
- * l2_bucket is fully populated, this removal
- * never frees an entire l2_bucket.
+ * access may repromote. Since the underlying L2 page
+ * table is fully populated, this removal never
+ * frees a L2 page table page.
*/
- l2b = pmap_get_l2_bucket(pmap, sva);
- KASSERT(l2b != NULL,
- ("pmap_advise: no l2 bucket for "
- "va 0x%#x, pmap 0x%p", sva, pmap));
- ptep = &l2b->l2b_kva[l2pte_index(sva)];
- opte = *ptep;
- m = PHYS_TO_VM_PAGE(l2pte_pa(*ptep));
- KASSERT(m != NULL,
- ("pmap_advise: no vm_page for demoted superpage"));
- pve = pmap_find_pv(&m->md, pmap, sva);
- KASSERT(pve != NULL,
- ("pmap_advise: no PV entry for managed mapping"));
- if ((pve->pv_flags & PVF_WIRED) == 0) {
- pmap_free_l2_bucket(pmap, l2b, 1);
- pve = pmap_remove_pv(m, pmap, sva);
- pmap_free_pv_entry(pmap, pve);
- *ptep = 0;
- PTE_SYNC(ptep);
- if (pmap_is_current(pmap)) {
- if (PTE_BEEN_EXECD(opte))
- cpu_tlb_flushID_SE(sva);
- else if (PTE_BEEN_REFD(opte))
- cpu_tlb_flushD_SE(sva);
- }
+ if (!pte1_is_wired(opte1)) {
+ pte2p = pmap_pte2_quick(pmap, sva);
+ KASSERT(pte2_is_valid(pte2_load(pte2p)),
+ ("%s: invalid PTE2", __func__));
+ pmap_remove_pte2(pmap, pte2p, sva, NULL);
}
}
- if (next_bucket > eva)
- next_bucket = eva;
- l2b = pmap_get_l2_bucket(pmap, sva);
- if (l2b == NULL)
- continue;
- for (ptep = &l2b->l2b_kva[l2pte_index(sva)];
- sva != next_bucket; ptep++, sva += PAGE_SIZE) {
- opte = pte = *ptep;
- if ((opte & L2_S_PROTO) == 0)
- continue;
- m = PHYS_TO_VM_PAGE(l2pte_pa(opte));
- if (m == NULL || (m->oflags & VPO_UNMANAGED) != 0)
+ if (pdnxt > eva)
+ pdnxt = eva;
+ for (pte2p = pmap_pte2_quick(pmap, sva); sva != pdnxt; pte2p++,
+ sva += PAGE_SIZE) {
+ pte2 = pte2_load(pte2p);
+ if (!pte2_is_valid(pte2) || !pte2_is_managed(pte2))
continue;
- else if (L2_S_WRITABLE(opte)) {
+ else if (pte2_is_dirty(pte2)) {
if (advice == MADV_DONTNEED) {
/*
- * Don't need to mark the page
- * dirty as it was already marked as
- * such in pmap_fault_fixup() or
- * pmap_enter_locked().
- * Just clear the state.
+ * Future calls to pmap_is_modified()
+ * can be avoided by making the page
+ * dirty now.
*/
- } else
- pte |= L2_APX;
-
- pte &= ~L2_S_REF;
- *ptep = pte;
- PTE_SYNC(ptep);
- } else if (L2_S_REFERENCED(opte)) {
- pte &= ~L2_S_REF;
- *ptep = pte;
- PTE_SYNC(ptep);
- } else
+ m = PHYS_TO_VM_PAGE(pte2_pa(pte2));
+ vm_page_dirty(m);
+ }
+ pte2_set_bit(pte2p, PTE2_NM);
+ pte2_clear_bit(pte2p, PTE2_A);
+ } else if ((pte2 & PTE2_A) != 0)
+ pte2_clear_bit(pte2p, PTE2_A);
+ else
continue;
- if (pmap_is_current(pmap)) {
- if (PTE_BEEN_EXECD(opte))
- cpu_tlb_flushID_SE(sva);
- else if (PTE_BEEN_REFD(opte))
- cpu_tlb_flushD_SE(sva);
- }
+ pmap_tlb_flush(pmap, sva);
}
}
- cpu_cpwait();
- rw_wunlock(&pvh_global_lock);
+ if (pv_lists_locked) {
+ sched_unpin();
+ rw_wunlock(&pvh_global_lock);
+ }
PMAP_UNLOCK(pmap);
}
@@ -5111,102 +5415,602 @@ pmap_advise(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, int advice)
void
pmap_clear_modify(vm_page_t m)
{
+ struct md_page *pvh;
+ pv_entry_t next_pv, pv;
+ pmap_t pmap;
+ pt1_entry_t *pte1p, opte1;
+ pt2_entry_t *pte2p, opte2;
+ vm_offset_t va;
KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("pmap_clear_modify: page %p is not managed", m));
+ ("%s: page %p is not managed", __func__, m));
VM_OBJECT_ASSERT_WLOCKED(m->object);
KASSERT(!vm_page_xbusied(m),
- ("pmap_clear_modify: page %p is exclusive busied", m));
+ ("%s: page %p is exclusive busy", __func__, m));
/*
- * If the page is not PGA_WRITEABLE, then no mappings can be modified.
- * If the object containing the page is locked and the page is not
- * exclusive busied, then PGA_WRITEABLE cannot be concurrently set.
+ * If the page is not PGA_WRITEABLE, then no PTE2s can have PTE2_NM
+ * cleared. If the object containing the page is locked and the page
+ * is not exclusive busied, then PGA_WRITEABLE cannot be concurrently
+ * set.
*/
- if ((m->aflags & PGA_WRITEABLE) == 0)
+ if ((m->flags & PGA_WRITEABLE) == 0)
return;
- if (pmap_is_modified(m))
- pmap_clearbit(m, PVF_MOD);
+ rw_wlock(&pvh_global_lock);
+ sched_pin();
+ if ((m->flags & PG_FICTITIOUS) != 0)
+ goto small_mappings;
+ pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) {
+ va = pv->pv_va;
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte1p = pmap_pte1(pmap, va);
+ opte1 = pte1_load(pte1p);
+ if (!(opte1 & PTE1_RO)) {
+ if (pmap_demote_pte1(pmap, pte1p, va) &&
+ !pte1_is_wired(opte1)) {
+ /*
+ * Write protect the mapping to a
+ * single page so that a subsequent
+ * write access may repromote.
+ */
+ va += VM_PAGE_TO_PHYS(m) - pte1_pa(opte1);
+ pte2p = pmap_pte2_quick(pmap, va);
+ opte2 = pte2_load(pte2p);
+ if ((opte2 & PTE2_V)) {
+ pte2_set_bit(pte2p, PTE2_NM | PTE2_RO);
+ vm_page_dirty(m);
+ pmap_tlb_flush(pmap, va);
+ }
+ }
+ }
+ PMAP_UNLOCK(pmap);
+ }
+small_mappings:
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte1p = pmap_pte1(pmap, pv->pv_va);
+ KASSERT(!pte1_is_section(pte1_load(pte1p)), ("%s: found"
+ " a section in page %p's pv list", __func__, m));
+ pte2p = pmap_pte2_quick(pmap, pv->pv_va);
+ if (pte2_is_dirty(pte2_load(pte2p))) {
+ pte2_set_bit(pte2p, PTE2_NM);
+ pmap_tlb_flush(pmap, pv->pv_va);
+ }
+ PMAP_UNLOCK(pmap);
+ }
+ sched_unpin();
+ rw_wunlock(&pvh_global_lock);
}
/*
- * Clear the write and modified bits in each of the given page's mappings.
+ * Sets the memory attribute for the specified page.
*/
void
-pmap_remove_write(vm_page_t m)
+pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma)
{
- KASSERT((m->oflags & VPO_UNMANAGED) == 0,
- ("pmap_remove_write: page %p is not managed", m));
+ struct sysmaps *sysmaps;
+ vm_memattr_t oma;
+ vm_paddr_t pa;
+
+ oma = m->md.pat_mode;
+ m->md.pat_mode = ma;
+ CTR5(KTR_PMAP, "%s: page %p - 0x%08X oma: %d, ma: %d", __func__, m,
+ VM_PAGE_TO_PHYS(m), oma, ma);
+ if ((m->flags & PG_FICTITIOUS) != 0)
+ return;
+#if 0
/*
- * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
- * set by another thread while the object is locked. Thus,
- * if PGA_WRITEABLE is clear, no page table entries need updating.
+ * If "m" is a normal page, flush it from the cache.
+ *
+ * First, try to find an existing mapping of the page by sf
+ * buffer. sf_buf_invalidate_cache() modifies mapping and
+ * flushes the cache.
*/
- VM_OBJECT_ASSERT_WLOCKED(m->object);
- if (vm_page_xbusied(m) || (m->aflags & PGA_WRITEABLE) != 0)
- pmap_clearbit(m, PVF_WRITE);
+ if (sf_buf_invalidate_cache(m, oma))
+ return;
+#endif
+ /*
+ * If page is not mapped by sf buffer, map the page
+ * transient and do invalidation.
+ */
+ if (ma != oma) {
+ pa = VM_PAGE_TO_PHYS(m);
+ sched_pin();
+ sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
+ mtx_lock(&sysmaps->lock);
+ if (*sysmaps->CMAP2)
+ panic("%s: CMAP2 busy", __func__);
+ pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW,
+ vm_memattr_to_pte2(ma)));
+ dcache_wbinv_poc((vm_offset_t)sysmaps->CADDR2, pa, PAGE_SIZE);
+ pte2_clear(sysmaps->CMAP2);
+ tlb_flush((vm_offset_t)sysmaps->CADDR2);
+ sched_unpin();
+ mtx_unlock(&sysmaps->lock);
+ }
+}
+
+/*
+ * Miscellaneous support routines follow
+ */
+
+/*
+ * Returns TRUE if the given page is mapped individually or as part of
+ * a 1mpage. Otherwise, returns FALSE.
+ */
+boolean_t
+pmap_page_is_mapped(vm_page_t m)
+{
+ boolean_t rv;
+
+ if ((m->oflags & VPO_UNMANAGED) != 0)
+ return (FALSE);
+ rw_wlock(&pvh_global_lock);
+ rv = !TAILQ_EMPTY(&m->md.pv_list) ||
+ ((m->flags & PG_FICTITIOUS) == 0 &&
+ !TAILQ_EMPTY(&pa_to_pvh(VM_PAGE_TO_PHYS(m))->pv_list));
+ rw_wunlock(&pvh_global_lock);
+ return (rv);
+}
+
+/*
+ * Returns true if the pmap's pv is one of the first
+ * 16 pvs linked to from this page. This count may
+ * be changed upwards or downwards in the future; it
+ * is only necessary that true be returned for a small
+ * subset of pmaps for proper page aging.
+ */
+boolean_t
+pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
+{
+ struct md_page *pvh;
+ pv_entry_t pv;
+ int loops = 0;
+ boolean_t rv;
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("%s: page %p is not managed", __func__, m));
+ rv = FALSE;
+ rw_wlock(&pvh_global_lock);
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
+ if (PV_PMAP(pv) == pmap) {
+ rv = TRUE;
+ break;
+ }
+ loops++;
+ if (loops >= 16)
+ break;
+ }
+ if (!rv && loops < 16 && (m->flags & PG_FICTITIOUS) == 0) {
+ pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
+ if (PV_PMAP(pv) == pmap) {
+ rv = TRUE;
+ break;
+ }
+ loops++;
+ if (loops >= 16)
+ break;
+ }
+ }
+ rw_wunlock(&pvh_global_lock);
+ return (rv);
+}
+
+/*
+ * pmap_zero_page zeros the specified hardware page by mapping
+ * the page into KVM and using bzero to clear its contents.
+ */
+void
+pmap_zero_page(vm_page_t m)
+{
+ struct sysmaps *sysmaps;
+
+ sched_pin();
+ sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
+ mtx_lock(&sysmaps->lock);
+ if (pte2_load(sysmaps->CMAP2) != 0)
+ panic("%s: CMAP2 busy", __func__);
+ pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW,
+ vm_page_pte2_attr(m)));
+ pagezero(sysmaps->CADDR2);
+ pte2_clear(sysmaps->CMAP2);
+ tlb_flush((vm_offset_t)sysmaps->CADDR2);
+ sched_unpin();
+ mtx_unlock(&sysmaps->lock);
+}
+
+/*
+ * pmap_zero_page_area zeros the specified hardware page by mapping
+ * the page into KVM and using bzero to clear its contents.
+ *
+ * off and size may not cover an area beyond a single hardware page.
+ */
+void
+pmap_zero_page_area(vm_page_t m, int off, int size)
+{
+ struct sysmaps *sysmaps;
+
+ sched_pin();
+ sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
+ mtx_lock(&sysmaps->lock);
+ if (pte2_load(sysmaps->CMAP2) != 0)
+ panic("%s: CMAP2 busy", __func__);
+ pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW,
+ vm_page_pte2_attr(m)));
+ if (off == 0 && size == PAGE_SIZE)
+ pagezero(sysmaps->CADDR2);
+ else
+ bzero(sysmaps->CADDR2 + off, size);
+ pte2_clear(sysmaps->CMAP2);
+ tlb_flush((vm_offset_t)sysmaps->CADDR2);
+ sched_unpin();
+ mtx_unlock(&sysmaps->lock);
+}
+
+/*
+ * pmap_zero_page_idle zeros the specified hardware page by mapping
+ * the page into KVM and using bzero to clear its contents. This
+ * is intended to be called from the vm_pagezero process only and
+ * outside of Giant.
+ */
+void
+pmap_zero_page_idle(vm_page_t m)
+{
+
+ if (pte2_load(CMAP3) != 0)
+ panic("%s: CMAP3 busy", __func__);
+ sched_pin();
+ pte2_store(CMAP3, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW,
+ vm_page_pte2_attr(m)));
+ pagezero(CADDR3);
+ pte2_clear(CMAP3);
+ tlb_flush((vm_offset_t)CADDR3);
+ sched_unpin();
+}
+
+/*
+ * pmap_copy_page copies the specified (machine independent)
+ * page by mapping the page into virtual memory and using
+ * bcopy to copy the page, one machine dependent page at a
+ * time.
+ */
+void
+pmap_copy_page(vm_page_t src, vm_page_t dst)
+{
+ struct sysmaps *sysmaps;
+
+ sched_pin();
+ sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
+ mtx_lock(&sysmaps->lock);
+ if (pte2_load(sysmaps->CMAP1) != 0)
+ panic("%s: CMAP1 busy", __func__);
+ if (pte2_load(sysmaps->CMAP2) != 0)
+ panic("%s: CMAP2 busy", __func__);
+ pte2_store(sysmaps->CMAP1, PTE2_KERN_NG(VM_PAGE_TO_PHYS(src),
+ PTE2_AP_KR | PTE2_NM, vm_page_pte2_attr(src)));
+ pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(dst),
+ PTE2_AP_KRW, vm_page_pte2_attr(dst)));
+ bcopy(sysmaps->CADDR1, sysmaps->CADDR2, PAGE_SIZE);
+ pte2_clear(sysmaps->CMAP1);
+ tlb_flush((vm_offset_t)sysmaps->CADDR1);
+ pte2_clear(sysmaps->CMAP2);
+ tlb_flush((vm_offset_t)sysmaps->CADDR2);
+ sched_unpin();
+ mtx_unlock(&sysmaps->lock);
+}
+
+int unmapped_buf_allowed = 1;
+
+void
+pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
+ vm_offset_t b_offset, int xfersize)
+{
+ struct sysmaps *sysmaps;
+ vm_page_t a_pg, b_pg;
+ char *a_cp, *b_cp;
+ vm_offset_t a_pg_offset, b_pg_offset;
+ int cnt;
+
+ sched_pin();
+ sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
+ mtx_lock(&sysmaps->lock);
+ if (*sysmaps->CMAP1 != 0)
+ panic("pmap_copy_pages: CMAP1 busy");
+ if (*sysmaps->CMAP2 != 0)
+ panic("pmap_copy_pages: CMAP2 busy");
+ while (xfersize > 0) {
+ a_pg = ma[a_offset >> PAGE_SHIFT];
+ a_pg_offset = a_offset & PAGE_MASK;
+ cnt = min(xfersize, PAGE_SIZE - a_pg_offset);
+ b_pg = mb[b_offset >> PAGE_SHIFT];
+ b_pg_offset = b_offset & PAGE_MASK;
+ cnt = min(cnt, PAGE_SIZE - b_pg_offset);
+ pte2_store(sysmaps->CMAP1, PTE2_KERN_NG(VM_PAGE_TO_PHYS(a_pg),
+ PTE2_AP_KR | PTE2_NM, vm_page_pte2_attr(a_pg)));
+ tlb_flush_local((vm_offset_t)sysmaps->CADDR1);
+ pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(b_pg),
+ PTE2_AP_KRW, vm_page_pte2_attr(b_pg)));
+ tlb_flush_local((vm_offset_t)sysmaps->CADDR2);
+ a_cp = sysmaps->CADDR1 + a_pg_offset;
+ b_cp = sysmaps->CADDR2 + b_pg_offset;
+ bcopy(a_cp, b_cp, cnt);
+ a_offset += cnt;
+ b_offset += cnt;
+ xfersize -= cnt;
+ }
+ pte2_clear(sysmaps->CMAP1);
+ tlb_flush((vm_offset_t)sysmaps->CADDR1);
+ pte2_clear(sysmaps->CMAP2);
+ tlb_flush((vm_offset_t)sysmaps->CADDR2);
+ sched_unpin();
+ mtx_unlock(&sysmaps->lock);
+}
+
+vm_offset_t
+pmap_quick_enter_page(vm_page_t m)
+{
+ pt2_entry_t *pte2p;
+ vm_offset_t qmap_addr;
+
+ critical_enter();
+ qmap_addr = PCPU_GET(qmap_addr);
+ pte2p = pt2map_entry(qmap_addr);
+
+ KASSERT(pte2_load(pte2p) == 0, ("%s: PTE2 busy", __func__));
+
+ pte2_store(pte2p, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW,
+ vm_page_pte2_attr(m)));
+ return (qmap_addr);
}
+void
+pmap_quick_remove_page(vm_offset_t addr)
+{
+ pt2_entry_t *pte2p;
+ vm_offset_t qmap_addr;
+
+ qmap_addr = PCPU_GET(qmap_addr);
+ pte2p = pt2map_entry(qmap_addr);
+
+ KASSERT(addr == qmap_addr, ("%s: invalid address", __func__));
+ KASSERT(pte2_load(pte2p) != 0, ("%s: PTE2 not in use", __func__));
+
+ pte2_clear(pte2p);
+ tlb_flush(qmap_addr);
+ critical_exit();
+}
/*
- * perform the pmap work for mincore
+ * Copy the range specified by src_addr/len
+ * from the source map to the range dst_addr/len
+ * in the destination map.
+ *
+ * This routine is only advisory and need not do anything.
+ */
+void
+pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
+ vm_offset_t src_addr)
+{
+ struct spglist free;
+ vm_offset_t addr;
+ vm_offset_t end_addr = src_addr + len;
+ vm_offset_t nextva;
+
+ if (dst_addr != src_addr)
+ return;
+
+ if (!pmap_is_current(src_pmap))
+ return;
+
+ rw_wlock(&pvh_global_lock);
+ if (dst_pmap < src_pmap) {
+ PMAP_LOCK(dst_pmap);
+ PMAP_LOCK(src_pmap);
+ } else {
+ PMAP_LOCK(src_pmap);
+ PMAP_LOCK(dst_pmap);
+ }
+ sched_pin();
+ for (addr = src_addr; addr < end_addr; addr = nextva) {
+ pt2_entry_t *src_pte2p, *dst_pte2p;
+ vm_page_t dst_mpt2pg, src_mpt2pg;
+ pt1_entry_t src_pte1;
+ u_int pte1_idx;
+
+ KASSERT(addr < VM_MAXUSER_ADDRESS,
+ ("%s: invalid to pmap_copy page tables", __func__));
+
+ nextva = pte1_trunc(addr + PTE1_SIZE);
+ if (nextva < addr)
+ nextva = end_addr;
+
+ pte1_idx = pte1_index(addr);
+ src_pte1 = src_pmap->pm_pt1[pte1_idx];
+ if (pte1_is_section(src_pte1)) {
+ if ((addr & PTE1_OFFSET) != 0 ||
+ (addr + PTE1_SIZE) > end_addr)
+ continue;
+ if (dst_pmap->pm_pt1[pte1_idx] == 0 &&
+ (!pte1_is_managed(src_pte1) ||
+ pmap_pv_insert_pte1(dst_pmap, addr,
+ pte1_pa(src_pte1)))) {
+ dst_pmap->pm_pt1[pte1_idx] = src_pte1 &
+ ~PTE1_W;
+ dst_pmap->pm_stats.resident_count +=
+ PTE1_SIZE / PAGE_SIZE;
+ pmap_pte1_mappings++;
+ }
+ continue;
+ } else if (!pte1_is_link(src_pte1))
+ continue;
+
+ src_mpt2pg = PHYS_TO_VM_PAGE(pte1_link_pa(src_pte1));
+
+ /*
+ * We leave PT2s to be linked from PT1 even if they are not
+ * referenced until all PT2s in a page are without reference.
+ *
+ * QQQ: It could be changed ...
+ */
+#if 0 /* single_pt2_link_is_cleared */
+ KASSERT(pt2_wirecount_get(src_mpt2pg, pte1_idx) > 0,
+ ("%s: source page table page is unused", __func__));
+#else
+ if (pt2_wirecount_get(src_mpt2pg, pte1_idx) == 0)
+ continue;
+#endif
+ if (nextva > end_addr)
+ nextva = end_addr;
+
+ src_pte2p = pt2map_entry(addr);
+ while (addr < nextva) {
+ pt2_entry_t temp_pte2;
+ temp_pte2 = pte2_load(src_pte2p);
+ /*
+ * we only virtual copy managed pages
+ */
+ if (pte2_is_managed(temp_pte2)) {
+ dst_mpt2pg = pmap_allocpte2(dst_pmap, addr,
+ PMAP_ENTER_NOSLEEP);
+ if (dst_mpt2pg == NULL)
+ goto out;
+ dst_pte2p = pmap_pte2_quick(dst_pmap, addr);
+ if (!pte2_is_valid(pte2_load(dst_pte2p)) &&
+ pmap_try_insert_pv_entry(dst_pmap, addr,
+ PHYS_TO_VM_PAGE(pte2_pa(temp_pte2)))) {
+ /*
+ * Clear the wired, modified, and
+ * accessed (referenced) bits
+ * during the copy.
+ */
+ temp_pte2 &= ~(PTE2_W | PTE2_A);
+ temp_pte2 |= PTE2_NM;
+ pte2_store(dst_pte2p, temp_pte2);
+ dst_pmap->pm_stats.resident_count++;
+ } else {
+ SLIST_INIT(&free);
+ if (pmap_unwire_pt2(dst_pmap, addr,
+ dst_mpt2pg, &free)) {
+ pmap_tlb_flush(dst_pmap, addr);
+ pmap_free_zero_pages(&free);
+ }
+ goto out;
+ }
+ if (pt2_wirecount_get(dst_mpt2pg, pte1_idx) >=
+ pt2_wirecount_get(src_mpt2pg, pte1_idx))
+ break;
+ }
+ addr += PAGE_SIZE;
+ src_pte2p++;
+ }
+ }
+out:
+ sched_unpin();
+ rw_wunlock(&pvh_global_lock);
+ PMAP_UNLOCK(src_pmap);
+ PMAP_UNLOCK(dst_pmap);
+}
+
+/*
+ * Increase the starting virtual address of the given mapping if a
+ * different alignment might result in more section mappings.
+ */
+void
+pmap_align_superpage(vm_object_t object, vm_ooffset_t offset,
+ vm_offset_t *addr, vm_size_t size)
+{
+ vm_offset_t pte1_offset;
+
+ if (size < PTE1_SIZE)
+ return;
+ if (object != NULL && (object->flags & OBJ_COLORED) != 0)
+ offset += ptoa(object->pg_color);
+ pte1_offset = offset & PTE1_OFFSET;
+ if (size - ((PTE1_SIZE - pte1_offset) & PTE1_OFFSET) < PTE1_SIZE ||
+ (*addr & PTE1_OFFSET) == pte1_offset)
+ return;
+ if ((*addr & PTE1_OFFSET) < pte1_offset)
+ *addr = pte1_trunc(*addr) + pte1_offset;
+ else
+ *addr = pte1_roundup(*addr) + pte1_offset;
+}
+
+void
+pmap_activate(struct thread *td)
+{
+ pmap_t pmap, oldpmap;
+ u_int cpuid, ttb;
+
+ PDEBUG(9, printf("%s: td = %08x\n", __func__, (uint32_t)td));
+
+ critical_enter();
+ pmap = vmspace_pmap(td->td_proc->p_vmspace);
+ oldpmap = PCPU_GET(curpmap);
+ cpuid = PCPU_GET(cpuid);
+
+#if defined(SMP)
+ CPU_CLR_ATOMIC(cpuid, &oldpmap->pm_active);
+ CPU_SET_ATOMIC(cpuid, &pmap->pm_active);
+#else
+ CPU_CLR(cpuid, &oldpmap->pm_active);
+ CPU_SET(cpuid, &pmap->pm_active);
+#endif
+
+ ttb = pmap_ttb_get(pmap);
+
+ /*
+ * pmap_activate is for the current thread on the current cpu
+ */
+ td->td_pcb->pcb_pagedir = ttb;
+ cp15_ttbr_set(ttb);
+ PCPU_SET(curpmap, pmap);
+ critical_exit();
+}
+
+/*
+ * Perform the pmap work for mincore.
*/
int
pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *locked_pa)
{
- struct l2_bucket *l2b;
- pd_entry_t *pl1pd, l1pd;
- pt_entry_t *ptep, pte;
+ pt1_entry_t *pte1p, pte1;
+ pt2_entry_t *pte2p, pte2;
vm_paddr_t pa;
- vm_page_t m;
- int val;
boolean_t managed;
+ int val;
PMAP_LOCK(pmap);
retry:
- pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(addr)];
- l1pd = *pl1pd;
- if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) {
- pa = (l1pd & L1_S_FRAME);
+ pte1p = pmap_pte1(pmap, addr);
+ pte1 = pte1_load(pte1p);
+ if (pte1_is_section(pte1)) {
+ pa = trunc_page(pte1_pa(pte1) | (addr & PTE1_OFFSET));
+ managed = pte1_is_managed(pte1);
val = MINCORE_SUPER | MINCORE_INCORE;
- if (L1_S_WRITABLE(l1pd))
+ if (pte1_is_dirty(pte1))
val |= MINCORE_MODIFIED | MINCORE_MODIFIED_OTHER;
- managed = FALSE;
- m = PHYS_TO_VM_PAGE(pa);
- if (m != NULL && (m->oflags & VPO_UNMANAGED) == 0)
- managed = TRUE;
- if (managed) {
- if (L1_S_REFERENCED(l1pd))
- val |= MINCORE_REFERENCED |
- MINCORE_REFERENCED_OTHER;
- }
- } else {
- l2b = pmap_get_l2_bucket(pmap, addr);
- if (l2b == NULL) {
- val = 0;
- goto out;
- }
- ptep = &l2b->l2b_kva[l2pte_index(addr)];
- pte = *ptep;
- if (!l2pte_valid(pte)) {
- val = 0;
- goto out;
- }
+ if (pte1 & PTE1_A)
+ val |= MINCORE_REFERENCED | MINCORE_REFERENCED_OTHER;
+ } else if (pte1_is_link(pte1)) {
+ pte2p = pmap_pte2(pmap, addr);
+ pte2 = pte2_load(pte2p);
+ pmap_pte2_release(pte2p);
+ pa = pte2_pa(pte2);
+ managed = pte2_is_managed(pte2);
val = MINCORE_INCORE;
- if (L2_S_WRITABLE(pte))
+ if (pte2_is_dirty(pte2))
val |= MINCORE_MODIFIED | MINCORE_MODIFIED_OTHER;
+ if (pte2 & PTE2_A)
+ val |= MINCORE_REFERENCED | MINCORE_REFERENCED_OTHER;
+ } else {
managed = FALSE;
- pa = l2pte_pa(pte);
- m = PHYS_TO_VM_PAGE(pa);
- if (m != NULL && (m->oflags & VPO_UNMANAGED) == 0)
- managed = TRUE;
- if (managed) {
- if (L2_S_REFERENCED(pte))
- val |= MINCORE_REFERENCED |
- MINCORE_REFERENCED_OTHER;
- }
+ val = 0;
}
if ((val & (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER)) !=
(MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER) && managed) {
@@ -5214,239 +6018,648 @@ retry:
if (vm_page_pa_tryrelock(pmap, pa, locked_pa))
goto retry;
} else
-out:
PA_UNLOCK_COND(*locked_pa);
PMAP_UNLOCK(pmap);
return (val);
}
void
-pmap_sync_icache(pmap_t pmap, vm_offset_t va, vm_size_t sz)
+pmap_kenter_device(vm_offset_t va, vm_size_t size, vm_paddr_t pa)
{
+ vm_offset_t sva;
+ uint32_t l2attr;
+
+ KASSERT((size & PAGE_MASK) == 0,
+ ("%s: device mapping not page-sized", __func__));
+
+ sva = va;
+ l2attr = vm_memattr_to_pte2(VM_MEMATTR_DEVICE);
+ while (size != 0) {
+ pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, l2attr);
+ va += PAGE_SIZE;
+ pa += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+ tlb_flush_range(sva, va - sva);
}
-/*
- * Increase the starting virtual address of the given mapping if a
- * different alignment might result in more superpage mappings.
- */
void
-pmap_align_superpage(vm_object_t object, vm_ooffset_t offset,
- vm_offset_t *addr, vm_size_t size)
+pmap_kremove_device(vm_offset_t va, vm_size_t size)
{
- vm_offset_t superpage_offset;
+ vm_offset_t sva;
- if (size < NBPDR)
- return;
- if (object != NULL && (object->flags & OBJ_COLORED) != 0)
- offset += ptoa(object->pg_color);
- superpage_offset = offset & PDRMASK;
- if (size - ((NBPDR - superpage_offset) & PDRMASK) < NBPDR ||
- (*addr & PDRMASK) == superpage_offset)
- return;
- if ((*addr & PDRMASK) < superpage_offset)
- *addr = (*addr & ~PDRMASK) + superpage_offset;
- else
- *addr = ((*addr + PDRMASK) & ~PDRMASK) + superpage_offset;
+ KASSERT((size & PAGE_MASK) == 0,
+ ("%s: device mapping not page-sized", __func__));
+
+ sva = va;
+ while (size != 0) {
+ pmap_kremove(va);
+ va += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+ tlb_flush_range(sva, va - sva);
}
-/*
- * pmap_map_section:
- *
- * Create a single section mapping.
- */
void
-pmap_map_section(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot,
- boolean_t ref)
+pmap_set_pcb_pagedir(pmap_t pmap, struct pcb *pcb)
{
- pd_entry_t *pl1pd, l1pd;
- pd_entry_t fl;
- KASSERT(((va | pa) & L1_S_OFFSET) == 0,
- ("Not a valid section mapping"));
+ pcb->pcb_pagedir = pmap_ttb_get(pmap);
+}
- fl = pte_l1_s_cache_mode;
- pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(va)];
- l1pd = L1_S_PROTO | pa | L1_S_PROT(PTE_USER, prot) | fl |
- L1_S_DOM(pmap->pm_domain);
+/*
+ * Clean L1 data cache range by physical address.
+ * The range must be within a single page.
+ */
+static void
+pmap_dcache_wb_pou(vm_paddr_t pa, vm_size_t size, uint32_t attr)
+{
+ struct sysmaps *sysmaps;
- /* Mark page referenced if this section is a result of a promotion. */
- if (ref == TRUE)
- l1pd |= L1_S_REF;
-#ifdef SMP
- l1pd |= L1_SHARED;
-#endif
- *pl1pd = l1pd;
- PTE_SYNC(pl1pd);
+ KASSERT(((pa & PAGE_MASK) + size) <= PAGE_SIZE,
+ ("%s: not on single page", __func__));
+
+ sched_pin();
+ sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
+ mtx_lock(&sysmaps->lock);
+ if (*sysmaps->CMAP3)
+ panic("%s: CMAP3 busy", __func__);
+ pte2_store(sysmaps->CMAP3, PTE2_KERN_NG(pa, PTE2_AP_KRW, attr));
+ dcache_wb_pou((vm_offset_t)sysmaps->CADDR3 + (pa & PAGE_MASK), size);
+ pte2_clear(sysmaps->CMAP3);
+ tlb_flush((vm_offset_t)sysmaps->CADDR3);
+ sched_unpin();
+ mtx_unlock(&sysmaps->lock);
}
/*
- * pmap_link_l2pt:
- *
- * Link the L2 page table specified by l2pv.pv_pa into the L1
- * page table at the slot for "va".
+ * Sync instruction cache range which is not mapped yet.
*/
void
-pmap_link_l2pt(vm_offset_t l1pt, vm_offset_t va, struct pv_addr *l2pv)
+cache_icache_sync_fresh(vm_offset_t va, vm_paddr_t pa, vm_size_t size)
{
- pd_entry_t *pde = (pd_entry_t *) l1pt, proto;
- u_int slot = va >> L1_S_SHIFT;
+ uint32_t len, offset;
+ vm_page_t m;
- proto = L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_C_PROTO;
+ /* Write back d-cache on given address range. */
+ offset = pa & PAGE_MASK;
+ for ( ; size != 0; size -= len, pa += len, offset = 0) {
+ len = min(PAGE_SIZE - offset, size);
+ m = PHYS_TO_VM_PAGE(pa);
+ KASSERT(m != NULL, ("%s: vm_page_t is null for %#x",
+ __func__, pa));
+ pmap_dcache_wb_pou(pa, len, vm_page_pte2_attr(m));
+ }
+ /*
+ * I-cache is VIPT. Only way how to flush all virtual mappings
+ * on given physical address is to invalidate all i-cache.
+ */
+ icache_inv_all();
+}
-#ifdef VERBOSE_INIT_ARM
- printf("pmap_link_l2pt: pa=0x%x va=0x%x\n", l2pv->pv_pa, l2pv->pv_va);
-#endif
+void
+pmap_sync_icache(pmap_t pmap, vm_offset_t va, vm_size_t size)
+{
- pde[slot + 0] = proto | (l2pv->pv_pa + 0x000);
- PTE_SYNC(&pde[slot]);
+ /* Write back d-cache on given address range. */
+ if (va >= VM_MIN_KERNEL_ADDRESS) {
+ dcache_wb_pou(va, size);
+ } else {
+ uint32_t len, offset;
+ vm_paddr_t pa;
+ vm_page_t m;
+
+ offset = va & PAGE_MASK;
+ for ( ; size != 0; size -= len, va += len, offset = 0) {
+ pa = pmap_extract(pmap, va); /* offset is preserved */
+ len = min(PAGE_SIZE - offset, size);
+ m = PHYS_TO_VM_PAGE(pa);
+ KASSERT(m != NULL, ("%s: vm_page_t is null for %#x",
+ __func__, pa));
+ pmap_dcache_wb_pou(pa, len, vm_page_pte2_attr(m));
+ }
+ }
+ /*
+ * I-cache is VIPT. Only way how to flush all virtual mappings
+ * on given physical address is to invalidate all i-cache.
+ */
+ icache_inv_all();
+}
- SLIST_INSERT_HEAD(&kernel_pt_list, l2pv, pv_list);
+/*
+ * The implementation of pmap_fault() uses IN_RANGE2() macro which
+ * depends on the fact that given range size is a power of 2.
+ */
+CTASSERT(powerof2(NB_IN_PT1));
+CTASSERT(powerof2(PT2MAP_SIZE));
-}
+#define IN_RANGE2(addr, start, size) \
+ ((vm_offset_t)(start) == ((vm_offset_t)(addr) & ~((size) - 1)))
/*
- * pmap_map_entry
- *
- * Create a single page mapping.
+ * Handle access and R/W emulation faults.
*/
-void
-pmap_map_entry(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa, int prot,
- int cache)
+int
+pmap_fault(pmap_t pmap, vm_offset_t far, uint32_t fsr, int idx, bool usermode)
{
- pd_entry_t *pde = (pd_entry_t *) l1pt;
- pt_entry_t fl;
- pt_entry_t *ptep;
+ pt1_entry_t *pte1p, pte1;
+ pt2_entry_t *pte2p, pte2;
- KASSERT(((va | pa) & PAGE_MASK) == 0, ("ouin"));
+ if (pmap == NULL)
+ pmap = kernel_pmap;
+
+ /*
+ * In kernel, we should never get abort with FAR which is in range of
+ * pmap->pm_pt1 or PT2MAP address spaces. If it happens, stop here
+ * and print out a useful abort message and even get to the debugger
+ * otherwise it likely ends with never ending loop of aborts.
+ */
+ if (__predict_false(IN_RANGE2(far, pmap->pm_pt1, NB_IN_PT1))) {
+ /*
+ * All L1 tables should always be mapped and present.
+ * However, we check only current one herein. For user mode,
+ * only permission abort from malicious user is not fatal.
+ * And alignment abort as it may have higher priority.
+ */
+ if (!usermode || (idx != FAULT_ALIGN && idx != FAULT_PERM_L2)) {
+ CTR4(KTR_PMAP, "%s: pmap %#x pm_pt1 %#x far %#x",
+ __func__, pmap, pmap->pm_pt1, far);
+ panic("%s: pm_pt1 abort", __func__);
+ }
+ return (KERN_INVALID_ADDRESS);
+ }
+ if (__predict_false(IN_RANGE2(far, PT2MAP, PT2MAP_SIZE))) {
+ /*
+ * PT2MAP should be always mapped and present in current
+ * L1 table. However, only existing L2 tables are mapped
+ * in PT2MAP. For user mode, only L2 translation abort and
+ * permission abort from malicious user is not fatal.
+ * And alignment abort as it may have higher priority.
+ */
+ if (!usermode || (idx != FAULT_ALIGN &&
+ idx != FAULT_TRAN_L2 && idx != FAULT_PERM_L2)) {
+ CTR4(KTR_PMAP, "%s: pmap %#x PT2MAP %#x far %#x",
+ __func__, pmap, PT2MAP, far);
+ panic("%s: PT2MAP abort", __func__);
+ }
+ return (KERN_INVALID_ADDRESS);
+ }
- fl = l2s_mem_types[cache];
+ /*
+ * Accesss bits for page and section. Note that the entry
+ * is not in TLB yet, so TLB flush is not necessary.
+ *
+ * QQQ: This is hardware emulation, we do not call userret()
+ * for aborts from user mode.
+ * We do not lock PMAP, so cmpset() is a need. Hopefully,
+ * no one removes the mapping when we are here.
+ */
+ if (idx == FAULT_ACCESS_L2) {
+ pte2p = pt2map_entry(far);
+pte2_seta:
+ pte2 = pte2_load(pte2p);
+ if (pte2_is_valid(pte2)) {
+ if (!pte2_cmpset(pte2p, pte2, pte2 | PTE2_A)) {
+ goto pte2_seta;
+ }
+ return (KERN_SUCCESS);
+ }
+ }
+ if (idx == FAULT_ACCESS_L1) {
+ pte1p = pmap_pte1(pmap, far);
+pte1_seta:
+ pte1 = pte1_load(pte1p);
+ if (pte1_is_section(pte1)) {
+ if (!pte1_cmpset(pte1p, pte1, pte1 | PTE1_A)) {
+ goto pte1_seta;
+ }
+ return (KERN_SUCCESS);
+ }
+ }
- if ((pde[va >> L1_S_SHIFT] & L1_TYPE_MASK) != L1_TYPE_C)
- panic("pmap_map_entry: no L2 table for VA 0x%08x", va);
+ /*
+ * Handle modify bits for page and section. Note that the modify
+ * bit is emulated by software. So PTEx_RO is software read only
+ * bit and PTEx_NM flag is real hardware read only bit.
+ *
+ * QQQ: This is hardware emulation, we do not call userret()
+ * for aborts from user mode.
+ * We do not lock PMAP, so cmpset() is a need. Hopefully,
+ * no one removes the mapping when we are here.
+ */
+ if ((fsr & FSR_WNR) && (idx == FAULT_PERM_L2)) {
+ pte2p = pt2map_entry(far);
+pte2_setrw:
+ pte2 = pte2_load(pte2p);
+ if (pte2_is_valid(pte2) && !(pte2 & PTE2_RO) &&
+ (pte2 & PTE2_NM)) {
+ if (!pte2_cmpset(pte2p, pte2, pte2 & ~PTE2_NM)) {
+ goto pte2_setrw;
+ }
+ tlb_flush(trunc_page(far));
+ return (KERN_SUCCESS);
+ }
+ }
+ if ((fsr & FSR_WNR) && (idx == FAULT_PERM_L1)) {
+ pte1p = pmap_pte1(pmap, far);
+pte1_setrw:
+ pte1 = pte1_load(pte1p);
+ if (pte1_is_section(pte1) && !(pte1 & PTE1_RO) &&
+ (pte1 & PTE1_NM)) {
+ if (!pte1_cmpset(pte1p, pte1, pte1 & ~PTE1_NM)) {
+ goto pte1_setrw;
+ }
+ tlb_flush(pte1_trunc(far));
+ return (KERN_SUCCESS);
+ }
+ }
- ptep = (pt_entry_t *)kernel_pt_lookup(pde[L1_IDX(va)] & L1_C_ADDR_MASK);
+ /*
+ * QQQ: The previous code, mainly fast handling of access and
+ * modify bits aborts, could be moved to ASM. Now we are
+ * starting to deal with not fast aborts.
+ */
- if (ptep == NULL)
- panic("pmap_map_entry: can't find L2 table for VA 0x%08x", va);
+#ifdef INVARIANTS
+ /*
+ * Read an entry in PT2TAB associated with both pmap and far.
+ * It's safe because PT2TAB is always mapped.
+ *
+ * QQQ: We do not lock PMAP, so false positives could happen if
+ * the mapping is removed concurrently.
+ */
+ pte2 = pt2tab_load(pmap_pt2tab_entry(pmap, far));
+ if (pte2_is_valid(pte2)) {
+ /*
+ * Now, when we know that L2 page table is allocated,
+ * we can use PT2MAP to get L2 page table entry.
+ */
+ pte2 = pte2_load(pt2map_entry(far));
+ if (pte2_is_valid(pte2)) {
+ /*
+ * If L2 page table entry is valid, make sure that
+ * L1 page table entry is valid too. Note that we
+ * leave L2 page entries untouched when promoted.
+ */
+ pte1 = pte1_load(pmap_pte1(pmap, far));
+ if (!pte1_is_valid(pte1)) {
+ panic("%s: missing L1 page entry (%p, %#x)",
+ __func__, pmap, far);
+ }
+ }
+ }
+#endif
+ return (KERN_FAILURE);
+}
- ptep[l2pte_index(va)] = L2_S_PROTO | pa | fl | L2_S_REF;
- pmap_set_prot(&ptep[l2pte_index(va)], prot, 0);
- PTE_SYNC(&ptep[l2pte_index(va)]);
+/* !!!! REMOVE !!!! */
+void vector_page_setprot(int p)
+{
}
+#if defined(PMAP_DEBUG)
/*
- * pmap_map_chunk:
- *
- * Map a chunk of memory using the most efficient mappings
- * possible (section. large page, small page) into the
- * provided L1 and L2 tables at the specified virtual address.
+ * Reusing of KVA used in pmap_zero_page function !!!
*/
-vm_size_t
-pmap_map_chunk(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa,
- vm_size_t size, int prot, int type)
+static void
+pmap_zero_page_check(vm_page_t m)
{
- pd_entry_t *pde = (pd_entry_t *) l1pt;
- pt_entry_t *ptep, f1, f2s, f2l;
- vm_size_t resid;
- int i;
+ uint32_t *p, *end;
+ struct sysmaps *sysmaps;
- resid = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+ sched_pin();
+ sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)];
+ mtx_lock(&sysmaps->lock);
+ if (pte2_load(sysmaps->CMAP2) != 0)
+ panic("%s: CMAP2 busy", __func__);
+ pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW,
+ vm_page_pte2_attr(m)));
+ end = (uint32_t*)(sysmaps->CADDR2 + PAGE_SIZE);
+ for (p = (uint32_t*)sysmaps->CADDR2; p < end; p++)
+ if (*p != 0)
+ panic("%s: page %p not zero, va: %p", __func__, m,
+ sysmaps->CADDR2);
+ pte2_clear(sysmaps->CMAP2);
+ tlb_flush((vm_offset_t)sysmaps->CADDR2);
+ sched_unpin();
+ mtx_unlock(&sysmaps->lock);
+}
- if (l1pt == 0)
- panic("pmap_map_chunk: no L1 table provided");
+int
+pmap_pid_dump(int pid)
+{
+ pmap_t pmap;
+ struct proc *p;
+ int npte2 = 0;
+ int i, j, index;
+
+ sx_slock(&allproc_lock);
+ FOREACH_PROC_IN_SYSTEM(p) {
+ if (p->p_pid != pid || p->p_vmspace == NULL)
+ continue;
+ index = 0;
+ pmap = vmspace_pmap(p->p_vmspace);
+ for (i = 0; i < NPTE1_IN_PT1; i++) {
+ pt1_entry_t pte1;
+ pt2_entry_t *pte2p, pte2;
+ vm_offset_t base, va;
+ vm_paddr_t pa;
+ vm_page_t m;
+
+ base = i << PTE1_SHIFT;
+ pte1 = pte1_load(&pmap->pm_pt1[i]);
+
+ if (pte1_is_section(pte1)) {
+ /*
+ * QQQ: Do something here!
+ */
+ } else if (pte1_is_link(pte1)) {
+ for (j = 0; j < NPTE2_IN_PT2; j++) {
+ va = base + (j << PAGE_SHIFT);
+ if (va >= VM_MIN_KERNEL_ADDRESS) {
+ if (index) {
+ index = 0;
+ printf("\n");
+ }
+ sx_sunlock(&allproc_lock);
+ return (npte2);
+ }
+ pte2p = pmap_pte2(pmap, va);
+ pte2 = pte2_load(pte2p);
+ pmap_pte2_release(pte2p);
+ if (!pte2_is_valid(pte2))
+ continue;
+
+ pa = pte2_pa(pte2);
+ m = PHYS_TO_VM_PAGE(pa);
+ printf("va: 0x%x, pa: 0x%x, h: %d, w:"
+ " %d, f: 0x%x", va, pa,
+ m->hold_count, m->wire_count,
+ m->flags);
+ npte2++;
+ index++;
+ if (index >= 2) {
+ index = 0;
+ printf("\n");
+ } else {
+ printf(" ");
+ }
+ }
+ }
+ }
+ }
+ sx_sunlock(&allproc_lock);
+ return (npte2);
+}
-#ifdef VERBOSE_INIT_ARM
- printf("pmap_map_chunk: pa=0x%x va=0x%x size=0x%x resid=0x%x "
- "prot=0x%x type=%d\n", pa, va, size, resid, prot, type);
#endif
- f1 = l1_mem_types[type];
- f2l = l2l_mem_types[type];
- f2s = l2s_mem_types[type];
+#ifdef DDB
+static pt2_entry_t *
+pmap_pte2_ddb(pmap_t pmap, vm_offset_t va)
+{
+ pt1_entry_t pte1;
+ vm_paddr_t pt2pg_pa;
+
+ pte1 = pte1_load(pmap_pte1(pmap, va));
+ if (!pte1_is_link(pte1))
+ return (NULL);
- size = resid;
+ if (pmap_is_current(pmap))
+ return (pt2map_entry(va));
- while (resid > 0) {
- /* See if we can use a section mapping. */
- if (L1_S_MAPPABLE_P(va, pa, resid)) {
-#ifdef VERBOSE_INIT_ARM
- printf("S");
+ /* Note that L2 page table size is not equal to PAGE_SIZE. */
+ pt2pg_pa = trunc_page(pte1_link_pa(pte1));
+ if (pte2_pa(pte2_load(PMAP3)) != pt2pg_pa) {
+ pte2_store(PMAP3, PTE2_KPT(pt2pg_pa));
+#ifdef SMP
+ PMAP3cpu = PCPU_GET(cpuid);
#endif
- pde[va >> L1_S_SHIFT] = L1_S_PROTO | pa |
- L1_S_PROT(PTE_KERNEL, prot | VM_PROT_EXECUTE) |
- f1 | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_REF;
- PTE_SYNC(&pde[va >> L1_S_SHIFT]);
- va += L1_S_SIZE;
- pa += L1_S_SIZE;
- resid -= L1_S_SIZE;
+ tlb_flush_local((vm_offset_t)PADDR3);
+ }
+#ifdef SMP
+ else if (PMAP3cpu != PCPU_GET(cpuid)) {
+ PMAP3cpu = PCPU_GET(cpuid);
+ tlb_flush_local((vm_offset_t)PADDR3);
+ }
+#endif
+ return (PADDR3 + (arm32_btop(va) & (NPTE2_IN_PG - 1)));
+}
+
+static void
+dump_pmap(pmap_t pmap)
+{
+
+ printf("pmap %p\n", pmap);
+ printf(" pm_pt1: %p\n", pmap->pm_pt1);
+ printf(" pm_pt2tab: %p\n", pmap->pm_pt2tab);
+ printf(" pm_active: 0x%08lX\n", pmap->pm_active.__bits[0]);
+}
+
+DB_SHOW_COMMAND(pmaps, pmap_list_pmaps)
+{
+
+ pmap_t pmap;
+ LIST_FOREACH(pmap, &allpmaps, pm_list) {
+ dump_pmap(pmap);
+ }
+}
+
+static int
+pte2_class(pt2_entry_t pte2)
+{
+ int cls;
+
+ cls = (pte2 >> 2) & 0x03;
+ cls |= (pte2 >> 4) & 0x04;
+ return (cls);
+}
+
+static void
+dump_section(pmap_t pmap, uint32_t pte1_idx)
+{
+}
+
+static void
+dump_link(pmap_t pmap, uint32_t pte1_idx, boolean_t invalid_ok)
+{
+ uint32_t i;
+ vm_offset_t va;
+ pt2_entry_t *pte2p, pte2;
+ vm_page_t m;
+
+ va = pte1_idx << PTE1_SHIFT;
+ pte2p = pmap_pte2_ddb(pmap, va);
+ for (i = 0; i < NPTE2_IN_PT2; i++, pte2p++, va += PAGE_SIZE) {
+ pte2 = pte2_load(pte2p);
+ if (pte2 == 0)
continue;
+ if (!pte2_is_valid(pte2)) {
+ printf(" 0x%08X: 0x%08X", va, pte2);
+ if (!invalid_ok)
+ printf(" - not valid !!!");
+ printf("\n");
+ continue;
+ }
+ m = PHYS_TO_VM_PAGE(pte2_pa(pte2));
+ printf(" 0x%08X: 0x%08X, TEX%d, s:%d, g:%d, m:%p", va , pte2,
+ pte2_class(pte2), !!(pte2 & PTE2_S), !(pte2 & PTE2_NG), m);
+ if (m != NULL) {
+ printf(" v:%d h:%d w:%d f:0x%04X\n", m->valid,
+ m->hold_count, m->wire_count, m->flags);
+ } else {
+ printf("\n");
}
+ }
+}
- /*
- * Ok, we're going to use an L2 table. Make sure
- * one is actually in the corresponding L1 slot
- * for the current VA.
- */
- if ((pde[va >> L1_S_SHIFT] & L1_TYPE_MASK) != L1_TYPE_C)
- panic("pmap_map_chunk: no L2 table for VA 0x%08x", va);
-
- ptep = (pt_entry_t *) kernel_pt_lookup(
- pde[L1_IDX(va)] & L1_C_ADDR_MASK);
- if (ptep == NULL)
- panic("pmap_map_chunk: can't find L2 table for VA"
- "0x%08x", va);
- /* See if we can use a L2 large page mapping. */
- if (L2_L_MAPPABLE_P(va, pa, resid)) {
-#ifdef VERBOSE_INIT_ARM
- printf("L");
-#endif
- for (i = 0; i < 16; i++) {
- ptep[l2pte_index(va) + i] =
- L2_L_PROTO | pa |
- L2_L_PROT(PTE_KERNEL, prot) | f2l;
- PTE_SYNC(&ptep[l2pte_index(va) + i]);
- }
- va += L2_L_SIZE;
- pa += L2_L_SIZE;
- resid -= L2_L_SIZE;
- continue;
+static __inline boolean_t
+is_pv_chunk_space(vm_offset_t va)
+{
+
+ if ((((vm_offset_t)pv_chunkbase) <= va) &&
+ (va < ((vm_offset_t)pv_chunkbase + PAGE_SIZE * pv_maxchunks)))
+ return (TRUE);
+ return (FALSE);
+}
+
+DB_SHOW_COMMAND(pmap, pmap_pmap_print)
+{
+ /* XXX convert args. */
+ pmap_t pmap = (pmap_t)addr;
+ pt1_entry_t pte1;
+ pt2_entry_t pte2;
+ vm_offset_t va, eva;
+ vm_page_t m;
+ uint32_t i;
+ boolean_t invalid_ok, dump_link_ok, dump_pv_chunk;
+
+ if (have_addr) {
+ pmap_t pm;
+
+ LIST_FOREACH(pm, &allpmaps, pm_list)
+ if (pm == pmap) break;
+ if (pm == NULL) {
+ printf("given pmap %p is not in allpmaps list\n", pmap);
+ return;
}
+ } else
+ pmap = PCPU_GET(curpmap);
- /* Use a small page mapping. */
-#ifdef VERBOSE_INIT_ARM
- printf("P");
-#endif
- ptep[l2pte_index(va)] = L2_S_PROTO | pa | f2s | L2_S_REF;
- pmap_set_prot(&ptep[l2pte_index(va)], prot, 0);
- PTE_SYNC(&ptep[l2pte_index(va)]);
- va += PAGE_SIZE;
- pa += PAGE_SIZE;
- resid -= PAGE_SIZE;
+ eva = (modif[0] == 'u') ? VM_MAXUSER_ADDRESS : 0xFFFFFFFF;
+ dump_pv_chunk = FALSE; /* XXX evaluate from modif[] */
+
+ printf("pmap: 0x%08X\n", (uint32_t)pmap);
+ printf("PT2MAP: 0x%08X\n", (uint32_t)PT2MAP);
+ printf("pt2tab: 0x%08X\n", (uint32_t)pmap->pm_pt2tab);
+
+ for(i = 0; i < NPTE1_IN_PT1; i++) {
+ pte1 = pte1_load(&pmap->pm_pt1[i]);
+ if (pte1 == 0)
+ continue;
+ va = i << PTE1_SHIFT;
+ if (va >= eva)
+ break;
+
+ if (pte1_is_section(pte1)) {
+ printf("0x%08X: Section 0x%08X, s:%d g:%d\n", va, pte1,
+ !!(pte1 & PTE1_S), !(pte1 & PTE1_NG));
+ dump_section(pmap, i);
+ } else if (pte1_is_link(pte1)) {
+ dump_link_ok = TRUE;
+ invalid_ok = FALSE;
+ pte2 = pte2_load(pmap_pt2tab_entry(pmap, va));
+ m = PHYS_TO_VM_PAGE(pte1_link_pa(pte1));
+ printf("0x%08X: Link 0x%08X, pt2tab: 0x%08X m: %p",
+ va, pte1, pte2, m);
+ if (is_pv_chunk_space(va)) {
+ printf(" - pv_chunk space");
+ if (dump_pv_chunk)
+ invalid_ok = TRUE;
+ else
+ dump_link_ok = FALSE;
+ }
+ else if (m != NULL)
+ printf(" w:%d w2:%u", m->wire_count,
+ pt2_wirecount_get(m, pte1_index(va)));
+ if (pte2 == 0)
+ printf(" !!! pt2tab entry is ZERO");
+ else if (pte2_pa(pte1) != pte2_pa(pte2))
+ printf(" !!! pt2tab entry is DIFFERENT - m: %p",
+ PHYS_TO_VM_PAGE(pte2_pa(pte2)));
+ printf("\n");
+ if (dump_link_ok)
+ dump_link(pmap, i, invalid_ok);
+ } else
+ printf("0x%08X: Invalid entry 0x%08X\n", va, pte1);
}
-#ifdef VERBOSE_INIT_ARM
- printf("\n");
-#endif
- return (size);
+}
+static void
+dump_pt2tab(pmap_t pmap)
+{
+ uint32_t i;
+ pt2_entry_t pte2;
+ vm_offset_t va;
+ vm_paddr_t pa;
+ vm_page_t m;
+
+ printf("PT2TAB:\n");
+ for (i = 0; i < PT2TAB_ENTRIES; i++) {
+ pte2 = pte2_load(&pmap->pm_pt2tab[i]);
+ if (!pte2_is_valid(pte2))
+ continue;
+ va = i << PT2TAB_SHIFT;
+ pa = pte2_pa(pte2);
+ m = PHYS_TO_VM_PAGE(pa);
+ printf(" 0x%08X: 0x%08X, TEX%d, s:%d, m:%p", va, pte2,
+ pte2_class(pte2), !!(pte2 & PTE2_S), m);
+ if (m != NULL)
+ printf(" , h: %d, w: %d, f: 0x%04X pidx: %lld",
+ m->hold_count, m->wire_count, m->flags, m->pindex);
+ printf("\n");
+ }
}
-void
-pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma)
+DB_SHOW_COMMAND(pmap_pt2tab, pmap_pt2tab_print)
{
- /*
- * Remember the memattr in a field that gets used to set the appropriate
- * bits in the PTEs as mappings are established.
- */
- m->md.pv_memattr = ma;
+ /* XXX convert args. */
+ pmap_t pmap = (pmap_t)addr;
+ pt1_entry_t pte1;
+ pt2_entry_t pte2;
+ vm_offset_t va;
+ uint32_t i, start;
- /*
- * It appears that this function can only be called before any mappings
- * for the page are established on ARM. If this ever changes, this code
- * will need to walk the pv_list and make each of the existing mappings
- * uncacheable, being careful to sync caches and PTEs (and maybe
- * invalidate TLB?) for any current mapping it modifies.
- */
- if (TAILQ_FIRST(&m->md.pv_list) != NULL)
- panic("Can't change memattr on page with existing mappings");
+ if (have_addr) {
+ printf("supported only on current pmap\n");
+ return;
+ }
+
+ pmap = PCPU_GET(curpmap);
+ printf("curpmap: 0x%08X\n", (uint32_t)pmap);
+ printf("PT2MAP: 0x%08X\n", (uint32_t)PT2MAP);
+ printf("pt2tab: 0x%08X\n", (uint32_t)pmap->pm_pt2tab);
+
+ start = pte1_index((vm_offset_t)PT2MAP);
+ for (i = start; i < (start + NPT2_IN_PT2TAB); i++) {
+ pte1 = pte1_load(&pmap->pm_pt1[i]);
+ if (pte1 == 0)
+ continue;
+ va = i << PTE1_SHIFT;
+ if (pte1_is_section(pte1)) {
+ printf("0x%08X: Section 0x%08X, s:%d\n", va, pte1,
+ !!(pte1 & PTE1_S));
+ dump_section(pmap, i);
+ } else if (pte1_is_link(pte1)) {
+ pte2 = pte2_load(pmap_pt2tab_entry(pmap, va));
+ printf("0x%08X: Link 0x%08X, pt2tab: 0x%08X\n", va,
+ pte1, pte2);
+ if (pte2 == 0)
+ printf(" !!! pt2tab entry is ZERO\n");
+ } else
+ printf("0x%08X: Invalid entry 0x%08X\n", va, pte1);
+ }
+ dump_pt2tab(pmap);
}
+#endif
diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c
index 3dd998429dfc..99a39a0ee522 100644
--- a/sys/arm/arm/pmap.c
+++ b/sys/arm/arm/pmap.c
@@ -394,7 +394,7 @@ int pmap_needs_pte_sync;
#define PMAP_SHPGPERPROC 200
#endif
-#define pmap_is_current(pm) ((pm) == pmap_kernel() || \
+#define pmap_is_current(pm) ((pm) == kernel_pmap || \
curproc->p_vmspace->vm_map.pmap == (pm))
static uma_zone_t pvzone = NULL;
uma_zone_t l2zone;
@@ -437,10 +437,10 @@ pmap_init_l1(struct l1_ttable *l1, pd_entry_t *l1pt)
/*
* Copy the kernel's L1 entries to each new L1.
*/
- if (l1pt != pmap_kernel()->pm_l1->l1_kva)
- memcpy(l1pt, pmap_kernel()->pm_l1->l1_kva, L1_TABLE_SIZE);
+ if (l1pt != kernel_pmap->pm_l1->l1_kva)
+ memcpy(l1pt, kernel_pmap->pm_l1->l1_kva, L1_TABLE_SIZE);
- if ((l1->l1_physaddr = pmap_extract(pmap_kernel(), (vm_offset_t)l1pt)) == 0)
+ if ((l1->l1_physaddr = pmap_extract(kernel_pmap, (vm_offset_t)l1pt)) == 0)
panic("pmap_init_l1: can't get PA of L1 at %p", l1pt);
SLIST_INSERT_HEAD(&l1_list, l1, l1_link);
TAILQ_INSERT_TAIL(&l1_lru_list, l1, l1_lru);
@@ -561,7 +561,7 @@ pmap_pte_init_xscale(void)
{
uint32_t id, type;
- id = cpufunc_id();
+ id = cpu_ident();
type = id & ~(CPU_ID_XSCALE_COREREV_MASK|CPU_ID_REVISION_MASK);
if (type == CPU_ID_PXA250 || type == CPU_ID_PXA210) {
@@ -932,7 +932,7 @@ pmap_free_l2_bucket(pmap_t pm, struct l2_bucket *l2b, u_int count)
* to a performance win over time as we don't need to continually
* alloc/free.
*/
- if (l2b->l2b_occupancy > 0 || pm == pmap_kernel())
+ if (l2b->l2b_occupancy > 0 || pm == kernel_pmap)
return;
/*
@@ -1002,7 +1002,7 @@ pmap_l2ptp_ctor(void *mem, int size, void *arg, int flags)
* page tables, we simply fix up the cache-mode here if it's not
* correct.
*/
- l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ l2b = pmap_get_l2_bucket(kernel_pmap, va);
ptep = &l2b->l2b_kva[l2pte_index(va)];
pte = *ptep;
@@ -1077,9 +1077,9 @@ pmap_idcache_wbinv_range(pmap_t pm, vm_offset_t va, vm_size_t len)
vm_size_t rest;
CTR4(KTR_PMAP, "pmap_dcache_wbinv_range: pmap %p is_kernel %d va 0x%08x"
- " len 0x%x ", pm, pm == pmap_kernel(), va, len);
+ " len 0x%x ", pm, pm == kernel_pmap, va, len);
- if (pmap_is_current(pm) || pm == pmap_kernel()) {
+ if (pmap_is_current(pm) || pm == kernel_pmap) {
rest = MIN(PAGE_SIZE - (va & PAGE_MASK), len);
while (len > 0) {
if (pmap_has_valid_mapping(pm, va)) {
@@ -1100,7 +1100,7 @@ pmap_dcache_wb_range(pmap_t pm, vm_offset_t va, vm_size_t len, boolean_t do_inv,
vm_size_t rest;
CTR4(KTR_PMAP, "pmap_dcache_wb_range: pmap %p is_kernel %d va 0x%08x "
- "len 0x%x ", pm, pm == pmap_kernel(), va, len);
+ "len 0x%x ", pm, pm == kernel_pmap, va, len);
CTR2(KTR_PMAP, " do_inv %d rd_only %d", do_inv, rd_only);
if (pmap_is_current(pm)) {
@@ -1230,13 +1230,13 @@ pmap_fix_cache(struct vm_page *pg, pmap_t pm, vm_offset_t va)
TAILQ_FOREACH(pv, &pg->md.pv_list, pv_list) {
/* generate a count of the pv_entry uses */
if (pv->pv_flags & PVF_WRITE) {
- if (pv->pv_pmap == pmap_kernel())
+ if (pv->pv_pmap == kernel_pmap)
kwritable++;
else if (pv->pv_pmap == pm)
uwritable++;
writable++;
}
- if (pv->pv_pmap == pmap_kernel())
+ if (pv->pv_pmap == kernel_pmap)
kentries++;
else {
if (pv->pv_pmap == pm)
@@ -1248,19 +1248,19 @@ pmap_fix_cache(struct vm_page *pg, pmap_t pm, vm_offset_t va)
* check if the user duplicate mapping has
* been removed.
*/
- if ((pm != pmap_kernel()) && (((uentries > 1) && uwritable) ||
+ if ((pm != kernel_pmap) && (((uentries > 1) && uwritable) ||
(uwritable > 1)))
pmwc = 1;
TAILQ_FOREACH(pv, &pg->md.pv_list, pv_list) {
/* check for user uncachable conditions - order is important */
- if (pm != pmap_kernel() &&
- (pv->pv_pmap == pm || pv->pv_pmap == pmap_kernel())) {
+ if (pm != kernel_pmap &&
+ (pv->pv_pmap == pm || pv->pv_pmap == kernel_pmap)) {
if ((uentries > 1 && uwritable) || uwritable > 1) {
/* user duplicate mapping */
- if (pv->pv_pmap != pmap_kernel())
+ if (pv->pv_pmap != kernel_pmap)
pv->pv_flags |= PVF_MWC;
if (!(pv->pv_flags & PVF_NC)) {
@@ -1279,7 +1279,7 @@ pmap_fix_cache(struct vm_page *pg, pmap_t pm, vm_offset_t va)
if ((kwritable && (entries || kentries > 1)) ||
(kwritable > 1) ||
((kwritable != writable) && kentries &&
- (pv->pv_pmap == pmap_kernel() ||
+ (pv->pv_pmap == kernel_pmap ||
(pv->pv_flags & PVF_WRITE) ||
(pv->pv_flags & PVF_MWC)))) {
@@ -1291,7 +1291,7 @@ pmap_fix_cache(struct vm_page *pg, pmap_t pm, vm_offset_t va)
}
/* kernel and user are cachable */
- if ((pm == pmap_kernel()) && !(pv->pv_flags & PVF_MWC) &&
+ if ((pm == kernel_pmap) && !(pv->pv_flags & PVF_MWC) &&
(pv->pv_flags & PVF_NC)) {
pv->pv_flags &= ~PVF_NC;
@@ -1300,8 +1300,8 @@ pmap_fix_cache(struct vm_page *pg, pmap_t pm, vm_offset_t va)
continue;
}
/* user is no longer sharable and writable */
- if (pm != pmap_kernel() &&
- (pv->pv_pmap == pm || pv->pv_pmap == pmap_kernel()) &&
+ if (pm != kernel_pmap &&
+ (pv->pv_pmap == pm || pv->pv_pmap == kernel_pmap) &&
!pmwc && (pv->pv_flags & PVF_NC)) {
pv->pv_flags &= ~(PVF_NC | PVF_MWC);
@@ -1565,7 +1565,7 @@ vector_page_setprot(int prot)
struct l2_bucket *l2b;
pt_entry_t *ptep;
- l2b = pmap_get_l2_bucket(pmap_kernel(), vector_page);
+ l2b = pmap_get_l2_bucket(kernel_pmap, vector_page);
ptep = &l2b->l2b_kva[l2pte_index(vector_page)];
@@ -1603,7 +1603,7 @@ pmap_nuke_pv(struct vm_page *pg, pmap_t pm, struct pv_entry *pve)
pg->md.pvh_attrs &= ~PVF_REF;
else
vm_page_aflag_set(pg, PGA_REFERENCED);
- if ((pve->pv_flags & PVF_NC) && ((pm == pmap_kernel()) ||
+ if ((pve->pv_flags & PVF_NC) && ((pm == kernel_pmap) ||
(pve->pv_flags & PVF_WRITE) || !(pve->pv_flags & PVF_MWC)))
pmap_fix_cache(pg, pm, 0);
else if (pve->pv_flags & PVF_WRITE) {
@@ -1972,7 +1972,7 @@ pmap_postinit(void)
pl1pt = (pd_entry_t *)va;
while (va < eva) {
- l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ l2b = pmap_get_l2_bucket(kernel_pmap, va);
ptep = &l2b->l2b_kva[l2pte_index(va)];
pte = *ptep;
pte = (pte & ~L2_S_CACHE_MASK) | pte_l2_s_cache_mode_pt;
@@ -2122,7 +2122,7 @@ pmap_alloc_specials(vm_offset_t *availp, int pages, vm_offset_t *vap,
struct l2_bucket *l2b;
if (ptep) {
- l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ l2b = pmap_get_l2_bucket(kernel_pmap, va);
if (l2b == NULL)
panic("pmap_alloc_specials: no l2b for 0x%x", va);
@@ -2381,7 +2381,7 @@ pmap_grow_map(vm_offset_t va, pt_entry_t cache_mode, vm_paddr_t *pap)
if (pap)
*pap = pa;
- l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ l2b = pmap_get_l2_bucket(kernel_pmap, va);
ptep = &l2b->l2b_kva[l2pte_index(va)];
*ptep = L2_S_PROTO | pa | cache_mode |
@@ -2494,7 +2494,7 @@ pmap_grow_l2_bucket(pmap_t pm, vm_offset_t va)
void
pmap_growkernel(vm_offset_t addr)
{
- pmap_t kpm = pmap_kernel();
+ pmap_t kpm = kernel_pmap;
if (addr <= pmap_curmaxkvaddr)
return; /* we are OK */
@@ -2654,9 +2654,9 @@ pmap_kenter_internal(vm_offset_t va, vm_offset_t pa, int flags)
(uint32_t) va, (uint32_t) pa));
- l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ l2b = pmap_get_l2_bucket(kernel_pmap, va);
if (l2b == NULL)
- l2b = pmap_grow_l2_bucket(pmap_kernel(), va);
+ l2b = pmap_grow_l2_bucket(kernel_pmap, va);
KASSERT(l2b != NULL, ("No L2 Bucket"));
pte = &l2b->l2b_kva[l2pte_index(va)];
opte = *pte;
@@ -2690,11 +2690,11 @@ pmap_kenter_internal(vm_offset_t va, vm_offset_t pa, int flags)
if (!TAILQ_EMPTY(&m->md.pv_list) || m->md.pv_kva != 0) {
if ((pve = pmap_get_pv_entry()) == NULL)
panic("pmap_kenter_internal: no pv entries");
- PMAP_LOCK(pmap_kernel());
- pmap_enter_pv(m, pve, pmap_kernel(), va,
+ PMAP_LOCK(kernel_pmap);
+ pmap_enter_pv(m, pve, kernel_pmap, va,
PVF_WRITE | PVF_UNMAN);
- pmap_fix_cache(m, pmap_kernel(), va);
- PMAP_UNLOCK(pmap_kernel());
+ pmap_fix_cache(m, kernel_pmap, va);
+ PMAP_UNLOCK(kernel_pmap);
} else {
m->md.pv_kva = va;
}
@@ -2758,7 +2758,7 @@ pmap_kenter_user(vm_offset_t va, vm_paddr_t pa)
* at the first use of the new address, or bad things will happen,
* as we use one of these addresses in the exception handlers.
*/
- pmap_fault_fixup(pmap_kernel(), va, VM_PROT_READ|VM_PROT_WRITE, 1);
+ pmap_fault_fixup(kernel_pmap, va, VM_PROT_READ|VM_PROT_WRITE, 1);
}
vm_paddr_t
@@ -2780,7 +2780,7 @@ pmap_kremove(vm_offset_t va)
vm_page_t m;
vm_offset_t pa;
- l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ l2b = pmap_get_l2_bucket(kernel_pmap, va);
if (!l2b)
return;
KASSERT(l2b != NULL, ("No L2 Bucket"));
@@ -2796,11 +2796,11 @@ pmap_kremove(vm_offset_t va)
* before the pvzone is initialized.
*/
rw_wlock(&pvh_global_lock);
- PMAP_LOCK(pmap_kernel());
+ PMAP_LOCK(kernel_pmap);
if (pvzone != NULL && (m = vm_phys_paddr_to_vm_page(pa)) &&
- (pve = pmap_remove_pv(m, pmap_kernel(), va)))
+ (pve = pmap_remove_pv(m, kernel_pmap, va)))
pmap_free_pv_entry(pve);
- PMAP_UNLOCK(pmap_kernel());
+ PMAP_UNLOCK(kernel_pmap);
rw_wunlock(&pvh_global_lock);
va = va & ~PAGE_MASK;
cpu_dcache_wbinv_range(va, PAGE_SIZE);
@@ -3027,7 +3027,7 @@ pmap_remove_all(vm_page_t m)
curpm = vmspace_pmap(curproc->p_vmspace);
while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
if (flush == FALSE && (pv->pv_pmap == curpm ||
- pv->pv_pmap == pmap_kernel()))
+ pv->pv_pmap == kernel_pmap))
flush = TRUE;
PMAP_LOCK(pv->pv_pmap);
@@ -3239,7 +3239,7 @@ pmap_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
PDEBUG(1, printf("pmap_enter: pmap = %08x, va = %08x, m = %08x, prot = %x, "
"flags = %x\n", (uint32_t) pmap, va, (uint32_t) m, prot, flags));
- if (pmap == pmap_kernel()) {
+ if (pmap == kernel_pmap) {
l2b = pmap_get_l2_bucket(pmap, va);
if (l2b == NULL)
l2b = pmap_grow_l2_bucket(pmap, va);
@@ -3414,7 +3414,7 @@ do_l2b_alloc:
/*
* Make sure userland mappings get the right permissions
*/
- if (pmap != pmap_kernel() && va != vector_page) {
+ if (pmap != kernel_pmap && va != vector_page) {
npte |= L2_S_PROT_U;
}
@@ -3672,9 +3672,9 @@ retry:
l1pd = pmap->pm_l1->l1_kva[l1idx];
if (l1pte_section_p(l1pd)) {
/*
- * These should only happen for pmap_kernel()
+ * These should only happen for kernel_pmap
*/
- KASSERT(pmap == pmap_kernel(), ("huh"));
+ KASSERT(pmap == kernel_pmap, ("huh"));
/* XXX: what to do about the bits > 32 ? */
if (l1pd & L1_S_SUPERSEC)
pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET);
@@ -4034,7 +4034,7 @@ pmap_use_minicache(vm_offset_t va, vm_size_t size)
if (next_bucket > eva)
next_bucket = eva;
- l2b = pmap_get_l2_bucket(pmap_kernel(), va);
+ l2b = pmap_get_l2_bucket(kernel_pmap, va);
sptep = ptep = &l2b->l2b_kva[l2pte_index(va)];
@@ -4137,10 +4137,10 @@ pmap_clean_page(struct pv_entry *pv, boolean_t is_src)
if (curthread)
pm = vmspace_pmap(curproc->p_vmspace);
else
- pm = pmap_kernel();
+ pm = kernel_pmap;
for (npv = pv; npv; npv = TAILQ_NEXT(npv, pv_list)) {
- if (npv->pv_pmap == pmap_kernel() || npv->pv_pmap == pm) {
+ if (npv->pv_pmap == kernel_pmap || npv->pv_pmap == pm) {
flags |= npv->pv_flags;
/*
* The page is mapped non-cacheable in
diff --git a/sys/arm/arm/swtch-v4.S b/sys/arm/arm/swtch-v4.S
new file mode 100644
index 000000000000..6fdbeed197c2
--- /dev/null
+++ b/sys/arm/arm/swtch-v4.S
@@ -0,0 +1,377 @@
+/* $NetBSD: cpuswitch.S,v 1.41 2003/11/15 08:44:18 scw Exp $ */
+
+/*-
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * cpuswitch.S
+ *
+ * cpu switching functions
+ *
+ * Created : 15/10/94
+ *
+ */
+
+#include "assym.s"
+#include "opt_sched.h"
+
+#include <machine/acle-compat.h>
+#include <machine/asm.h>
+#include <machine/asmacros.h>
+#include <machine/armreg.h>
+#include <machine/vfp.h>
+
+__FBSDID("$FreeBSD$");
+
+
+#define GET_PCPU(tmp, tmp2) \
+ ldr tmp, .Lcurpcpu
+
+#ifdef VFP
+ .fpu vfp /* allow VFP instructions */
+#endif
+
+.Lcurpcpu:
+ .word _C_LABEL(__pcpu)
+.Lblocked_lock:
+ .word _C_LABEL(blocked_lock)
+
+
+#define DOMAIN_CLIENT 0x01
+
+.Lcpufuncs:
+ .word _C_LABEL(cpufuncs)
+
+/*
+ * cpu_throw(oldtd, newtd)
+ *
+ * Remove current thread state, then select the next thread to run
+ * and load its state.
+ * r0 = oldtd
+ * r1 = newtd
+ */
+ENTRY(cpu_throw)
+ mov r5, r1
+
+ /*
+ * r0 = oldtd
+ * r5 = newtd
+ */
+
+#ifdef VFP /* This thread is dying, disable */
+ bl _C_LABEL(vfp_discard) /* VFP without preserving state. */
+#endif
+
+ GET_PCPU(r7, r9)
+ ldr r7, [r5, #(TD_PCB)] /* r7 = new thread's PCB */
+
+ /* Switch to lwp0 context */
+
+ ldr r9, .Lcpufuncs
+ mov lr, pc
+ ldr pc, [r9, #CF_IDCACHE_WBINV_ALL]
+ ldr r0, [r7, #(PCB_PL1VEC)]
+ ldr r1, [r7, #(PCB_DACR)]
+ /*
+ * r0 = Pointer to L1 slot for vector_page (or NULL)
+ * r1 = lwp0's DACR
+ * r5 = lwp0
+ * r7 = lwp0's PCB
+ * r9 = cpufuncs
+ */
+
+ /*
+ * Ensure the vector table is accessible by fixing up lwp0's L1
+ */
+ cmp r0, #0 /* No need to fixup vector table? */
+ ldrne r3, [r0] /* But if yes, fetch current value */
+ ldrne r2, [r7, #(PCB_L1VEC)] /* Fetch new vector_page value */
+ mcr p15, 0, r1, c3, c0, 0 /* Update DACR for lwp0's context */
+ cmpne r3, r2 /* Stuffing the same value? */
+ strne r2, [r0] /* Store if not. */
+
+#ifdef PMAP_INCLUDE_PTE_SYNC
+ /*
+ * Need to sync the cache to make sure that last store is
+ * visible to the MMU.
+ */
+ movne r1, #4
+ movne lr, pc
+ ldrne pc, [r9, #CF_DCACHE_WB_RANGE]
+#endif /* PMAP_INCLUDE_PTE_SYNC */
+
+ /*
+ * Note: We don't do the same optimisation as cpu_switch() with
+ * respect to avoiding flushing the TLB if we're switching to
+ * the same L1 since this process' VM space may be about to go
+ * away, so we don't want *any* turds left in the TLB.
+ */
+
+ /* Switch the memory to the new process */
+ ldr r0, [r7, #(PCB_PAGEDIR)]
+ mov lr, pc
+ ldr pc, [r9, #CF_CONTEXT_SWITCH]
+
+ GET_PCPU(r6, r4)
+ /* Hook in a new pcb */
+ str r7, [r6, #PC_CURPCB]
+ /* We have a new curthread now so make a note it */
+ str r5, [r6, #PC_CURTHREAD]
+
+ /* Set the new tp */
+ ldr r6, [r5, #(TD_MD + MD_TP)]
+ ldr r4, =ARM_TP_ADDRESS
+ str r6, [r4]
+ ldr r6, [r5, #(TD_MD + MD_RAS_START)]
+ str r6, [r4, #4] /* ARM_RAS_START */
+ ldr r6, [r5, #(TD_MD + MD_RAS_END)]
+ str r6, [r4, #8] /* ARM_RAS_END */
+
+ /* Restore all the saved registers and exit */
+ add r3, r7, #PCB_R4
+ ldmia r3, {r4-r12, sp, pc}
+END(cpu_throw)
+
+/*
+ * cpu_switch(oldtd, newtd, lock)
+ *
+ * Save the current thread state, then select the next thread to run
+ * and load its state.
+ * r0 = oldtd
+ * r1 = newtd
+ * r2 = lock (new lock for old thread)
+ */
+ENTRY(cpu_switch)
+ /* Interrupts are disabled. */
+ /* Save all the registers in the old thread's pcb. */
+ ldr r3, [r0, #(TD_PCB)]
+
+ /* Restore all the saved registers and exit */
+ add r3, #(PCB_R4)
+ stmia r3, {r4-r12, sp, lr, pc}
+
+ mov r6, r2 /* Save the mutex */
+
+ /* rem: r0 = old lwp */
+ /* rem: interrupts are disabled */
+
+ /* Process is now on a processor. */
+ /* We have a new curthread now so make a note it */
+ GET_PCPU(r7, r2)
+ str r1, [r7, #PC_CURTHREAD]
+
+ /* Hook in a new pcb */
+ ldr r2, [r1, #TD_PCB]
+ str r2, [r7, #PC_CURPCB]
+
+ /* Stage two : Save old context */
+
+ /* Get the user structure for the old thread. */
+ ldr r2, [r0, #(TD_PCB)]
+ mov r4, r0 /* Save the old thread. */
+
+ /* Store the old tp; userland can change it on armv4. */
+ ldr r3, =ARM_TP_ADDRESS
+ ldr r9, [r3]
+ str r9, [r0, #(TD_MD + MD_TP)]
+ ldr r9, [r3, #4]
+ str r9, [r0, #(TD_MD + MD_RAS_START)]
+ ldr r9, [r3, #8]
+ str r9, [r0, #(TD_MD + MD_RAS_END)]
+
+ /* Set the new tp */
+ ldr r9, [r1, #(TD_MD + MD_TP)]
+ str r9, [r3]
+ ldr r9, [r1, #(TD_MD + MD_RAS_START)]
+ str r9, [r3, #4]
+ ldr r9, [r1, #(TD_MD + MD_RAS_END)]
+ str r9, [r3, #8]
+
+ /* Get the user structure for the new process in r9 */
+ ldr r9, [r1, #(TD_PCB)]
+
+ /* rem: r2 = old PCB */
+ /* rem: r9 = new PCB */
+ /* rem: interrupts are enabled */
+
+#ifdef VFP
+ fmrx r0, fpexc /* If the VFP is enabled */
+ tst r0, #(VFPEXC_EN) /* the current thread has */
+ movne r1, #1 /* used it, so go save */
+ addne r0, r2, #(PCB_VFPSTATE) /* the state into the PCB */
+ blne _C_LABEL(vfp_store) /* and disable the VFP. */
+#endif
+
+ /* r0-r3 now free! */
+
+ /* Third phase : restore saved context */
+
+ /* rem: r2 = old PCB */
+ /* rem: r9 = new PCB */
+
+ ldr r5, [r9, #(PCB_DACR)] /* r5 = new DACR */
+ mov r2, #DOMAIN_CLIENT
+ cmp r5, r2, lsl #(PMAP_DOMAIN_KERNEL * 2) /* Sw to kernel thread? */
+ beq .Lcs_context_switched /* Yup. Don't flush cache */
+ mrc p15, 0, r0, c3, c0, 0 /* r0 = old DACR */
+ /*
+ * Get the new L1 table pointer into r11. If we're switching to
+ * an LWP with the same address space as the outgoing one, we can
+ * skip the cache purge and the TTB load.
+ *
+ * To avoid data dep stalls that would happen anyway, we try
+ * and get some useful work done in the mean time.
+ */
+ mrc p15, 0, r10, c2, c0, 0 /* r10 = old L1 */
+ ldr r11, [r9, #(PCB_PAGEDIR)] /* r11 = new L1 */
+
+ teq r10, r11 /* Same L1? */
+ cmpeq r0, r5 /* Same DACR? */
+ beq .Lcs_context_switched /* yes! */
+
+ /*
+ * Definately need to flush the cache.
+ */
+
+ ldr r1, .Lcpufuncs
+ mov lr, pc
+ ldr pc, [r1, #CF_IDCACHE_WBINV_ALL]
+
+.Lcs_cache_purge_skipped:
+ /* rem: r6 = lock */
+ /* rem: r9 = new PCB */
+ /* rem: r10 = old L1 */
+ /* rem: r11 = new L1 */
+
+ mov r2, #0x00000000
+ ldr r7, [r9, #(PCB_PL1VEC)]
+
+ /*
+ * Ensure the vector table is accessible by fixing up the L1
+ */
+ cmp r7, #0 /* No need to fixup vector table? */
+ ldrne r2, [r7] /* But if yes, fetch current value */
+ ldrne r0, [r9, #(PCB_L1VEC)] /* Fetch new vector_page value */
+ mcr p15, 0, r5, c3, c0, 0 /* Update DACR for new context */
+ cmpne r2, r0 /* Stuffing the same value? */
+#ifndef PMAP_INCLUDE_PTE_SYNC
+ strne r0, [r7] /* Nope, update it */
+#else
+ beq .Lcs_same_vector
+ str r0, [r7] /* Otherwise, update it */
+
+ /*
+ * Need to sync the cache to make sure that last store is
+ * visible to the MMU.
+ */
+ ldr r2, .Lcpufuncs
+ mov r0, r7
+ mov r1, #4
+ mov lr, pc
+ ldr pc, [r2, #CF_DCACHE_WB_RANGE]
+
+.Lcs_same_vector:
+#endif /* PMAP_INCLUDE_PTE_SYNC */
+
+ cmp r10, r11 /* Switching to the same L1? */
+ ldr r10, .Lcpufuncs
+ beq .Lcs_same_l1 /* Yup. */
+ /*
+ * Do a full context switch, including full TLB flush.
+ */
+ mov r0, r11
+ mov lr, pc
+ ldr pc, [r10, #CF_CONTEXT_SWITCH]
+
+ b .Lcs_context_switched
+
+ /*
+ * We're switching to a different process in the same L1.
+ * In this situation, we only need to flush the TLB for the
+ * vector_page mapping, and even then only if r7 is non-NULL.
+ */
+.Lcs_same_l1:
+ cmp r7, #0
+ movne r0, #0 /* We *know* vector_page's VA is 0x0 */
+ movne lr, pc
+ ldrne pc, [r10, #CF_TLB_FLUSHID_SE]
+
+.Lcs_context_switched:
+
+ /* Release the old thread */
+ str r6, [r4, #TD_LOCK]
+
+ /* XXXSCW: Safe to re-enable FIQs here */
+
+ /* rem: r9 = new PCB */
+
+ /* Restore all the saved registers and exit */
+ add r3, r9, #PCB_R4
+ ldmia r3, {r4-r12, sp, pc}
+END(cpu_switch)
diff --git a/sys/arm/arm/swtch-v6.S b/sys/arm/arm/swtch-v6.S
new file mode 100644
index 000000000000..ef2156a4f121
--- /dev/null
+++ b/sys/arm/arm/swtch-v6.S
@@ -0,0 +1,482 @@
+/* $NetBSD: cpuswitch.S,v 1.41 2003/11/15 08:44:18 scw Exp $ */
+
+/*-
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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.
+ *
+ * RiscBSD kernel project
+ *
+ * cpuswitch.S
+ *
+ * cpu switching functions
+ *
+ * Created : 15/10/94
+ *
+ */
+
+#include "assym.s"
+#include "opt_sched.h"
+
+#include <machine/acle-compat.h>
+#include <machine/asm.h>
+#include <machine/asmacros.h>
+#include <machine/armreg.h>
+#include <machine/sysreg.h>
+#include <machine/vfp.h>
+
+__FBSDID("$FreeBSD$");
+
+#if defined(SMP)
+#define GET_PCPU(tmp, tmp2) \
+ mrc CP15_MPIDR(tmp); \
+ and tmp, tmp, #0xf; \
+ ldr tmp2, .Lcurpcpu+4; \
+ mul tmp, tmp, tmp2; \
+ ldr tmp2, .Lcurpcpu; \
+ add tmp, tmp, tmp2;
+#else
+
+#define GET_PCPU(tmp, tmp2) \
+ ldr tmp, .Lcurpcpu
+#endif
+
+#ifdef VFP
+ .fpu vfp /* allow VFP instructions */
+#endif
+
+.Lcurpcpu:
+ .word _C_LABEL(__pcpu)
+ .word PCPU_SIZE
+.Lblocked_lock:
+ .word _C_LABEL(blocked_lock)
+
+ENTRY(cpu_context_switch) /* QQQ: What about macro instead of function? */
+ DSB
+ mcr CP15_TTBR0(r0) /* set the new TTB */
+ ISB
+ mov r0, #(CPU_ASID_KERNEL)
+ mcr CP15_TLBIASID(r0) /* flush not global TLBs */
+ /*
+ * Flush entire Branch Target Cache because of the branch predictor
+ * is not architecturally invisible. See ARM Architecture Reference
+ * Manual ARMv7-A and ARMv7-R edition, page B2-1264(65), Branch
+ * predictors and Requirements for branch predictor maintenance
+ * operations sections.
+ *
+ * QQQ: The predictor is virtually addressed and holds virtual target
+ * addresses. Therefore, if mapping is changed, the predictor cache
+ * must be flushed.The flush is part of entire i-cache invalidation
+ * what is always called when code mapping is changed. So herein,
+ * it's the only place where standalone predictor flush must be
+ * executed in kernel (except self modifying code case).
+ */
+ mcr CP15_BPIALL /* flush entire Branch Target Cache */
+ DSB
+ mov pc, lr
+END(cpu_context_switch)
+
+/*
+ * cpu_throw(oldtd, newtd)
+ *
+ * Remove current thread state, then select the next thread to run
+ * and load its state.
+ * r0 = oldtd
+ * r1 = newtd
+ */
+ENTRY(cpu_throw)
+ mov r10, r0 /* r10 = oldtd */
+ mov r11, r1 /* r11 = newtd */
+
+#ifdef VFP /* This thread is dying, disable */
+ bl _C_LABEL(vfp_discard) /* VFP without preserving state. */
+#endif
+ GET_PCPU(r8, r9) /* r8 = current pcpu */
+ ldr r4, [r8, #PC_CPUID] /* r4 = current cpu id */
+
+ cmp r10, #0 /* old thread? */
+ beq 2f /* no, skip */
+
+ /* Remove this CPU from the active list. */
+ ldr r5, [r8, #PC_CURPMAP]
+ mov r0, #(PM_ACTIVE)
+ add r5, r0 /* r5 = old pm_active */
+
+ /* Compute position and mask. */
+#if _NCPUWORDS > 1
+ lsr r0, r4, #3
+ bic r0, #3
+ add r5, r0 /* r5 = position in old pm_active */
+ mov r2, #1
+ and r0, r4, #31
+ lsl r2, r0 /* r2 = mask */
+#else
+ mov r2, #1
+ lsl r2, r4 /* r2 = mask */
+#endif
+ /* Clear cpu from old active list. */
+#ifdef SMP
+1: ldrex r0, [r5]
+ bic r0, r2
+ strex r1, r0, [r5]
+ teq r1, #0
+ bne 1b
+#else
+ ldr r0, [r5]
+ bic r0, r2
+ str r0, [r5]
+#endif
+
+2:
+#ifdef INVARIANTS
+ cmp r11, #0 /* new thread? */
+ beq badsw1 /* no, panic */
+#endif
+ ldr r7, [r11, #(TD_PCB)] /* r7 = new PCB */
+
+ /*
+ * Registers at this point
+ * r4 = current cpu id
+ * r7 = new PCB
+ * r8 = current pcpu
+ * r11 = newtd
+ */
+
+ /* MMU switch to new thread. */
+ ldr r0, [r7, #(PCB_PAGEDIR)]
+#ifdef INVARIANTS
+ cmp r0, #0 /* new thread? */
+ beq badsw4 /* no, panic */
+#endif
+ bl _C_LABEL(cpu_context_switch)
+
+ /*
+ * Set new PMAP as current one.
+ * Insert cpu to new active list.
+ */
+
+ ldr r6, [r11, #(TD_PROC)] /* newtd->proc */
+ ldr r6, [r6, #(P_VMSPACE)] /* newtd->proc->vmspace */
+ add r6, #VM_PMAP /* newtd->proc->vmspace->pmap */
+ str r6, [r8, #PC_CURPMAP] /* store to curpmap */
+
+ mov r0, #PM_ACTIVE
+ add r6, r0 /* r6 = new pm_active */
+
+ /* compute position and mask */
+#if _NCPUWORDS > 1
+ lsr r0, r4, #3
+ bic r0, #3
+ add r6, r0 /* r6 = position in new pm_active */
+ mov r2, #1
+ and r0, r4, #31
+ lsl r2, r0 /* r2 = mask */
+#else
+ mov r2, #1
+ lsl r2, r4 /* r2 = mask */
+#endif
+ /* Set cpu to new active list. */
+#ifdef SMP
+1: ldrex r0, [r6]
+ orr r0, r2
+ strex r1, r0, [r6]
+ teq r1, #0
+ bne 1b
+#else
+ ldr r0, [r6]
+ orr r0, r2
+ str r0, [r6]
+#endif
+ /*
+ * Registers at this point.
+ * r7 = new PCB
+ * r8 = current pcpu
+ * r11 = newtd
+ * They must match the ones in sw1 position !!!
+ */
+ DMB
+ b sw1 /* share new thread init with cpu_switch() */
+END(cpu_throw)
+
+/*
+ * cpu_switch(oldtd, newtd, lock)
+ *
+ * Save the current thread state, then select the next thread to run
+ * and load its state.
+ * r0 = oldtd
+ * r1 = newtd
+ * r2 = lock (new lock for old thread)
+ */
+ENTRY(cpu_switch)
+ /* Interrupts are disabled. */
+#ifdef INVARIANTS
+ cmp r0, #0 /* old thread? */
+ beq badsw2 /* no, panic */
+#endif
+ /* Save all the registers in the old thread's pcb. */
+ ldr r3, [r0, #(TD_PCB)]
+ add r3, #(PCB_R4)
+ stmia r3, {r4-r12, sp, lr, pc}
+
+#ifdef INVARIANTS
+ cmp r1, #0 /* new thread? */
+ beq badsw3 /* no, panic */
+#endif
+ /*
+ * Save arguments. Note that we can now use r0-r14 until
+ * it is time to restore them for the new thread. However,
+ * some registers are not safe over function call.
+ */
+ mov r9, r2 /* r9 = lock */
+ mov r10, r0 /* r10 = oldtd */
+ mov r11, r1 /* r11 = newtd */
+
+ GET_PCPU(r8, r3) /* r8 = current PCPU */
+ ldr r7, [r11, #(TD_PCB)] /* r7 = newtd->td_pcb */
+
+
+
+#ifdef VFP
+ ldr r3, [r10, #(TD_PCB)]
+ fmrx r0, fpexc /* If the VFP is enabled */
+ tst r0, #(VFPEXC_EN) /* the current thread has */
+ movne r1, #1 /* used it, so go save */
+ addne r0, r3, #(PCB_VFPSTATE) /* the state into the PCB */
+ blne _C_LABEL(vfp_store) /* and disable the VFP. */
+#endif
+
+ /*
+ * MMU switch. If we're switching to a thread with the same
+ * address space as the outgoing one, we can skip the MMU switch.
+ */
+ mrc CP15_TTBR0(r1) /* r1 = old TTB */
+ ldr r0, [r7, #(PCB_PAGEDIR)] /* r0 = new TTB */
+ cmp r0, r1 /* Switching to the TTB? */
+ beq sw0 /* same TTB, skip */
+
+#ifdef INVARIANTS
+ cmp r0, #0 /* new thread? */
+ beq badsw4 /* no, panic */
+#endif
+
+ bl cpu_context_switch /* new TTB as argument */
+
+ /*
+ * Registers at this point
+ * r7 = new PCB
+ * r8 = current pcpu
+ * r9 = lock
+ * r10 = oldtd
+ * r11 = newtd
+ */
+
+ /*
+ * Set new PMAP as current one.
+ * Update active list on PMAPs.
+ */
+ ldr r6, [r11, #TD_PROC] /* newtd->proc */
+ ldr r6, [r6, #P_VMSPACE] /* newtd->proc->vmspace */
+ add r6, #VM_PMAP /* newtd->proc->vmspace->pmap */
+
+ ldr r5, [r8, #PC_CURPMAP] /* get old curpmap */
+ str r6, [r8, #PC_CURPMAP] /* and save new one */
+
+ mov r0, #PM_ACTIVE
+ add r5, r0 /* r5 = old pm_active */
+ add r6, r0 /* r6 = new pm_active */
+
+ /* Compute position and mask. */
+ ldr r4, [r8, #PC_CPUID]
+#if _NCPUWORDS > 1
+ lsr r0, r4, #3
+ bic r0, #3
+ add r5, r0 /* r5 = position in old pm_active */
+ add r6, r0 /* r6 = position in new pm_active */
+ mov r2, #1
+ and r0, r4, #31
+ lsl r2, r0 /* r2 = mask */
+#else
+ mov r2, #1
+ lsl r2, r4 /* r2 = mask */
+#endif
+ /* Clear cpu from old active list. */
+#ifdef SMP
+1: ldrex r0, [r5]
+ bic r0, r2
+ strex r1, r0, [r5]
+ teq r1, #0
+ bne 1b
+#else
+ ldr r0, [r5]
+ bic r0, r2
+ str r0, [r5]
+#endif
+ /* Set cpu to new active list. */
+#ifdef SMP
+1: ldrex r0, [r6]
+ orr r0, r2
+ strex r1, r0, [r6]
+ teq r1, #0
+ bne 1b
+#else
+ ldr r0, [r6]
+ orr r0, r2
+ str r0, [r6]
+#endif
+
+sw0:
+ /*
+ * Registers at this point
+ * r7 = new PCB
+ * r8 = current pcpu
+ * r9 = lock
+ * r10 = oldtd
+ * r11 = newtd
+ */
+
+ /* Change the old thread lock. */
+ add r5, r10, #TD_LOCK
+ DMB
+1: ldrex r0, [r5]
+ strex r1, r9, [r5]
+ teq r1, #0
+ bne 1b
+ DMB
+
+sw1:
+ clrex
+ /*
+ * Registers at this point
+ * r7 = new PCB
+ * r8 = current pcpu
+ * r11 = newtd
+ */
+
+#if defined(SMP) && defined(SCHED_ULE)
+ /*
+ * 386 and amd64 do the blocked lock test only for SMP and SCHED_ULE
+ * QQQ: What does it mean in reality and why is it done?
+ */
+ ldr r6, =blocked_lock
+1:
+ ldr r3, [r11, #TD_LOCK] /* atomic write regular read */
+ cmp r3, r6
+ beq 1b
+#endif
+ /* Set the new tls */
+ ldr r0, [r11, #(TD_MD + MD_TP)]
+ mcr CP15_TPIDRURO(r0) /* write tls thread reg 2 */
+
+ /* We have a new curthread now so make a note it */
+ str r11, [r8, #PC_CURTHREAD]
+ mcr CP15_TPIDRPRW(r11)
+
+ /* store pcb in per cpu structure */
+ str r7, [r8, #PC_CURPCB]
+
+ /*
+ * Restore all saved registers and return. Note that some saved
+ * registers can be changed when either cpu_fork(), cpu_set_upcall(),
+ * cpu_set_fork_handler(), or makectx() was called.
+ */
+ add r3, r7, #PCB_R4
+ ldmia r3, {r4-r12, sp, pc}
+
+#ifdef INVARIANTS
+badsw1:
+ ldr r0, =sw1_panic_str
+ bl _C_LABEL(panic)
+1: nop
+ b 1b
+
+badsw2:
+ ldr r0, =sw2_panic_str
+ bl _C_LABEL(panic)
+1: nop
+ b 1b
+
+badsw3:
+ ldr r0, =sw3_panic_str
+ bl _C_LABEL(panic)
+1: nop
+ b 1b
+
+badsw4:
+ ldr r0, =sw4_panic_str
+ bl _C_LABEL(panic)
+1: nop
+ b 1b
+
+sw1_panic_str:
+ .asciz "cpu_throw: no newthread supplied.\n"
+sw2_panic_str:
+ .asciz "cpu_switch: no curthread supplied.\n"
+sw3_panic_str:
+ .asciz "cpu_switch: no newthread supplied.\n"
+sw4_panic_str:
+ .asciz "cpu_switch: new pagedir is NULL.\n"
+#endif
+END(cpu_switch)
diff --git a/sys/arm/arm/swtch.S b/sys/arm/arm/swtch.S
index ee6368553bcc..e70532a447e2 100644
--- a/sys/arm/arm/swtch.S
+++ b/sys/arm/arm/swtch.S
@@ -79,9 +79,7 @@
*/
#include "assym.s"
-#include "opt_sched.h"
-#include <machine/acle-compat.h>
#include <machine/asm.h>
#include <machine/asmacros.h>
#include <machine/armreg.h>
@@ -89,708 +87,10 @@
__FBSDID("$FreeBSD$");
-#if __ARM_ARCH >= 6 && defined(SMP)
-#define GET_PCPU(tmp, tmp2) \
- mrc p15, 0, tmp, c0, c0, 5; \
- and tmp, tmp, #0xf; \
- ldr tmp2, .Lcurpcpu+4; \
- mul tmp, tmp, tmp2; \
- ldr tmp2, .Lcurpcpu; \
- add tmp, tmp, tmp2;
-#else
-
-#define GET_PCPU(tmp, tmp2) \
- ldr tmp, .Lcurpcpu
-#endif
-
#ifdef VFP
.fpu vfp /* allow VFP instructions */
#endif
-.Lcurpcpu:
- .word _C_LABEL(__pcpu)
- .word PCPU_SIZE
-.Lblocked_lock:
- .word _C_LABEL(blocked_lock)
-
-
-#ifndef ARM_NEW_PMAP
-
-#define DOMAIN_CLIENT 0x01
-
-.Lcpufuncs:
- .word _C_LABEL(cpufuncs)
-
-/*
- * cpu_throw(oldtd, newtd)
- *
- * Remove current thread state, then select the next thread to run
- * and load its state.
- * r0 = oldtd
- * r1 = newtd
- */
-ENTRY(cpu_throw)
- mov r5, r1
-
- /*
- * r0 = oldtd
- * r5 = newtd
- */
-
-#ifdef VFP /* This thread is dying, disable */
- bl _C_LABEL(vfp_discard) /* VFP without preserving state. */
-#endif
-
- GET_PCPU(r7, r9)
- ldr r7, [r5, #(TD_PCB)] /* r7 = new thread's PCB */
-
- /* Switch to lwp0 context */
-
- ldr r9, .Lcpufuncs
-#if !defined(CPU_ARM11) && !defined(CPU_CORTEXA) && !defined(CPU_MV_PJ4B) && !defined(CPU_KRAIT)
- mov lr, pc
- ldr pc, [r9, #CF_IDCACHE_WBINV_ALL]
-#endif
- ldr r0, [r7, #(PCB_PL1VEC)]
- ldr r1, [r7, #(PCB_DACR)]
- /*
- * r0 = Pointer to L1 slot for vector_page (or NULL)
- * r1 = lwp0's DACR
- * r5 = lwp0
- * r7 = lwp0's PCB
- * r9 = cpufuncs
- */
-
- /*
- * Ensure the vector table is accessible by fixing up lwp0's L1
- */
- cmp r0, #0 /* No need to fixup vector table? */
- ldrne r3, [r0] /* But if yes, fetch current value */
- ldrne r2, [r7, #(PCB_L1VEC)] /* Fetch new vector_page value */
- mcr p15, 0, r1, c3, c0, 0 /* Update DACR for lwp0's context */
- cmpne r3, r2 /* Stuffing the same value? */
- strne r2, [r0] /* Store if not. */
-
-#ifdef PMAP_INCLUDE_PTE_SYNC
- /*
- * Need to sync the cache to make sure that last store is
- * visible to the MMU.
- */
- movne r1, #4
- movne lr, pc
- ldrne pc, [r9, #CF_DCACHE_WB_RANGE]
-#endif /* PMAP_INCLUDE_PTE_SYNC */
-
- /*
- * Note: We don't do the same optimisation as cpu_switch() with
- * respect to avoiding flushing the TLB if we're switching to
- * the same L1 since this process' VM space may be about to go
- * away, so we don't want *any* turds left in the TLB.
- */
-
- /* Switch the memory to the new process */
- ldr r0, [r7, #(PCB_PAGEDIR)]
- mov lr, pc
- ldr pc, [r9, #CF_CONTEXT_SWITCH]
-
- GET_PCPU(r6, r4)
- /* Hook in a new pcb */
- str r7, [r6, #PC_CURPCB]
- /* We have a new curthread now so make a note it */
- str r5, [r6, #PC_CURTHREAD]
-#if __ARM_ARCH >= 6
- mcr p15, 0, r5, c13, c0, 4
-#endif
- /* Set the new tp */
- ldr r6, [r5, #(TD_MD + MD_TP)]
-#if __ARM_ARCH >= 6
- mcr p15, 0, r6, c13, c0, 3
-#else
- ldr r4, =ARM_TP_ADDRESS
- str r6, [r4]
- ldr r6, [r5, #(TD_MD + MD_RAS_START)]
- str r6, [r4, #4] /* ARM_RAS_START */
- ldr r6, [r5, #(TD_MD + MD_RAS_END)]
- str r6, [r4, #8] /* ARM_RAS_END */
-#endif
- /* Restore all the saved registers and exit */
- add r3, r7, #PCB_R4
- ldmia r3, {r4-r12, sp, pc}
-END(cpu_throw)
-
-/*
- * cpu_switch(oldtd, newtd, lock)
- *
- * Save the current thread state, then select the next thread to run
- * and load its state.
- * r0 = oldtd
- * r1 = newtd
- * r2 = lock (new lock for old thread)
- */
-ENTRY(cpu_switch)
- /* Interrupts are disabled. */
- /* Save all the registers in the old thread's pcb. */
- ldr r3, [r0, #(TD_PCB)]
-
- /* Restore all the saved registers and exit */
- add r3, #(PCB_R4)
- stmia r3, {r4-r12, sp, lr, pc}
-
- mov r6, r2 /* Save the mutex */
-
- /* rem: r0 = old lwp */
- /* rem: interrupts are disabled */
-
- /* Process is now on a processor. */
- /* We have a new curthread now so make a note it */
- GET_PCPU(r7, r2)
- str r1, [r7, #PC_CURTHREAD]
-#if __ARM_ARCH >= 6
- mcr p15, 0, r1, c13, c0, 4
-#endif
-
- /* Hook in a new pcb */
- ldr r2, [r1, #TD_PCB]
- str r2, [r7, #PC_CURPCB]
-
- /* Stage two : Save old context */
-
- /* Get the user structure for the old thread. */
- ldr r2, [r0, #(TD_PCB)]
- mov r4, r0 /* Save the old thread. */
-
-#if __ARM_ARCH >= 6
- /*
- * Set new tp. No need to store the old one first, userland can't
- * change it directly on armv6.
- */
- ldr r9, [r1, #(TD_MD + MD_TP)]
- mcr p15, 0, r9, c13, c0, 3
-#else
- /* Store the old tp; userland can change it on armv4. */
- ldr r3, =ARM_TP_ADDRESS
- ldr r9, [r3]
- str r9, [r0, #(TD_MD + MD_TP)]
- ldr r9, [r3, #4]
- str r9, [r0, #(TD_MD + MD_RAS_START)]
- ldr r9, [r3, #8]
- str r9, [r0, #(TD_MD + MD_RAS_END)]
-
- /* Set the new tp */
- ldr r9, [r1, #(TD_MD + MD_TP)]
- str r9, [r3]
- ldr r9, [r1, #(TD_MD + MD_RAS_START)]
- str r9, [r3, #4]
- ldr r9, [r1, #(TD_MD + MD_RAS_END)]
- str r9, [r3, #8]
-#endif
-
- /* Get the user structure for the new process in r9 */
- ldr r9, [r1, #(TD_PCB)]
-
- /* rem: r2 = old PCB */
- /* rem: r9 = new PCB */
- /* rem: interrupts are enabled */
-
-#ifdef VFP
- fmrx r0, fpexc /* If the VFP is enabled */
- tst r0, #(VFPEXC_EN) /* the current thread has */
- movne r1, #1 /* used it, so go save */
- addne r0, r2, #(PCB_VFPSTATE) /* the state into the PCB */
- blne _C_LABEL(vfp_store) /* and disable the VFP. */
-#endif
-
- /* r0-r3 now free! */
-
- /* Third phase : restore saved context */
-
- /* rem: r2 = old PCB */
- /* rem: r9 = new PCB */
-
- ldr r5, [r9, #(PCB_DACR)] /* r5 = new DACR */
- mov r2, #DOMAIN_CLIENT
- cmp r5, r2, lsl #(PMAP_DOMAIN_KERNEL * 2) /* Sw to kernel thread? */
- beq .Lcs_context_switched /* Yup. Don't flush cache */
- mrc p15, 0, r0, c3, c0, 0 /* r0 = old DACR */
- /*
- * Get the new L1 table pointer into r11. If we're switching to
- * an LWP with the same address space as the outgoing one, we can
- * skip the cache purge and the TTB load.
- *
- * To avoid data dep stalls that would happen anyway, we try
- * and get some useful work done in the mean time.
- */
- mrc p15, 0, r10, c2, c0, 0 /* r10 = old L1 */
- ldr r11, [r9, #(PCB_PAGEDIR)] /* r11 = new L1 */
-
- teq r10, r11 /* Same L1? */
- cmpeq r0, r5 /* Same DACR? */
- beq .Lcs_context_switched /* yes! */
-
-#if !defined(CPU_ARM11) && !defined(CPU_CORTEXA) && !defined(CPU_MV_PJ4B) && !defined(CPU_KRAIT)
- /*
- * Definately need to flush the cache.
- */
-
- ldr r1, .Lcpufuncs
- mov lr, pc
- ldr pc, [r1, #CF_IDCACHE_WBINV_ALL]
-#endif
-.Lcs_cache_purge_skipped:
- /* rem: r6 = lock */
- /* rem: r9 = new PCB */
- /* rem: r10 = old L1 */
- /* rem: r11 = new L1 */
-
- mov r2, #0x00000000
- ldr r7, [r9, #(PCB_PL1VEC)]
-
- /*
- * Ensure the vector table is accessible by fixing up the L1
- */
- cmp r7, #0 /* No need to fixup vector table? */
- ldrne r2, [r7] /* But if yes, fetch current value */
- ldrne r0, [r9, #(PCB_L1VEC)] /* Fetch new vector_page value */
- mcr p15, 0, r5, c3, c0, 0 /* Update DACR for new context */
- cmpne r2, r0 /* Stuffing the same value? */
-#ifndef PMAP_INCLUDE_PTE_SYNC
- strne r0, [r7] /* Nope, update it */
-#else
- beq .Lcs_same_vector
- str r0, [r7] /* Otherwise, update it */
-
- /*
- * Need to sync the cache to make sure that last store is
- * visible to the MMU.
- */
- ldr r2, .Lcpufuncs
- mov r0, r7
- mov r1, #4
- mov lr, pc
- ldr pc, [r2, #CF_DCACHE_WB_RANGE]
-
-.Lcs_same_vector:
-#endif /* PMAP_INCLUDE_PTE_SYNC */
-
- cmp r10, r11 /* Switching to the same L1? */
- ldr r10, .Lcpufuncs
- beq .Lcs_same_l1 /* Yup. */
- /*
- * Do a full context switch, including full TLB flush.
- */
- mov r0, r11
- mov lr, pc
- ldr pc, [r10, #CF_CONTEXT_SWITCH]
-
- b .Lcs_context_switched
-
- /*
- * We're switching to a different process in the same L1.
- * In this situation, we only need to flush the TLB for the
- * vector_page mapping, and even then only if r7 is non-NULL.
- */
-.Lcs_same_l1:
- cmp r7, #0
- movne r0, #0 /* We *know* vector_page's VA is 0x0 */
- movne lr, pc
- ldrne pc, [r10, #CF_TLB_FLUSHID_SE]
-
-.Lcs_context_switched:
-
- /* Release the old thread */
- str r6, [r4, #TD_LOCK]
-#if defined(SCHED_ULE) && defined(SMP)
- ldr r6, .Lblocked_lock
- GET_CURTHREAD_PTR(r3)
-1:
- ldr r4, [r3, #TD_LOCK]
- cmp r4, r6
- beq 1b
-#endif
-
- /* XXXSCW: Safe to re-enable FIQs here */
-
- /* rem: r9 = new PCB */
-
- /* Restore all the saved registers and exit */
- add r3, r9, #PCB_R4
- ldmia r3, {r4-r12, sp, pc}
-END(cpu_switch)
-
-
-#else /* !ARM_NEW_PMAP */
-#include <machine/sysreg.h>
-
-ENTRY(cpu_context_switch) /* QQQ: What about macro instead of function? */
- DSB
- mcr CP15_TTBR0(r0) /* set the new TTB */
- ISB
- mov r0, #(CPU_ASID_KERNEL)
- mcr CP15_TLBIASID(r0) /* flush not global TLBs */
- /*
- * Flush entire Branch Target Cache because of the branch predictor
- * is not architecturally invisible. See ARM Architecture Reference
- * Manual ARMv7-A and ARMv7-R edition, page B2-1264(65), Branch
- * predictors and Requirements for branch predictor maintenance
- * operations sections.
- *
- * QQQ: The predictor is virtually addressed and holds virtual target
- * addresses. Therefore, if mapping is changed, the predictor cache
- * must be flushed.The flush is part of entire i-cache invalidation
- * what is always called when code mapping is changed. So herein,
- * it's the only place where standalone predictor flush must be
- * executed in kernel (except self modifying code case).
- */
- mcr CP15_BPIALL /* and flush entire Branch Target Cache */
- DSB
- mov pc, lr
-END(cpu_context_switch)
-
-/*
- * cpu_throw(oldtd, newtd)
- *
- * Remove current thread state, then select the next thread to run
- * and load its state.
- * r0 = oldtd
- * r1 = newtd
- */
-ENTRY(cpu_throw)
- mov r10, r0 /* r10 = oldtd */
- mov r11, r1 /* r11 = newtd */
-
-#ifdef VFP /* This thread is dying, disable */
- bl _C_LABEL(vfp_discard) /* VFP without preserving state. */
-#endif
- GET_PCPU(r8, r9) /* r8 = current pcpu */
- ldr r4, [r8, #PC_CPUID] /* r4 = current cpu id */
-
- cmp r10, #0 /* old thread? */
- beq 2f /* no, skip */
-
- /* Remove this CPU from the active list. */
- ldr r5, [r8, #PC_CURPMAP]
- mov r0, #(PM_ACTIVE)
- add r5, r0 /* r5 = old pm_active */
-
- /* Compute position and mask. */
-#if _NCPUWORDS > 1
- lsr r0, r4, #3
- bic r0, #3
- add r5, r0 /* r5 = position in old pm_active */
- mov r2, #1
- and r0, r4, #31
- lsl r2, r0 /* r2 = mask */
-#else
- mov r2, #1
- lsl r2, r4 /* r2 = mask */
-#endif
- /* Clear cpu from old active list. */
-#ifdef SMP
-1: ldrex r0, [r5]
- bic r0, r2
- strex r1, r0, [r5]
- teq r1, #0
- bne 1b
-#else
- ldr r0, [r5]
- bic r0, r2
- str r0, [r5]
-#endif
-
-2:
-#ifdef INVARIANTS
- cmp r11, #0 /* new thread? */
- beq badsw1 /* no, panic */
-#endif
- ldr r7, [r11, #(TD_PCB)] /* r7 = new PCB */
-
- /*
- * Registers at this point
- * r4 = current cpu id
- * r7 = new PCB
- * r8 = current pcpu
- * r11 = newtd
- */
-
- /* MMU switch to new thread. */
- ldr r0, [r7, #(PCB_PAGEDIR)]
-#ifdef INVARIANTS
- cmp r0, #0 /* new thread? */
- beq badsw4 /* no, panic */
-#endif
- bl _C_LABEL(cpu_context_switch)
-
- /*
- * Set new PMAP as current one.
- * Insert cpu to new active list.
- */
-
- ldr r6, [r11, #(TD_PROC)] /* newtd->proc */
- ldr r6, [r6, #(P_VMSPACE)] /* newtd->proc->vmspace */
- add r6, #VM_PMAP /* newtd->proc->vmspace->pmap */
- str r6, [r8, #PC_CURPMAP] /* store to curpmap */
-
- mov r0, #PM_ACTIVE
- add r6, r0 /* r6 = new pm_active */
-
- /* compute position and mask */
-#if _NCPUWORDS > 1
- lsr r0, r4, #3
- bic r0, #3
- add r6, r0 /* r6 = position in new pm_active */
- mov r2, #1
- and r0, r4, #31
- lsl r2, r0 /* r2 = mask */
-#else
- mov r2, #1
- lsl r2, r4 /* r2 = mask */
-#endif
- /* Set cpu to new active list. */
-#ifdef SMP
-1: ldrex r0, [r6]
- orr r0, r2
- strex r1, r0, [r6]
- teq r1, #0
- bne 1b
-#else
- ldr r0, [r6]
- orr r0, r2
- str r0, [r6]
-#endif
- /*
- * Registers at this point.
- * r7 = new PCB
- * r8 = current pcpu
- * r11 = newtd
- * They must match the ones in sw1 position !!!
- */
- DMB
- b sw1 /* share new thread init with cpu_switch() */
-END(cpu_throw)
-
-/*
- * cpu_switch(oldtd, newtd, lock)
- *
- * Save the current thread state, then select the next thread to run
- * and load its state.
- * r0 = oldtd
- * r1 = newtd
- * r2 = lock (new lock for old thread)
- */
-ENTRY(cpu_switch)
- /* Interrupts are disabled. */
-#ifdef INVARIANTS
- cmp r0, #0 /* old thread? */
- beq badsw2 /* no, panic */
-#endif
- /* Save all the registers in the old thread's pcb. */
- ldr r3, [r0, #(TD_PCB)]
- add r3, #(PCB_R4)
- stmia r3, {r4-r12, sp, lr, pc}
-
-#ifdef INVARIANTS
- cmp r1, #0 /* new thread? */
- beq badsw3 /* no, panic */
-#endif
- /*
- * Save arguments. Note that we can now use r0-r14 until
- * it is time to restore them for the new thread. However,
- * some registers are not safe over function call.
- */
- mov r9, r2 /* r9 = lock */
- mov r10, r0 /* r10 = oldtd */
- mov r11, r1 /* r11 = newtd */
-
- GET_PCPU(r8, r3) /* r8 = current PCPU */
- ldr r7, [r11, #(TD_PCB)] /* r7 = newtd->td_pcb */
-
-
-
-#ifdef VFP
- ldr r3, [r10, #(TD_PCB)]
- fmrx r0, fpexc /* If the VFP is enabled */
- tst r0, #(VFPEXC_EN) /* the current thread has */
- movne r1, #1 /* used it, so go save */
- addne r0, r3, #(PCB_VFPSTATE) /* the state into the PCB */
- blne _C_LABEL(vfp_store) /* and disable the VFP. */
-#endif
-
- /*
- * MMU switch. If we're switching to a thread with the same
- * address space as the outgoing one, we can skip the MMU switch.
- */
- mrc CP15_TTBR0(r1) /* r1 = old TTB */
- ldr r0, [r7, #(PCB_PAGEDIR)] /* r0 = new TTB */
- cmp r0, r1 /* Switching to the TTB? */
- beq sw0 /* same TTB, skip */
-
-#ifdef INVARIANTS
- cmp r0, #0 /* new thread? */
- beq badsw4 /* no, panic */
-#endif
-
- bl cpu_context_switch /* new TTB as argument */
-
- /*
- * Registers at this point
- * r7 = new PCB
- * r8 = current pcpu
- * r9 = lock
- * r10 = oldtd
- * r11 = newtd
- */
-
- /*
- * Set new PMAP as current one.
- * Update active list on PMAPs.
- */
- ldr r6, [r11, #TD_PROC] /* newtd->proc */
- ldr r6, [r6, #P_VMSPACE] /* newtd->proc->vmspace */
- add r6, #VM_PMAP /* newtd->proc->vmspace->pmap */
-
- ldr r5, [r8, #PC_CURPMAP] /* get old curpmap */
- str r6, [r8, #PC_CURPMAP] /* and save new one */
-
- mov r0, #PM_ACTIVE
- add r5, r0 /* r5 = old pm_active */
- add r6, r0 /* r6 = new pm_active */
-
- /* Compute position and mask. */
- ldr r4, [r8, #PC_CPUID]
-#if _NCPUWORDS > 1
- lsr r0, r4, #3
- bic r0, #3
- add r5, r0 /* r5 = position in old pm_active */
- add r6, r0 /* r6 = position in new pm_active */
- mov r2, #1
- and r0, r4, #31
- lsl r2, r0 /* r2 = mask */
-#else
- mov r2, #1
- lsl r2, r4 /* r2 = mask */
-#endif
- /* Clear cpu from old active list. */
-#ifdef SMP
-1: ldrex r0, [r5]
- bic r0, r2
- strex r1, r0, [r5]
- teq r1, #0
- bne 1b
-#else
- ldr r0, [r5]
- bic r0, r2
- str r0, [r5]
-#endif
- /* Set cpu to new active list. */
-#ifdef SMP
-1: ldrex r0, [r6]
- orr r0, r2
- strex r1, r0, [r6]
- teq r1, #0
- bne 1b
-#else
- ldr r0, [r6]
- orr r0, r2
- str r0, [r6]
-#endif
-
-sw0:
- /*
- * Registers at this point
- * r7 = new PCB
- * r8 = current pcpu
- * r9 = lock
- * r10 = oldtd
- * r11 = newtd
- */
-
- /* Change the old thread lock. */
- add r5, r10, #TD_LOCK
- DMB
-1: ldrex r0, [r5]
- strex r1, r9, [r5]
- teq r1, #0
- bne 1b
- DMB
-
-sw1:
- clrex
- /*
- * Registers at this point
- * r7 = new PCB
- * r8 = current pcpu
- * r11 = newtd
- */
-
-#if defined(SMP) && defined(SCHED_ULE)
- /*
- * 386 and amd64 do the blocked lock test only for SMP and SCHED_ULE
- * QQQ: What does it mean in reality and why is it done?
- */
- ldr r6, =blocked_lock
-1:
- ldr r3, [r11, #TD_LOCK] /* atomic write regular read */
- cmp r3, r6
- beq 1b
-#endif
- /* Set the new tls */
- ldr r0, [r11, #(TD_MD + MD_TP)]
- mcr CP15_TPIDRURO(r0) /* write tls thread reg 2 */
-
- /* We have a new curthread now so make a note it */
- str r11, [r8, #PC_CURTHREAD]
- mcr CP15_TPIDRPRW(r11)
-
- /* store pcb in per cpu structure */
- str r7, [r8, #PC_CURPCB]
-
- /*
- * Restore all saved registers and return. Note that some saved
- * registers can be changed when either cpu_fork(), cpu_set_upcall(),
- * cpu_set_fork_handler(), or makectx() was called.
- */
- add r3, r7, #PCB_R4
- ldmia r3, {r4-r12, sp, pc}
-
-#ifdef INVARIANTS
-badsw1:
- ldr r0, =sw1_panic_str
- bl _C_LABEL(panic)
-1: nop
- b 1b
-
-badsw2:
- ldr r0, =sw2_panic_str
- bl _C_LABEL(panic)
-1: nop
- b 1b
-
-badsw3:
- ldr r0, =sw3_panic_str
- bl _C_LABEL(panic)
-1: nop
- b 1b
-
-badsw4:
- ldr r0, =sw4_panic_str
- bl _C_LABEL(panic)
-1: nop
- b 1b
-
-sw1_panic_str:
- .asciz "cpu_throw: no newthread supplied.\n"
-sw2_panic_str:
- .asciz "cpu_switch: no curthread supplied.\n"
-sw3_panic_str:
- .asciz "cpu_switch: no newthread supplied.\n"
-sw4_panic_str:
- .asciz "cpu_switch: new pagedir is NULL.\n"
-#endif
-END(cpu_switch)
-
-
-#endif /* !ARM_NEW_PMAP */
-
ENTRY(savectx)
stmfd sp!, {lr}
sub sp, sp, #4
diff --git a/sys/arm/arm/sys_machdep.c b/sys/arm/arm/sys_machdep.c
index efebda32262e..b893a9028561 100644
--- a/sys/arm/arm/sys_machdep.c
+++ b/sys/arm/arm/sys_machdep.c
@@ -45,7 +45,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_extern.h>
#include <machine/acle-compat.h>
-#include <machine/cpu-v6.h>
+#include <machine/cpu.h>
#include <machine/sysarch.h>
#include <machine/vmparam.h>
@@ -153,8 +153,13 @@ arm32_drain_writebuf(struct thread *td, void *args)
{
/* No args. */
- td->td_retval[0] = 0;
+#if __ARM_ARCH < 6
cpu_drain_writebuf();
+#else
+ dsb();
+ cpu_l2cache_drain_writebuf();
+#endif
+ td->td_retval[0] = 0;
return (0);
}
diff --git a/sys/arm/arm/trap-v6.c b/sys/arm/arm/trap-v6.c
index 6d8015137939..81a6ee428f6f 100644
--- a/sys/arm/arm/trap-v6.c
+++ b/sys/arm/arm/trap-v6.c
@@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
#include <machine/acle-compat.h>
#include <machine/cpu.h>
-#include <machine/cpu-v6.h>
#include <machine/frame.h>
#include <machine/machdep.h>
#include <machine/pcb.h>
@@ -70,7 +69,6 @@ __FBSDID("$FreeBSD$");
#include <sys/dtrace_bsd.h>
#endif
-extern char fusubailout[];
extern char cachebailout[];
#ifdef DEBUG
@@ -293,7 +291,10 @@ abort_handler(struct trapframe *tf, int prefetch)
#ifdef INVARIANTS
void *onfault;
#endif
+
+ PCPU_INC(cnt.v_trap);
td = curthread;
+
fsr = (prefetch) ? cp15_ifsr_get(): cp15_dfsr_get();
#if __ARM_ARCH >= 7
far = (prefetch) ? cp15_ifar_get() : cp15_dfar_get();
@@ -334,26 +335,23 @@ abort_handler(struct trapframe *tf, int prefetch)
* they are not from KVA space. Thus, no action is needed here.
*/
-#ifdef ARM_NEW_PMAP
+ /*
+ * (1) Handle access and R/W hardware emulation aborts.
+ * (2) Check that abort is not on pmap essential address ranges.
+ * There is no way how to fix it, so we don't even try.
+ */
rv = pmap_fault(PCPU_GET(curpmap), far, fsr, idx, usermode);
if (rv == KERN_SUCCESS)
return;
- if (rv == KERN_INVALID_ADDRESS)
- goto nogo;
-#endif
- /*
- * Now, when we handled imprecise and debug aborts, the rest of
- * aborts should be really related to mapping.
- */
-
- PCPU_INC(cnt.v_trap);
-
#ifdef KDB
if (kdb_active) {
kdb_reenter();
goto out;
}
#endif
+ if (rv == KERN_INVALID_ADDRESS)
+ goto nogo;
+
if (__predict_false((td->td_pflags & TDP_NOFAULTING) != 0)) {
/*
* Due to both processor errata and lazy TLB invalidation when
@@ -420,6 +418,14 @@ abort_handler(struct trapframe *tf, int prefetch)
}
/*
+ * At this point, we're dealing with one of the following aborts:
+ *
+ * FAULT_ICACHE - I-cache maintenance
+ * FAULT_TRAN_xx - Translation
+ * FAULT_PERM_xx - Permission
+ */
+
+ /*
* Don't pass faulting cache operation to vm_fault(). We don't want
* to handle all vm stuff at this moment.
*/
@@ -437,23 +443,6 @@ abort_handler(struct trapframe *tf, int prefetch)
goto out;
}
- /*
- * At this point, we're dealing with one of the following aborts:
- *
- * FAULT_TRAN_xx - Translation
- * FAULT_PERM_xx - Permission
- *
- * These are the main virtual memory-related faults signalled by
- * the MMU.
- */
-
- /* fusubailout is used by [fs]uswintr to avoid page faulting. */
- if (__predict_false(pcb->pcb_onfault == fusubailout)) {
- tf->tf_r0 = EFAULT;
- tf->tf_pc = (register_t)pcb->pcb_onfault;
- return;
- }
-
va = trunc_page(far);
if (va >= KERNBASE) {
/*
@@ -488,13 +477,6 @@ abort_handler(struct trapframe *tf, int prefetch)
last_fault_code = fsr;
#endif
-#ifndef ARM_NEW_PMAP
- if (pmap_fault_fixup(vmspace_pmap(td->td_proc->p_vmspace), va, ftype,
- usermode)) {
- goto out;
- }
-#endif
-
#ifdef INVARIANTS
onfault = pcb->pcb_onfault;
pcb->pcb_onfault = NULL;
diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c
index e43ec8eb3eb2..eb4d68304b33 100644
--- a/sys/arm/arm/trap.c
+++ b/sys/arm/arm/trap.c
@@ -111,8 +111,6 @@ __FBSDID("$FreeBSD$");
#define ReadWord(a) (*((volatile unsigned int *)(a)))
-extern char fusubailout[];
-
#ifdef DEBUG
int last_fault_code; /* For the benefit of pmap_fault_fixup() */
#endif
@@ -255,13 +253,6 @@ abort_handler(struct trapframe *tf, int type)
* the MMU.
*/
- /* fusubailout is used by [fs]uswintr to avoid page faulting */
- if (__predict_false(pcb->pcb_onfault == fusubailout)) {
- tf->tf_r0 = EFAULT;
- tf->tf_pc = (register_t)(intptr_t) pcb->pcb_onfault;
- return;
- }
-
/*
* Make sure the Program Counter is sane. We could fall foul of
* someone executing Thumb code, in which case the PC might not
diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c
index 6a70cbf403e0..601be0718d97 100644
--- a/sys/arm/arm/vm_machdep.c
+++ b/sys/arm/arm/vm_machdep.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/unistd.h>
+#include <sys/taskqueue.h>
#include <machine/acle-compat.h>
#include <machine/cpu.h>
diff --git a/sys/arm/at91/at91_machdep.c b/sys/arm/at91/at91_machdep.c
index 936f145909de..e904780877f0 100644
--- a/sys/arm/at91/at91_machdep.c
+++ b/sys/arm/at91/at91_machdep.c
@@ -566,7 +566,7 @@ initarm(struct arm_boot_params *abp)
arm_devmap_bootstrap(l1pagetable, at91_devmap);
cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) | DOMAIN_CLIENT);
- setttb(kernel_l1pt.pv_pa);
+ cpu_setttb(kernel_l1pt.pv_pa);
cpu_tlb_flushID();
cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2));
@@ -612,7 +612,7 @@ initarm(struct arm_boot_params *abp)
/*
* We must now clean the cache again....
* Cleaning may be done by reading new data to displace any
- * dirty data in the cache. This will have happened in setttb()
+ * dirty data in the cache. This will have happened in cpu_setttb()
* but since we are boot strapping the addresses used for the read
* may have just been remapped and thus the cache could be out
* of sync. A re-clean after the switch will cure this.
diff --git a/sys/arm/broadcom/bcm2835/bcm2836_mp.c b/sys/arm/broadcom/bcm2835/bcm2836_mp.c
index 93cc0d862d86..d6c84cbd1244 100644
--- a/sys/arm/broadcom/bcm2835/bcm2836_mp.c
+++ b/sys/arm/broadcom/bcm2835/bcm2836_mp.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <machine/cpu.h>
#include <machine/smp.h>
#include <machine/bus.h>
#include <machine/fdt.h>
@@ -123,8 +124,7 @@ platform_mp_start_ap(void)
BSWR4(MBOX3CLR_CORE(i), 0xffffffff);
}
wmb();
- cpu_idcache_wbinv_all();
- cpu_l2cache_wbinv_all();
+ dcache_wbinv_poc_all();
/* boot secondary CPUs */
for (i = 1; i < mp_ncpus; i++) {
diff --git a/sys/arm/cavium/cns11xx/econa_machdep.c b/sys/arm/cavium/cns11xx/econa_machdep.c
index 159105333f03..e212a100c97f 100644
--- a/sys/arm/cavium/cns11xx/econa_machdep.c
+++ b/sys/arm/cavium/cns11xx/econa_machdep.c
@@ -275,7 +275,7 @@ initarm(struct arm_boot_params *abp)
arm_devmap_bootstrap(l1pagetable, econa_devmap);
cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
- setttb(kernel_l1pt.pv_pa);
+ cpu_setttb(kernel_l1pt.pv_pa);
cpu_tlb_flushID();
cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
cninit();
@@ -297,7 +297,7 @@ initarm(struct arm_boot_params *abp)
/*
* We must now clean the cache again....
* Cleaning may be done by reading new data to displace any
- * dirty data in the cache. This will have happened in setttb()
+ * dirty data in the cache. This will have happened in cpu_setttb()
* but since we are boot strapping the addresses used for the read
* may have just been remapped and thus the cache could be out
* of sync. A re-clean after the switch will cure this.
diff --git a/sys/arm/conf/NOTES b/sys/arm/conf/NOTES
index f4259f2324d7..db64f8ebb625 100644
--- a/sys/arm/conf/NOTES
+++ b/sys/arm/conf/NOTES
@@ -5,8 +5,6 @@ machine arm
cpu CPU_ARM9
cpu CPU_ARM9E
cpu CPU_FA526
-cpu CPU_XSCALE_80219
-cpu CPU_XSCALE_80321
cpu CPU_XSCALE_81342
cpu CPU_XSCALE_IXP425
cpu CPU_XSCALE_IXP435
diff --git a/sys/arm/conf/std.armv6 b/sys/arm/conf/std.armv6
index 8e5df24ae12f..35f60a3345e7 100644
--- a/sys/arm/conf/std.armv6
+++ b/sys/arm/conf/std.armv6
@@ -37,8 +37,6 @@ options KBD_INSTALL_CDEV # install a CDEV entry in /dev
options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
options VFP # Enable floating point hardware support
-options ARM_NEW_PMAP # Use new pmap code.
-
# DTrace support
options KDTRACE_HOOKS # Kernel DTrace hooks
options DDB_CTF # all architectures - kernel ELF linker loads CTF data
diff --git a/sys/arm/freescale/imx/imx6_mp.c b/sys/arm/freescale/imx/imx6_mp.c
index 3208f676e6ff..7aa9aab708d1 100644
--- a/sys/arm/freescale/imx/imx6_mp.c
+++ b/sys/arm/freescale/imx/imx6_mp.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <machine/cpu.h>
#include <machine/smp.h>
#include <machine/fdt.h>
#include <machine/intr.h>
@@ -149,7 +150,7 @@ platform_mp_start_ap(void)
val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG);
bus_space_write_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG,
val | SCU_CONTROL_ENABLE);
- cpu_idcache_wbinv_all();
+ dcache_wbinv_poc_all();
/*
* For each AP core, set the entry point address and argument registers,
diff --git a/sys/arm/freescale/vybrid/vf_ehci.c b/sys/arm/freescale/vybrid/vf_ehci.c
index 122513f33c9c..0a7dc941fef3 100644
--- a/sys/arm/freescale/vybrid/vf_ehci.c
+++ b/sys/arm/freescale/vybrid/vf_ehci.c
@@ -169,6 +169,18 @@ static devclass_t ehci_devclass;
DRIVER_MODULE(ehci, simplebus, ehci_driver, ehci_devclass, 0, 0);
MODULE_DEPEND(ehci, usb, 1, 1, 1);
+static void
+vybrid_ehci_post_reset(struct ehci_softc *ehci_softc)
+{
+ uint32_t usbmode;
+
+ /* Force HOST mode */
+ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
+ usbmode &= ~EHCI_UM_CM;
+ usbmode |= EHCI_UM_CM_HOST;
+ EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
+}
+
/*
* Public methods
*/
@@ -343,8 +355,10 @@ vybrid_ehci_attach(device_t dev)
reg |= 0x3;
bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl, 0xA8, reg);
- /* Set flags */
- sc->sc_flags |= EHCI_SCFLG_SETMODE | EHCI_SCFLG_NORESTERM;
+ /* Set flags and callbacks*/
+ sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM;
+ sc->sc_vendor_post_reset = vybrid_ehci_post_reset;
+ sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc;
err = ehci_init(sc);
if (!err) {
diff --git a/sys/arm/include/cpu-v4.h b/sys/arm/include/cpu-v4.h
new file mode 100644
index 000000000000..0d66dee42bc3
--- /dev/null
+++ b/sys/arm/include/cpu-v4.h
@@ -0,0 +1,186 @@
+/*-
+ * Copyright 2016 Svatopluk Kraus <skra@FreeBSD.org>
+ * Copyright 2016 Michal Meloun <mmel@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef MACHINE_CPU_V4_H
+#define MACHINE_CPU_V4_H
+
+/* There are no user serviceable parts here, they may change without notice */
+#ifndef _KERNEL
+#error Only include this file in the kernel
+#endif
+
+#include <machine/acle-compat.h>
+#include <machine/atomic.h>
+#include <machine/cpufunc.h>
+#include <machine/cpuinfo.h>
+#include <machine/sysreg.h>
+
+#if __ARM_ARCH >= 6
+#error Never include this file for ARMv6
+#else
+
+#define CPU_ASID_KERNEL 0
+
+/*
+ * Macros to generate CP15 (system control processor) read/write functions.
+ */
+#define _FX(s...) #s
+
+#define _RF0(fname, aname...) \
+static __inline register_t \
+fname(void) \
+{ \
+ register_t reg; \
+ __asm __volatile("mrc\t" _FX(aname): "=r" (reg)); \
+ return(reg); \
+}
+
+#define _R64F0(fname, aname) \
+static __inline uint64_t \
+fname(void) \
+{ \
+ uint64_t reg; \
+ __asm __volatile("mrrc\t" _FX(aname): "=r" (reg)); \
+ return(reg); \
+}
+
+#define _WF0(fname, aname...) \
+static __inline void \
+fname(void) \
+{ \
+ __asm __volatile("mcr\t" _FX(aname)); \
+}
+
+#define _WF1(fname, aname...) \
+static __inline void \
+fname(register_t reg) \
+{ \
+ __asm __volatile("mcr\t" _FX(aname):: "r" (reg)); \
+}
+
+
+/*
+ * Publicly accessible functions
+ */
+
+
+/* Various control registers */
+
+_RF0(cp15_cpacr_get, CP15_CPACR(%0))
+_WF1(cp15_cpacr_set, CP15_CPACR(%0))
+_RF0(cp15_dfsr_get, CP15_DFSR(%0))
+_RF0(cp15_ttbr_get, CP15_TTBR0(%0))
+_RF0(cp15_dfar_get, CP15_DFAR(%0))
+/* XScale */
+_RF0(cp15_actlr_get, CP15_ACTLR(%0))
+_WF1(cp15_actlr_set, CP15_ACTLR(%0))
+
+/*CPU id registers */
+_RF0(cp15_midr_get, CP15_MIDR(%0))
+_RF0(cp15_ctr_get, CP15_CTR(%0))
+_RF0(cp15_tcmtr_get, CP15_TCMTR(%0))
+_RF0(cp15_tlbtr_get, CP15_TLBTR(%0))
+
+#undef _FX
+#undef _RF0
+#undef _WF0
+#undef _WF1
+
+
+/*
+ * armv4/5 compatibility shims.
+ *
+ * These functions provide armv4 cache maintenance using the new armv6 names.
+ * Included here are just the functions actually used now in common code; it may
+ * be necessary to add things here over time.
+ *
+ * The callers of the dcache functions expect these routines to handle address
+ * and size values which are not aligned to cacheline boundaries; the armv4 and
+ * armv5 asm code handles that.
+ */
+
+static __inline void
+tlb_flush_all(void)
+{
+ cpu_tlb_flushID();
+ cpu_cpwait();
+}
+
+static __inline void
+icache_sync(vm_offset_t va, vm_size_t size)
+{
+ cpu_icache_sync_range(va, size);
+}
+
+static __inline void
+dcache_inv_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size)
+{
+
+ cpu_dcache_inv_range(va, size);
+#ifdef ARM_L2_PIPT
+ cpu_l2cache_inv_range(pa, size);
+#else
+ cpu_l2cache_inv_range(va, size);
+#endif
+}
+
+static __inline void
+dcache_inv_poc_dma(vm_offset_t va, vm_paddr_t pa, vm_size_t size)
+{
+
+ /* See armv6 code, above, for why we do L2 before L1 in this case. */
+#ifdef ARM_L2_PIPT
+ cpu_l2cache_inv_range(pa, size);
+#else
+ cpu_l2cache_inv_range(va, size);
+#endif
+ cpu_dcache_inv_range(va, size);
+}
+
+static __inline void
+dcache_wb_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size)
+{
+
+ cpu_dcache_wb_range(va, size);
+#ifdef ARM_L2_PIPT
+ cpu_l2cache_wb_range(pa, size);
+#else
+ cpu_l2cache_wb_range(va, size);
+#endif
+}
+
+static __inline void
+dcache_wbinv_poc_all(void)
+{
+ cpu_idcache_wbinv_all();
+ cpu_l2cache_wbinv_all();
+}
+
+#endif /* _KERNEL */
+
+#endif /* MACHINE_CPU_V4_H */
diff --git a/sys/arm/include/cpu-v6.h b/sys/arm/include/cpu-v6.h
index bb8649ab30ba..e537c10b4d4e 100644
--- a/sys/arm/include/cpu-v6.h
+++ b/sys/arm/include/cpu-v6.h
@@ -32,19 +32,32 @@
/* There are no user serviceable parts here, they may change without notice */
#ifndef _KERNEL
#error Only include this file in the kernel
-#else
+#endif
#include <machine/acle-compat.h>
-#include "machine/atomic.h"
-#include "machine/cpufunc.h"
-#include "machine/cpuinfo.h"
-#include "machine/sysreg.h"
+#include <machine/atomic.h>
+#include <machine/cpufunc.h>
+#include <machine/cpuinfo.h>
+#include <machine/sysreg.h>
+
+#if __ARM_ARCH < 6
+#error Only include this file for ARMv6
+#else
#define CPU_ASID_KERNEL 0
+void dcache_wbinv_poc_all(void); /* !!! NOT SMP coherent function !!! */
vm_offset_t dcache_wb_pou_checked(vm_offset_t, vm_size_t);
vm_offset_t icache_inv_pou_checked(vm_offset_t, vm_size_t);
+#ifdef DEV_PMU
+#include <sys/pcpu.h>
+#define PMU_OVSR_C 0x80000000 /* Cycle Counter */
+extern uint32_t ccnt_hi[MAXCPU];
+extern int pmu_attched;
+#endif /* DEV_PMU */
+
+
/*
* Macros to generate CP15 (system control processor) read/write functions.
*/
@@ -277,12 +290,6 @@ _W64F1(cp15_cnthp_cval_set, CP15_CNTHP_CVAL(%Q0, %R0))
#undef _WF0
#undef _WF1
-#if __ARM_ARCH >= 6
-/*
- * Cache and TLB maintenance operations for armv6+ code. The #else block
- * provides armv4/v5 implementations for a few of these used in common code.
- */
-
/*
* TLB maintenance operations.
*/
@@ -577,48 +584,6 @@ cp15_ttbr_set(uint32_t reg)
isb();
tlb_flush_all_ng_local();
}
-
-#else /* ! __ARM_ARCH >= 6 */
-
-/*
- * armv4/5 compatibility shims.
- *
- * These functions provide armv4 cache maintenance using the new armv6 names.
- * Included here are just the functions actually used now in common code; it may
- * be necessary to add things here over time.
- *
- * The callers of the dcache functions expect these routines to handle address
- * and size values which are not aligned to cacheline boundaries; the armv4 and
- * armv5 asm code handles that.
- */
-
-static __inline void
-dcache_inv_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size)
-{
-
- cpu_dcache_inv_range(va, size);
- cpu_l2cache_inv_range(va, size);
-}
-
-static __inline void
-dcache_inv_poc_dma(vm_offset_t va, vm_paddr_t pa, vm_size_t size)
-{
-
- /* See armv6 code, above, for why we do L2 before L1 in this case. */
- cpu_l2cache_inv_range(va, size);
- cpu_dcache_inv_range(va, size);
-}
-
-static __inline void
-dcache_wb_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size)
-{
-
- cpu_dcache_wb_range(va, size);
- cpu_l2cache_wb_range(va, size);
-}
-
-#endif /* __ARM_ARCH >= 6 */
-
#endif /* _KERNEL */
#endif /* !MACHINE_CPU_V6_H */
diff --git a/sys/arm/include/cpu.h b/sys/arm/include/cpu.h
index 782471e725d3..0d79e68dc2b8 100644
--- a/sys/arm/include/cpu.h
+++ b/sys/arm/include/cpu.h
@@ -14,12 +14,8 @@ void swi_vm(void *);
#ifdef _KERNEL
#if __ARM_ARCH >= 6
#include <machine/cpu-v6.h>
-#ifdef DEV_PMU
-#include <sys/pcpu.h>
-#define PMU_OVSR_C 0x80000000 /* Cycle Counter */
-extern uint32_t ccnt_hi[MAXCPU];
-extern int pmu_attched;
-#endif /* DEV_PMU */
+#else
+#include <machine/cpu-v4.h>
#endif /* __ARM_ARCH >= 6 */
static __inline uint64_t
diff --git a/sys/arm/include/cpuconf.h b/sys/arm/include/cpuconf.h
index ecee28088255..24a3b8f1c2cd 100644
--- a/sys/arm/include/cpuconf.h
+++ b/sys/arm/include/cpuconf.h
@@ -53,7 +53,6 @@
#define CPU_NTYPES (defined(CPU_ARM9) + \
defined(CPU_ARM9E) + \
defined(CPU_ARM1176) + \
- defined(CPU_XSCALE_80321) + \
defined(CPU_XSCALE_PXA2X0) + \
defined(CPU_FA526) + \
defined(CPU_XSCALE_IXP425)) + \
@@ -71,8 +70,7 @@
#endif
#if (defined(CPU_ARM9E) || \
- defined(CPU_XSCALE_80321) || \
- defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
+ defined(CPU_XSCALE_81342) || \
defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425))
#define ARM_ARCH_5 1
#else
@@ -163,9 +161,8 @@
#define ARM_MMU_V7 0
#endif
-#if (defined(CPU_XSCALE_80321) || \
- defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
- defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342))
+#if (defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
+ defined(CPU_XSCALE_81342))
#define ARM_MMU_XSCALE 1
#else
#define ARM_MMU_XSCALE 0
@@ -180,11 +177,10 @@
/*
* Step 4: Define features that may be present on a subset of CPUs
*
- * ARM_XSCALE_PMU Performance Monitoring Unit on 80200 and 80321
+ * ARM_XSCALE_PMU Performance Monitoring Unit on 81342
*/
-#if (defined(CPU_XSCALE_80321) || \
- defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342))
+#if (defined(CPU_XSCALE_81342))
#define ARM_XSCALE_PMU 1
#else
#define ARM_XSCALE_PMU 0
diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h
index 8bbb1dd7491c..eb445b49abcf 100644
--- a/sys/arm/include/cpufunc.h
+++ b/sys/arm/include/cpufunc.h
@@ -60,23 +60,17 @@ struct cpu_functions {
/* CPU functions */
- u_int (*cf_id) (void);
void (*cf_cpwait) (void);
/* MMU functions */
u_int (*cf_control) (u_int bic, u_int eor);
- void (*cf_domains) (u_int domains);
void (*cf_setttb) (u_int ttb);
- u_int (*cf_faultstatus) (void);
- u_int (*cf_faultaddress) (void);
/* TLB functions */
void (*cf_tlb_flushID) (void);
void (*cf_tlb_flushID_SE) (u_int va);
- void (*cf_tlb_flushI) (void);
- void (*cf_tlb_flushI_SE) (u_int va);
void (*cf_tlb_flushD) (void);
void (*cf_tlb_flushD_SE) (u_int va);
@@ -85,7 +79,6 @@ struct cpu_functions {
*
* We define the following primitives:
*
- * icache_sync_all Synchronize I-cache
* icache_sync_range Synchronize I-cache range
*
* dcache_wbinv_all Write-back and Invalidate D-cache
@@ -110,7 +103,7 @@ struct cpu_functions {
* state (such as when it may have lines tagged as valid
* that belong to a previous set of mappings).
*
- * I-cache Synch (all or range):
+ * I-cache Sync range:
* The goal is to synchronize the instruction stream,
* so you may beed to write-back dirty D-cache blocks
* first. If a range is requested, and you can't
@@ -136,7 +129,6 @@ struct cpu_functions {
* Valid virtual addresses must be passed to each
* cache operation.
*/
- void (*cf_icache_sync_all) (void);
void (*cf_icache_sync_range) (vm_offset_t, vm_size_t);
void (*cf_dcache_wbinv_all) (void);
@@ -155,18 +147,12 @@ struct cpu_functions {
/* Other functions */
- void (*cf_flush_prefetchbuf) (void);
void (*cf_drain_writebuf) (void);
- void (*cf_flush_brnchtgt_C) (void);
- void (*cf_flush_brnchtgt_E) (u_int va);
void (*cf_sleep) (int mode);
/* Soft functions */
- int (*cf_dataabt_fixup) (void *arg);
- int (*cf_prefetchabt_fixup) (void *arg);
-
void (*cf_context_switch) (void);
void (*cf_setup) (void);
@@ -175,70 +161,19 @@ struct cpu_functions {
extern struct cpu_functions cpufuncs;
extern u_int cputype;
-#define cpu_ident() cpufuncs.cf_id()
+#if __ARM_ARCH < 6
#define cpu_cpwait() cpufuncs.cf_cpwait()
+#endif
#define cpu_control(c, e) cpufuncs.cf_control(c, e)
-#define cpu_domains(d) cpufuncs.cf_domains(d)
+#if __ARM_ARCH < 6
#define cpu_setttb(t) cpufuncs.cf_setttb(t)
-#define cpu_faultstatus() cpufuncs.cf_faultstatus()
-#define cpu_faultaddress() cpufuncs.cf_faultaddress()
-
-#ifndef SMP
#define cpu_tlb_flushID() cpufuncs.cf_tlb_flushID()
#define cpu_tlb_flushID_SE(e) cpufuncs.cf_tlb_flushID_SE(e)
-#define cpu_tlb_flushI() cpufuncs.cf_tlb_flushI()
-#define cpu_tlb_flushI_SE(e) cpufuncs.cf_tlb_flushI_SE(e)
#define cpu_tlb_flushD() cpufuncs.cf_tlb_flushD()
#define cpu_tlb_flushD_SE(e) cpufuncs.cf_tlb_flushD_SE(e)
-#else
-void tlb_broadcast(int);
-
-#if defined(CPU_CORTEXA) || defined(CPU_MV_PJ4B) || defined(CPU_KRAIT)
-#define TLB_BROADCAST /* No need to explicitely send an IPI */
-#else
-#define TLB_BROADCAST tlb_broadcast(7)
-#endif
-
-#define cpu_tlb_flushID() do { \
- cpufuncs.cf_tlb_flushID(); \
- TLB_BROADCAST; \
-} while(0)
-
-#define cpu_tlb_flushID_SE(e) do { \
- cpufuncs.cf_tlb_flushID_SE(e); \
- TLB_BROADCAST; \
-} while(0)
-
-
-#define cpu_tlb_flushI() do { \
- cpufuncs.cf_tlb_flushI(); \
- TLB_BROADCAST; \
-} while(0)
-
-
-#define cpu_tlb_flushI_SE(e) do { \
- cpufuncs.cf_tlb_flushI_SE(e); \
- TLB_BROADCAST; \
-} while(0)
-
-
-#define cpu_tlb_flushD() do { \
- cpufuncs.cf_tlb_flushD(); \
- TLB_BROADCAST; \
-} while(0)
-
-
-#define cpu_tlb_flushD_SE(e) do { \
- cpufuncs.cf_tlb_flushD_SE(e); \
- TLB_BROADCAST; \
-} while(0)
-
-#endif
-
-#define cpu_icache_sync_all() cpufuncs.cf_icache_sync_all()
#define cpu_icache_sync_range(a, s) cpufuncs.cf_icache_sync_range((a), (s))
#define cpu_dcache_wbinv_all() cpufuncs.cf_dcache_wbinv_all()
@@ -249,25 +184,18 @@ void tlb_broadcast(int);
#define cpu_idcache_inv_all() cpufuncs.cf_idcache_inv_all()
#define cpu_idcache_wbinv_all() cpufuncs.cf_idcache_wbinv_all()
#define cpu_idcache_wbinv_range(a, s) cpufuncs.cf_idcache_wbinv_range((a), (s))
+#endif
#define cpu_l2cache_wbinv_all() cpufuncs.cf_l2cache_wbinv_all()
#define cpu_l2cache_wb_range(a, s) cpufuncs.cf_l2cache_wb_range((a), (s))
#define cpu_l2cache_inv_range(a, s) cpufuncs.cf_l2cache_inv_range((a), (s))
#define cpu_l2cache_wbinv_range(a, s) cpufuncs.cf_l2cache_wbinv_range((a), (s))
#define cpu_l2cache_drain_writebuf() cpufuncs.cf_l2cache_drain_writebuf()
-#define cpu_flush_prefetchbuf() cpufuncs.cf_flush_prefetchbuf()
+#if __ARM_ARCH < 6
#define cpu_drain_writebuf() cpufuncs.cf_drain_writebuf()
-#define cpu_flush_brnchtgt_C() cpufuncs.cf_flush_brnchtgt_C()
-#define cpu_flush_brnchtgt_E(e) cpufuncs.cf_flush_brnchtgt_E(e)
-
+#endif
#define cpu_sleep(m) cpufuncs.cf_sleep(m)
-#define cpu_dataabt_fixup(a) cpufuncs.cf_dataabt_fixup(a)
-#define cpu_prefetchabt_fixup(a) cpufuncs.cf_prefetchabt_fixup(a)
-#define ABORT_FIXUP_OK 0 /* fixup succeeded */
-#define ABORT_FIXUP_FAILED 1 /* fixup failed */
-#define ABORT_FIXUP_RETURN 2 /* abort handler should return */
-
#define cpu_setup() cpufuncs.cf_setup()
int set_cpufuncs (void);
@@ -275,15 +203,12 @@ int set_cpufuncs (void);
#define ARCHITECTURE_NOT_SUPPORTED 2 /* not known */
void cpufunc_nullop (void);
-int cpufunc_null_fixup (void *);
-int early_abort_fixup (void *);
-int late_abort_fixup (void *);
-u_int cpufunc_id (void);
-u_int cpufunc_cpuid (void);
+u_int cpu_ident (void);
u_int cpufunc_control (u_int clear, u_int bic);
-void cpufunc_domains (u_int domains);
-u_int cpufunc_faultstatus (void);
-u_int cpufunc_faultaddress (void);
+void cpu_domains (u_int domains);
+u_int cpu_faultstatus (void);
+u_int cpu_faultaddress (void);
+u_int cpu_get_control (void);
u_int cpu_pfr (int);
#if defined(CPU_FA526)
@@ -291,12 +216,8 @@ void fa526_setup (void);
void fa526_setttb (u_int ttb);
void fa526_context_switch (void);
void fa526_cpu_sleep (int);
-void fa526_tlb_flushI_SE (u_int);
void fa526_tlb_flushID_SE (u_int);
-void fa526_flush_prefetchbuf (void);
-void fa526_flush_brnchtgt_E (u_int);
-void fa526_icache_sync_all (void);
void fa526_icache_sync_range(vm_offset_t start, vm_size_t end);
void fa526_dcache_wbinv_all (void);
void fa526_dcache_wbinv_range(vm_offset_t start, vm_size_t end);
@@ -307,12 +228,13 @@ void fa526_idcache_wbinv_range(vm_offset_t start, vm_size_t end);
#endif
-#ifdef CPU_ARM9
+#if defined(CPU_ARM9) || defined(CPU_ARM9E)
void arm9_setttb (u_int);
-
void arm9_tlb_flushID_SE (u_int va);
+void arm9_context_switch (void);
+#endif
-void arm9_icache_sync_all (void);
+#if defined(CPU_ARM9)
void arm9_icache_sync_range (vm_offset_t, vm_size_t);
void arm9_dcache_wbinv_all (void);
@@ -323,8 +245,6 @@ void arm9_dcache_wb_range (vm_offset_t, vm_size_t);
void arm9_idcache_wbinv_all (void);
void arm9_idcache_wbinv_range (vm_offset_t, vm_size_t);
-void arm9_context_switch (void);
-
void arm9_setup (void);
extern unsigned arm9_dcache_sets_max;
@@ -334,11 +254,6 @@ extern unsigned arm9_dcache_index_inc;
#endif
#if defined(CPU_ARM9E)
-void arm10_tlb_flushID_SE (u_int);
-void arm10_tlb_flushI_SE (u_int);
-
-void arm10_context_switch (void);
-
void arm10_setup (void);
u_int sheeva_control_ext (u_int, u_int);
@@ -362,7 +277,6 @@ void armv6_idcache_wbinv_all (void);
void armv7_setttb (u_int);
void armv7_tlb_flushID (void);
void armv7_tlb_flushID_SE (u_int);
-void armv7_icache_sync_all (void);
void armv7_icache_sync_range (vm_offset_t, vm_size_t);
void armv7_idcache_wbinv_range (vm_offset_t, vm_size_t);
void armv7_idcache_inv_all (void);
@@ -390,8 +304,6 @@ void pj4bv7_setup (void);
#if defined(CPU_ARM1176)
void arm11_tlb_flushID (void);
void arm11_tlb_flushID_SE (u_int);
-void arm11_tlb_flushI (void);
-void arm11_tlb_flushI_SE (u_int);
void arm11_tlb_flushD (void);
void arm11_tlb_flushD_SE (u_int va);
@@ -408,8 +320,6 @@ void armv6_idcache_inv_all (void);
void arm11x6_setttb (u_int);
void arm11x6_idcache_wbinv_all (void);
void arm11x6_dcache_wbinv_all (void);
-void arm11x6_icache_sync_all (void);
-void arm11x6_flush_prefetchbuf (void);
void arm11x6_icache_sync_range (vm_offset_t, vm_size_t);
void arm11x6_idcache_wbinv_range (vm_offset_t, vm_size_t);
void arm11x6_setup (void);
@@ -419,7 +329,6 @@ void arm11x6_sleep (int); /* no ref. for errata */
#if defined(CPU_ARM9E)
void armv5_ec_setttb(u_int);
-void armv5_ec_icache_sync_all(void);
void armv5_ec_icache_sync_range(vm_offset_t, vm_size_t);
void armv5_ec_dcache_wbinv_all(void);
@@ -432,13 +341,11 @@ void armv5_ec_idcache_wbinv_range(vm_offset_t, vm_size_t);
#endif
#if defined(CPU_ARM9) || defined(CPU_ARM9E) || \
- defined(CPU_XSCALE_80321) || \
defined(CPU_FA526) || \
defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
- defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
+ defined(CPU_XSCALE_81342)
void armv4_tlb_flushID (void);
-void armv4_tlb_flushI (void);
void armv4_tlb_flushD (void);
void armv4_tlb_flushD_SE (u_int va);
@@ -446,9 +353,8 @@ void armv4_drain_writebuf (void);
void armv4_idcache_inv_all (void);
#endif
-#if defined(CPU_XSCALE_80321) || \
- defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
- defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
+#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
+ defined(CPU_XSCALE_81342)
void xscale_cpwait (void);
void xscale_cpu_sleep (int mode);
@@ -486,8 +392,7 @@ void xscale_cache_flushD_rng (vm_offset_t start, vm_size_t end);
void xscale_context_switch (void);
void xscale_setup (void);
-#endif /* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425
- CPU_XSCALE_80219 */
+#endif /* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */
#ifdef CPU_XSCALE_81342
@@ -514,9 +419,6 @@ void xscalec3_context_switch (void);
#endif /* CPU_XSCALE_81342 */
-#define setttb cpu_setttb
-#define drain_writebuf cpu_drain_writebuf
-
/*
* Macros for manipulating CPU interrupts
*/
diff --git a/sys/arm/include/debug_monitor.h b/sys/arm/include/debug_monitor.h
index 0cc8156ba447..776d344f972e 100644
--- a/sys/arm/include/debug_monitor.h
+++ b/sys/arm/include/debug_monitor.h
@@ -48,6 +48,7 @@ void dbg_monitor_init(void);
void dbg_show_watchpoint(void);
int dbg_setup_watchpoint(db_expr_t, db_expr_t, enum dbg_access_t);
int dbg_remove_watchpoint(db_expr_t, db_expr_t);
+void dbg_resume_dbreg(void);
#else /* __ARM_ARCH >= 6 */
static __inline void
dbg_show_watchpoint(void)
@@ -68,6 +69,11 @@ static __inline void
dbg_monitor_init(void)
{
}
+
+static __inline void
+dbg_resume_dbreg(void)
+{
+}
#endif /* __ARM_ARCH < 6 */
#else /* DDB */
diff --git a/sys/arm/include/kdb.h b/sys/arm/include/kdb.h
index fb50c78ef94e..c7968ab6e8b2 100644
--- a/sys/arm/include/kdb.h
+++ b/sys/arm/include/kdb.h
@@ -29,10 +29,10 @@
#ifndef _MACHINE_KDB_H_
#define _MACHINE_KDB_H_
+#include <machine/cpu.h>
+#include <machine/db_machdep.h>
#include <machine/frame.h>
#include <machine/psl.h>
-#include <machine/cpufunc.h>
-#include <machine/db_machdep.h>
#define KDB_STOPPEDPCB(pc) &stoppcbs[pc->pc_cpuid]
@@ -56,7 +56,7 @@ static __inline void
kdb_cpu_sync_icache(unsigned char *addr, size_t size)
{
- cpu_icache_sync_range((vm_offset_t)addr, size);
+ icache_sync((vm_offset_t)addr, size);
}
static __inline void
diff --git a/sys/arm/include/machdep.h b/sys/arm/include/machdep.h
index fdf59beedb33..36c2f44daed9 100644
--- a/sys/arm/include/machdep.h
+++ b/sys/arm/include/machdep.h
@@ -4,8 +4,10 @@
#ifndef _MACHDEP_BOOT_MACHDEP_H_
#define _MACHDEP_BOOT_MACHDEP_H_
+#include <machine/acle-compat.h>
+
/* Structs that need to be initialised by initarm */
-#ifdef ARM_NEW_PMAP
+#if __ARM_ARCH >= 6
extern vm_offset_t irqstack;
extern vm_offset_t undstack;
extern vm_offset_t abtstack;
diff --git a/sys/arm/include/param.h b/sys/arm/include/param.h
index bbe9bcb08325..384891daf36a 100644
--- a/sys/arm/include/param.h
+++ b/sys/arm/include/param.h
@@ -110,7 +110,6 @@
#define PAGE_SHIFT 12
#define PAGE_SIZE (1 << PAGE_SHIFT) /* Page size */
#define PAGE_MASK (PAGE_SIZE - 1)
-#define NPTEPG (PAGE_SIZE/(sizeof (pt_entry_t)))
#define PDR_SHIFT 20 /* log2(NBPDR) */
#define NBPDR (1 << PDR_SHIFT)
diff --git a/sys/arm/include/pcpu.h b/sys/arm/include/pcpu.h
index 4261a5a2a2d1..b4814fc2503c 100644
--- a/sys/arm/include/pcpu.h
+++ b/sys/arm/include/pcpu.h
@@ -49,7 +49,9 @@ struct vmspace;
struct pmap *pc_curpmap; \
vm_offset_t pc_qmap_addr; \
void *pc_qmap_pte; \
- char __pad[133]
+ unsigned int pc_dbreg[32]; \
+ int pc_dbreg_cmd; \
+ char __pad[1]
#else
#define PCPU_MD_FIELDS \
vm_offset_t qmap_addr; \
@@ -59,6 +61,9 @@ struct vmspace;
#ifdef _KERNEL
+#define PC_DBREG_CMD_NONE 0
+#define PC_DBREG_CMD_LOAD 1
+
struct pcb;
struct pcpu;
diff --git a/sys/arm/include/pmap-v6.h b/sys/arm/include/pmap-v6.h
index beaf638a179b..067897779a20 100644
--- a/sys/arm/include/pmap-v6.h
+++ b/sys/arm/include/pmap-v6.h
@@ -115,7 +115,7 @@ struct pv_chunk;
struct md_page {
TAILQ_HEAD(,pv_entry) pv_list;
uint16_t pt2_wirecount[4];
- int pat_mode;
+ vm_memattr_t pat_mode;
};
struct pmap {
@@ -173,7 +173,7 @@ struct pv_chunk {
struct pcb;
extern ttb_entry_t pmap_kern_ttb; /* TTB for kernel pmap */
-#define pmap_page_get_memattr(m) ((vm_memattr_t)(m)->md.pat_mode)
+#define pmap_page_get_memattr(m) ((m)->md.pat_mode)
#define pmap_page_is_write_mapped(m) (((m)->aflags & PGA_WRITEABLE) != 0)
/*
@@ -216,28 +216,8 @@ vm_paddr_t pmap_preboot_get_pages(u_int );
void pmap_preboot_map_pages(vm_paddr_t , vm_offset_t , u_int );
vm_offset_t pmap_preboot_reserve_pages(u_int );
vm_offset_t pmap_preboot_get_vpages(u_int );
-void pmap_preboot_map_attr(vm_paddr_t , vm_offset_t , vm_size_t ,
- int , int );
-static __inline void
-pmap_map_chunk(vm_offset_t l1pt, vm_offset_t va, vm_offset_t pa,
- vm_size_t size, int prot, int cache)
-{
- pmap_preboot_map_attr(pa, va, size, prot, cache);
-}
-
-/*
- * This structure is used by machine-dependent code to describe
- * static mappings of devices, created at bootstrap time.
- */
-struct pmap_devmap {
- vm_offset_t pd_va; /* virtual address */
- vm_paddr_t pd_pa; /* physical address */
- vm_size_t pd_size; /* size of region */
- vm_prot_t pd_prot; /* protection code */
- int pd_cache; /* cache attributes */
-};
-
-void pmap_devmap_bootstrap(const struct pmap_devmap *);
+void pmap_preboot_map_attr(vm_paddr_t, vm_offset_t, vm_size_t, vm_prot_t,
+ vm_memattr_t);
#endif /* _KERNEL */
@@ -268,40 +248,9 @@ void pmap_devmap_bootstrap(const struct pmap_devmap *);
/*
* sys/arm/arm/cpufunc.c
*/
-void pmap_pte_init_mmu_v6(void);
void vector_page_setprot(int);
-
-/*
- * sys/arm/arm/db_interface.c
- * sys/arm/arm/machdep.c
- * sys/arm/arm/minidump_machdep.c
- * sys/arm/arm/pmap.c
- */
-#define pmap_kernel() kernel_pmap
-
-/*
- * sys/arm/arm/bus_space_generic.c (just comment)
- * sys/arm/arm/devmap.c
- * sys/arm/arm/pmap.c (just comment)
- * sys/arm/at91/at91_machdep.c
- * sys/arm/cavium/cns11xx/econa_machdep.c
- * sys/arm/freescale/imx/imx6_machdep.c (just comment)
- * sys/arm/mv/orion/db88f5xxx.c
- * sys/arm/mv/mv_localbus.c
- * sys/arm/mv/mv_machdep.c
- * sys/arm/mv/mv_pci.c
- * sys/arm/s3c2xx0/s3c24x0_machdep.c
- * sys/arm/versatile/versatile_machdep.c
- * sys/arm/xscale/ixp425/avila_machdep.c
- * sys/arm/xscale/i8134x/crb_machdep.c
- * sys/arm/xscale/i80321/ep80219_machdep.c
- * sys/arm/xscale/i80321/iq31244_machdep.c
- * sys/arm/xscale/pxa/pxa_machdep.c
- */
-#define PTE_DEVICE PTE2_ATTR_DEVICE
-
-
+#define PTE_DEVICE VM_MEMATTR_DEVICE
#endif /* _KERNEL */
// -----------------------------------------------------------------------------
diff --git a/sys/arm/include/pmap.h b/sys/arm/include/pmap.h
index a0b0d94255b8..8222652084b4 100644
--- a/sys/arm/include/pmap.h
+++ b/sys/arm/include/pmap.h
@@ -46,9 +46,11 @@
*
* $FreeBSD$
*/
-#ifdef ARM_NEW_PMAP
+ #include <machine/acle-compat.h>
+
+#if __ARM_ARCH >= 6
#include <machine/pmap-v6.h>
-#else /* ARM_NEW_PMAP */
+#else /* __ARM_ARCH >= 6 */
#ifndef _MACHINE_PMAP_H_
#define _MACHINE_PMAP_H_
@@ -58,21 +60,10 @@
/*
* Pte related macros
*/
-#if ARM_ARCH_6 || ARM_ARCH_7A
-#ifdef SMP
-#define PTE_NOCACHE 2
-#else
-#define PTE_NOCACHE 1
-#endif
-#define PTE_CACHE 6
-#define PTE_DEVICE 2
-#define PTE_PAGETABLE 6
-#else
#define PTE_NOCACHE 1
#define PTE_CACHE 2
#define PTE_DEVICE PTE_NOCACHE
#define PTE_PAGETABLE 3
-#endif
enum mem_type {
STRONG_ORD = 0,
@@ -102,11 +93,7 @@ enum mem_type {
#define pmap_page_get_memattr(m) ((m)->md.pv_memattr)
#define pmap_page_is_write_mapped(m) (((m)->aflags & PGA_WRITEABLE) != 0)
-#if (ARM_MMU_V6 + ARM_MMU_V7) > 0
-boolean_t pmap_page_is_mapped(vm_page_t);
-#else
#define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list))
-#endif
void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma);
/*
@@ -129,9 +116,7 @@ struct pv_chunk;
struct md_page {
int pvh_attrs;
vm_memattr_t pv_memattr;
-#if (ARM_MMU_V6 + ARM_MMU_V7) == 0
vm_offset_t pv_kva; /* first kernel VA mapping */
-#endif
TAILQ_HEAD(,pv_entry) pv_list;
};
@@ -162,11 +147,7 @@ struct pmap {
struct l2_dtable *pm_l2[L2_SIZE];
cpuset_t pm_active; /* active on cpus */
struct pmap_statistics pm_stats; /* pmap statictics */
-#if (ARM_MMU_V6 + ARM_MMU_V7) != 0
- TAILQ_HEAD(,pv_chunk) pm_pvchunk; /* list of mappings in pmap */
-#else
TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */
-#endif
};
typedef struct pmap *pmap_t;
@@ -174,7 +155,6 @@ typedef struct pmap *pmap_t;
#ifdef _KERNEL
extern struct pmap kernel_pmap_store;
#define kernel_pmap (&kernel_pmap_store)
-#define pmap_kernel() kernel_pmap
#define PMAP_ASSERT_LOCKED(pmap) \
mtx_assert(&(pmap)->pm_mtx, MA_OWNED)
@@ -197,10 +177,8 @@ typedef struct pv_entry {
vm_offset_t pv_va; /* virtual address for mapping */
TAILQ_ENTRY(pv_entry) pv_list;
int pv_flags; /* flags (wired, etc...) */
-#if (ARM_MMU_V6 + ARM_MMU_V7) == 0
pmap_t pv_pmap; /* pmap where mapping lies */
TAILQ_ENTRY(pv_entry) pv_plist;
-#endif
} *pv_entry_t;
/*
@@ -245,7 +223,7 @@ vtopte(vm_offset_t va)
pd_entry_t *pdep;
pt_entry_t *ptep;
- if (pmap_get_pde_pte(pmap_kernel(), va, &pdep, &ptep) == FALSE)
+ if (pmap_get_pde_pte(kernel_pmap, va, &pdep, &ptep) == FALSE)
return (NULL);
return (ptep);
}
@@ -269,9 +247,7 @@ void *pmap_mapdev(vm_offset_t, vm_size_t);
void pmap_unmapdev(vm_offset_t, vm_size_t);
vm_page_t pmap_use_pt(pmap_t, vm_offset_t);
void pmap_debug(int);
-#if (ARM_MMU_V6 + ARM_MMU_V7) == 0
void pmap_map_section(vm_offset_t, vm_offset_t, vm_offset_t, int, int);
-#endif
void pmap_link_l2pt(vm_offset_t, vm_offset_t, struct pv_addr *);
vm_size_t pmap_map_chunk(vm_offset_t, vm_offset_t, vm_offset_t, vm_size_t, int, int);
void
@@ -339,119 +315,9 @@ extern int pmap_needs_pte_sync;
/*
* User-visible names for the ones that vary with MMU class.
*/
-#if (ARM_MMU_V6 + ARM_MMU_V7) != 0
-#define L2_AP(x) (L2_AP0(x))
-#else
#define L2_AP(x) (L2_AP0(x) | L2_AP1(x) | L2_AP2(x) | L2_AP3(x))
-#endif
-
-#if (ARM_MMU_V6 + ARM_MMU_V7) != 0
-/*
- * AP[2:1] access permissions model:
- *
- * AP[2](APX) - Write Disable
- * AP[1] - User Enable
- * AP[0] - Reference Flag
- *
- * AP[2] AP[1] Kernel User
- * 0 0 R/W N
- * 0 1 R/W R/W
- * 1 0 R N
- * 1 1 R R
- *
- */
-#define L2_S_PROT_R (0) /* kernel read */
-#define L2_S_PROT_U (L2_AP0(2)) /* user read */
-#define L2_S_REF (L2_AP0(1)) /* reference flag */
-
-#define L2_S_PROT_MASK (L2_S_PROT_U|L2_S_PROT_R|L2_APX)
-#define L2_S_EXECUTABLE(pte) (!(pte & L2_XN))
-#define L2_S_WRITABLE(pte) (!(pte & L2_APX))
-#define L2_S_REFERENCED(pte) (!!(pte & L2_S_REF))
-
-#ifndef SMP
-#define L1_S_CACHE_MASK (L1_S_TEX_MASK|L1_S_B|L1_S_C)
-#define L2_L_CACHE_MASK (L2_L_TEX_MASK|L2_B|L2_C)
-#define L2_S_CACHE_MASK (L2_S_TEX_MASK|L2_B|L2_C)
-#else
-#define L1_S_CACHE_MASK (L1_S_TEX_MASK|L1_S_B|L1_S_C|L1_SHARED)
-#define L2_L_CACHE_MASK (L2_L_TEX_MASK|L2_B|L2_C|L2_SHARED)
-#define L2_S_CACHE_MASK (L2_S_TEX_MASK|L2_B|L2_C|L2_SHARED)
-#endif /* SMP */
-
-#define L1_S_PROTO (L1_TYPE_S)
-#define L1_C_PROTO (L1_TYPE_C)
-#define L2_S_PROTO (L2_TYPE_S)
-
-/*
- * Promotion to a 1MB (SECTION) mapping requires that the corresponding
- * 4KB (SMALL) page mappings have identical settings for the following fields:
- */
-#define L2_S_PROMOTE (L2_S_REF | L2_SHARED | L2_S_PROT_MASK | \
- L2_XN | L2_S_PROTO)
-/*
- * In order to compare 1MB (SECTION) entry settings with the 4KB (SMALL)
- * page mapping it is necessary to read and shift appropriate bits from
- * L1 entry to positions of the corresponding bits in the L2 entry.
- */
-#define L1_S_DEMOTE(l1pd) ((((l1pd) & L1_S_PROTO) >> 0) | \
- (((l1pd) & L1_SHARED) >> 6) | \
- (((l1pd) & L1_S_REF) >> 6) | \
- (((l1pd) & L1_S_PROT_MASK) >> 6) | \
- (((l1pd) & L1_S_XN) >> 4))
-
-#ifndef SMP
-#define ARM_L1S_STRONG_ORD (0)
-#define ARM_L1S_DEVICE_NOSHARE (L1_S_TEX(2))
-#define ARM_L1S_DEVICE_SHARE (L1_S_B)
-#define ARM_L1S_NRML_NOCACHE (L1_S_TEX(1))
-#define ARM_L1S_NRML_IWT_OWT (L1_S_C)
-#define ARM_L1S_NRML_IWB_OWB (L1_S_C|L1_S_B)
-#define ARM_L1S_NRML_IWBA_OWBA (L1_S_TEX(1)|L1_S_C|L1_S_B)
-
-#define ARM_L2L_STRONG_ORD (0)
-#define ARM_L2L_DEVICE_NOSHARE (L2_L_TEX(2))
-#define ARM_L2L_DEVICE_SHARE (L2_B)
-#define ARM_L2L_NRML_NOCACHE (L2_L_TEX(1))
-#define ARM_L2L_NRML_IWT_OWT (L2_C)
-#define ARM_L2L_NRML_IWB_OWB (L2_C|L2_B)
-#define ARM_L2L_NRML_IWBA_OWBA (L2_L_TEX(1)|L2_C|L2_B)
-
-#define ARM_L2S_STRONG_ORD (0)
-#define ARM_L2S_DEVICE_NOSHARE (L2_S_TEX(2))
-#define ARM_L2S_DEVICE_SHARE (L2_B)
-#define ARM_L2S_NRML_NOCACHE (L2_S_TEX(1))
-#define ARM_L2S_NRML_IWT_OWT (L2_C)
-#define ARM_L2S_NRML_IWB_OWB (L2_C|L2_B)
-#define ARM_L2S_NRML_IWBA_OWBA (L2_S_TEX(1)|L2_C|L2_B)
-#else
-#define ARM_L1S_STRONG_ORD (0)
-#define ARM_L1S_DEVICE_NOSHARE (L1_S_TEX(2))
-#define ARM_L1S_DEVICE_SHARE (L1_S_B)
-#define ARM_L1S_NRML_NOCACHE (L1_S_TEX(1)|L1_SHARED)
-#define ARM_L1S_NRML_IWT_OWT (L1_S_C|L1_SHARED)
-#define ARM_L1S_NRML_IWB_OWB (L1_S_C|L1_S_B|L1_SHARED)
-#define ARM_L1S_NRML_IWBA_OWBA (L1_S_TEX(1)|L1_S_C|L1_S_B|L1_SHARED)
-
-#define ARM_L2L_STRONG_ORD (0)
-#define ARM_L2L_DEVICE_NOSHARE (L2_L_TEX(2))
-#define ARM_L2L_DEVICE_SHARE (L2_B)
-#define ARM_L2L_NRML_NOCACHE (L2_L_TEX(1)|L2_SHARED)
-#define ARM_L2L_NRML_IWT_OWT (L2_C|L2_SHARED)
-#define ARM_L2L_NRML_IWB_OWB (L2_C|L2_B|L2_SHARED)
-#define ARM_L2L_NRML_IWBA_OWBA (L2_L_TEX(1)|L2_C|L2_B|L2_SHARED)
-
-#define ARM_L2S_STRONG_ORD (0)
-#define ARM_L2S_DEVICE_NOSHARE (L2_S_TEX(2))
-#define ARM_L2S_DEVICE_SHARE (L2_B)
-#define ARM_L2S_NRML_NOCACHE (L2_S_TEX(1)|L2_SHARED)
-#define ARM_L2S_NRML_IWT_OWT (L2_C|L2_SHARED)
-#define ARM_L2S_NRML_IWB_OWB (L2_C|L2_B|L2_SHARED)
-#define ARM_L2S_NRML_IWBA_OWBA (L2_S_TEX(1)|L2_C|L2_B|L2_SHARED)
-#endif /* SMP */
-
-#elif ARM_NMMUS > 1
+#if ARM_NMMUS > 1
/* More than one MMU class configured; use variables. */
#define L2_S_PROT_U pte_l2_s_prot_u
#define L2_S_PROT_W pte_l2_s_prot_w
@@ -493,7 +359,7 @@ extern int pmap_needs_pte_sync;
#endif /* ARM_NMMUS > 1 */
-#if defined(CPU_XSCALE_81342) || ARM_ARCH_6 || ARM_ARCH_7A
+#if defined(CPU_XSCALE_81342)
#define PMAP_NEEDS_PTE_SYNC 1
#define PMAP_INCLUDE_PTE_SYNC
#else
@@ -504,8 +370,6 @@ extern int pmap_needs_pte_sync;
* These macros return various bits based on kernel/user and protection.
* Note that the compiler will usually fold these at compile time.
*/
-#if (ARM_MMU_V6 + ARM_MMU_V7) == 0
-
#define L1_S_PROT_U (L1_S_AP(AP_U))
#define L1_S_PROT_W (L1_S_AP(AP_W))
#define L1_S_PROT_MASK (L1_S_PROT_U|L1_S_PROT_W)
@@ -523,27 +387,6 @@ extern int pmap_needs_pte_sync;
#define L2_S_PROT(ku, pr) ((((ku) == PTE_USER) ? L2_S_PROT_U : 0) | \
(((pr) & VM_PROT_WRITE) ? L2_S_PROT_W : 0))
-#else
-#define L1_S_PROT_U (L1_S_AP(AP_U))
-#define L1_S_PROT_W (L1_S_APX) /* Write disable */
-#define L1_S_PROT_MASK (L1_S_PROT_W|L1_S_PROT_U)
-#define L1_S_REF (L1_S_AP(AP_REF)) /* Reference flag */
-#define L1_S_WRITABLE(pd) (!((pd) & L1_S_PROT_W))
-#define L1_S_EXECUTABLE(pd) (!((pd) & L1_S_XN))
-#define L1_S_REFERENCED(pd) ((pd) & L1_S_REF)
-
-#define L1_S_PROT(ku, pr) (((((ku) == PTE_KERNEL) ? 0 : L1_S_PROT_U) | \
- (((pr) & VM_PROT_WRITE) ? 0 : L1_S_PROT_W) | \
- (((pr) & VM_PROT_EXECUTE) ? 0 : L1_S_XN)))
-
-#define L2_L_PROT_MASK (L2_APX|L2_AP0(0x3))
-#define L2_L_PROT(ku, pr) (L2_L_PROT_MASK & ~((((ku) == PTE_KERNEL) ? L2_S_PROT_U : 0) | \
- (((pr) & VM_PROT_WRITE) ? L2_APX : 0)))
-
-#define L2_S_PROT(ku, pr) (L2_S_PROT_MASK & ~((((ku) == PTE_KERNEL) ? L2_S_PROT_U : 0) | \
- (((pr) & VM_PROT_WRITE) ? L2_APX : 0)))
-
-#endif
/*
* Macros to test if a mapping is mappable with an L1 Section mapping
@@ -618,15 +461,12 @@ extern void (*pmap_copy_page_offs_func)(vm_paddr_t a_phys,
vm_offset_t a_offs, vm_paddr_t b_phys, vm_offset_t b_offs, int cnt);
extern void (*pmap_zero_page_func)(vm_paddr_t, int, int);
-#if (ARM_MMU_GENERIC + ARM_MMU_V6 + ARM_MMU_V7) != 0 || defined(CPU_XSCALE_81342)
+#if ARM_MMU_GENERIC != 0 || defined(CPU_XSCALE_81342)
void pmap_copy_page_generic(vm_paddr_t, vm_paddr_t);
void pmap_zero_page_generic(vm_paddr_t, int, int);
void pmap_pte_init_generic(void);
-#if (ARM_MMU_V6 + ARM_MMU_V7) != 0
-void pmap_pte_init_mmu_v6(void);
-#endif /* (ARM_MMU_V6 + ARM_MMU_V7) != 0 */
-#endif /* (ARM_MMU_GENERIC + ARM_MMU_V6 + ARM_MMU_V7) != 0 */
+#endif /* ARM_MMU_GENERIC != 0 */
#if ARM_MMU_XSCALE == 1
void pmap_copy_page_xscale(vm_paddr_t, vm_paddr_t);
@@ -704,4 +544,4 @@ extern vm_paddr_t dump_avail[];
#endif /* !LOCORE */
#endif /* !_MACHINE_PMAP_H_ */
-#endif /* !ARM_NEW_PMAP */
+#endif /* __ARM_ARCH >= 6 */
diff --git a/sys/arm/include/pte.h b/sys/arm/include/pte.h
index 42e26ab61584..8c26aabe5ce7 100644
--- a/sys/arm/include/pte.h
+++ b/sys/arm/include/pte.h
@@ -33,9 +33,11 @@
*
* $FreeBSD$
*/
-#ifdef ARM_NEW_PMAP
+#include <machine/acle-compat.h>
+
+#if __ARM_ARCH >= 6
#include <machine/pte-v6.h>
-#else /* ARM_NEW_PMAP */
+#else /* __ARM_ARCH >= 6 */
#ifndef _MACHINE_PTE_H_
#define _MACHINE_PTE_H_
@@ -356,6 +358,6 @@ typedef pt_entry_t pt2_entry_t; /* compatibility with v6 */
* 1 X 1 1 1 Y Y WT Y Y
*/
#endif /* !_MACHINE_PTE_H_ */
-#endif /* !ARM_NEW_PMAP */
+#endif /* __ARM_ARCH >= 6 */
/* End of pte.h */
diff --git a/sys/arm/include/reg.h b/sys/arm/include/reg.h
index 2f8c2ede7d21..d4cc4575627b 100644
--- a/sys/arm/include/reg.h
+++ b/sys/arm/include/reg.h
@@ -19,7 +19,9 @@ struct fpreg {
};
struct dbreg {
- unsigned int dr[8]; /* debug registers */
+#define ARM_WR_MAX 16 /* Maximum number of watchpoint registers */
+ unsigned int dbg_wcr[ARM_WR_MAX]; /* Watchpoint Control Registers */
+ unsigned int dbg_wvr[ARM_WR_MAX]; /* Watchpoint Value Registers */
};
#ifdef _KERNEL
diff --git a/sys/arm/include/sf_buf.h b/sys/arm/include/sf_buf.h
index eba8488e8f9c..5228864946c0 100644
--- a/sys/arm/include/sf_buf.h
+++ b/sys/arm/include/sf_buf.h
@@ -29,11 +29,13 @@
#ifndef _MACHINE_SF_BUF_H_
#define _MACHINE_SF_BUF_H_
+#include <machine/acle-compat.h>
+
static inline void
sf_buf_map(struct sf_buf *sf, int flags)
{
-#ifdef ARM_NEW_PMAP
+#if __ARM_ARCH >= 6
pmap_qenter(sf->kva, &(sf->m), 1);
#else
pmap_kenter(sf->kva, VM_PAGE_TO_PHYS(sf->m));
@@ -44,7 +46,7 @@ static inline int
sf_buf_unmap(struct sf_buf *sf)
{
-#ifdef ARM_NEW_PMAP
+#if __ARM_ARCH >= 6
pmap_qremove(sf->kva, 1);
#else
pmap_kremove(sf->kva);
diff --git a/sys/arm/include/smp.h b/sys/arm/include/smp.h
index c50b99db1236..a993cc0579c2 100644
--- a/sys/arm/include/smp.h
+++ b/sys/arm/include/smp.h
@@ -14,8 +14,8 @@ enum {
IPI_STOP,
IPI_STOP_HARD = IPI_STOP, /* These are synonyms on arm. */
IPI_HARDCLOCK,
- IPI_TLB,
- IPI_CACHE,
+ IPI_TLB, /* Not used now, but keep it reserved. */
+ IPI_CACHE, /* Not used now, but keep it reserved. */
INTR_IPI_COUNT
};
#else
@@ -25,8 +25,8 @@ enum {
#define IPI_STOP 4
#define IPI_STOP_HARD 4
#define IPI_HARDCLOCK 6
-#define IPI_TLB 7
-#define IPI_CACHE 8
+#define IPI_TLB 7 /* Not used now, but keep it reserved. */
+#define IPI_CACHE 8 /* Not used now, but keep it reserved. */
#endif /* INTRNG */
void init_secondary(int cpu);
diff --git a/sys/arm/include/vm.h b/sys/arm/include/vm.h
index 8fb230e23de8..eb670256f47c 100644
--- a/sys/arm/include/vm.h
+++ b/sys/arm/include/vm.h
@@ -29,20 +29,24 @@
#ifndef _MACHINE_VM_H_
#define _MACHINE_VM_H_
-#ifdef ARM_NEW_PMAP
+#include <machine/acle-compat.h>
+
+#if __ARM_ARCH >= 6
#include <machine/pte-v6.h>
-#define VM_MEMATTR_WB_WA ((vm_memattr_t)PTE2_ATTR_WB_WA)
-#define VM_MEMATTR_NOCACHE ((vm_memattr_t)PTE2_ATTR_NOCACHE)
-#define VM_MEMATTR_DEVICE ((vm_memattr_t)PTE2_ATTR_DEVICE)
-#define VM_MEMATTR_SO ((vm_memattr_t)PTE2_ATTR_SO)
-#define VM_MEMATTR_WT ((vm_memattr_t)PTE2_ATTR_WT)
+#define VM_MEMATTR_WB_WA ((vm_memattr_t)0)
+#define VM_MEMATTR_NOCACHE ((vm_memattr_t)1)
+#define VM_MEMATTR_DEVICE ((vm_memattr_t)2)
+#define VM_MEMATTR_SO ((vm_memattr_t)3)
+#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)4)
#define VM_MEMATTR_DEFAULT VM_MEMATTR_WB_WA
#define VM_MEMATTR_UNCACHEABLE VM_MEMATTR_SO /* misused by DMA */
-#define VM_MEMATTR_WRITE_COMBINING VM_MEMATTR_WT /* for DRM */
+#ifdef _KERNEL
+/* Don't export aliased VM_MEMATTR to userland */
+#define VM_MEMATTR_WRITE_COMBINING VM_MEMATTR_WRITE_THROUGH /* for DRM */
#define VM_MEMATTR_WRITE_BACK VM_MEMATTR_WB_WA /* for DRM */
-
+#endif
#else
/* Memory attribute configuration. */
#define VM_MEMATTR_DEFAULT 0
diff --git a/sys/arm/mv/armada38x/pmsu.c b/sys/arm/mv/armada38x/pmsu.c
index a84ede02a4a3..110278b4f181 100644
--- a/sys/arm/mv/armada38x/pmsu.c
+++ b/sys/arm/mv/armada38x/pmsu.c
@@ -36,10 +36,12 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/resource.h>
+#include <sys/systm.h>
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <machine/cpu.h>
#include <machine/fdt.h>
#include <machine/smp.h>
@@ -143,8 +145,7 @@ pmsu_boot_secondary_cpu(void)
bus_space_write_4(fdtbus_bs_tag, vaddr, PMSU_BOOT_ADDR_REDIRECT_OFFSET(1),
pmap_kextract((vm_offset_t)mpentry));
- cpu_idcache_wbinv_all();
- cpu_l2cache_wbinv_all();
+ dcache_wbinv_poc_all();
armv7_sev();
bus_space_unmap(fdtbus_bs_tag, vaddr, MV_PMSU_REGS_LEN);
diff --git a/sys/arm/mv/armadaxp/armadaxp.c b/sys/arm/mv/armadaxp/armadaxp.c
index 693ae6a93e65..3cb03faeae62 100644
--- a/sys/arm/mv/armadaxp/armadaxp.c
+++ b/sys/arm/mv/armadaxp/armadaxp.c
@@ -128,7 +128,7 @@ get_tclk(void)
{
uint32_t cputype;
- cputype = cpufunc_id();
+ cputype = cpu_ident();
cputype &= CPU_ID_CPU_MASK;
if (cputype == CPU_ID_MV88SV584X_V7)
diff --git a/sys/arm/mv/armadaxp/armadaxp_mp.c b/sys/arm/mv/armadaxp/armadaxp_mp.c
index 6685204b59ed..52f35084a4bd 100644
--- a/sys/arm/mv/armadaxp/armadaxp_mp.c
+++ b/sys/arm/mv/armadaxp/armadaxp_mp.c
@@ -40,6 +40,7 @@
#include <dev/fdt/fdt_common.h>
+#include <machine/cpu.h>
#include <machine/smp.h>
#include <machine/fdt.h>
#include <machine/armreg.h>
@@ -111,7 +112,7 @@ platform_mp_start_ap(void)
* Initialization procedure depends on core revision,
* in this step CHIP ID is checked to choose proper procedure
*/
- cputype = cpufunc_id();
+ cputype = cpu_ident();
cputype &= CPU_ID_CPU_MASK;
/*
@@ -174,7 +175,7 @@ platform_mp_start_ap(void)
bus_space_write_4(fdtbus_bs_tag, CPU_PMU(cpu_num), CPU_PMU_BOOT,
pmap_kextract((vm_offset_t)mpentry));
- cpu_idcache_wbinv_all();
+ dcache_wbinv_poc_all();
for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ )
bus_space_write_4(fdtbus_bs_tag, MP, MP_SW_RESET(cpu_num), 0);
diff --git a/sys/arm/mv/mv_common.c b/sys/arm/mv/mv_common.c
index 8e9465512853..afefc7f28600 100644
--- a/sys/arm/mv/mv_common.c
+++ b/sys/arm/mv/mv_common.c
@@ -377,7 +377,7 @@ soc_id(uint32_t *dev, uint32_t *rev)
* Notice: system identifiers are available in the registers range of
* PCIE controller, so using this function is only allowed (and
* possible) after the internal registers range has been mapped in via
- * pmap_devmap_bootstrap().
+ * arm_devmap_bootstrap().
*/
*dev = bus_space_read_4(fdtbus_bs_tag, MV_PCIE_BASE, 0) >> 16;
*rev = bus_space_read_4(fdtbus_bs_tag, MV_PCIE_BASE, 8) & 0xff;
diff --git a/sys/arm/mv/mv_machdep.c b/sys/arm/mv/mv_machdep.c
index 9b307730b387..8f0375bc1b05 100644
--- a/sys/arm/mv/mv_machdep.c
+++ b/sys/arm/mv/mv_machdep.c
@@ -337,7 +337,7 @@ __weak_reference(mv_default_fdt_pci_devmap, mv_pci_devmap);
*/
/*
- * Construct pmap_devmap[] with DT-derived config data.
+ * Construct devmap table with DT-derived config data.
*/
int
platform_devmap_init(void)
diff --git a/sys/arm/mv/orion/db88f5xxx.c b/sys/arm/mv/orion/db88f5xxx.c
index f59d511f4d09..15751cc990b7 100644
--- a/sys/arm/mv/orion/db88f5xxx.c
+++ b/sys/arm/mv/orion/db88f5xxx.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr.h>
-#include <machine/pte.h>
#include <machine/vmparam.h>
#include <arm/mv/mvreg.h>
@@ -74,7 +73,7 @@ __FBSDID("$FreeBSD$");
int platform_pci_get_irq(u_int bus, u_int slot, u_int func, u_int pin);
/* Static device mappings. */
-const struct pmap_devmap pmap_devmap[] = {
+const struct arm_devmap_entry db88f5xxx_devmap[] = {
/*
* Map the on-board devices VA == PA so that we can access them
* with the MMU on or off.
diff --git a/sys/arm/rockchip/rk30xx_mp.c b/sys/arm/rockchip/rk30xx_mp.c
index 38b6b41e13c7..5de2eff14757 100644
--- a/sys/arm/rockchip/rk30xx_mp.c
+++ b/sys/arm/rockchip/rk30xx_mp.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <machine/cpu.h>
#include <machine/smp.h>
#include <machine/fdt.h>
#include <machine/intr.h>
@@ -171,8 +172,7 @@ platform_mp_start_ap(void)
bus_space_write_region_4(fdtbus_bs_tag, imem, 0,
(uint32_t *)&rk30xx_boot2, 8);
- cpu_idcache_wbinv_all();
- cpu_l2cache_wbinv_all();
+ dcache_wbinv_poc_all();
/* Start all cores */
val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON);
diff --git a/sys/arm/samsung/exynos/exynos5_mp.c b/sys/arm/samsung/exynos/exynos5_mp.c
index 8eb0d29fcedd..44b2844ce254 100644
--- a/sys/arm/samsung/exynos/exynos5_mp.c
+++ b/sys/arm/samsung/exynos/exynos5_mp.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <machine/cpu.h>
#include <machine/smp.h>
#include <machine/fdt.h>
#include <machine/intr.h>
@@ -135,8 +136,7 @@ platform_mp_start_ap(void)
bus_space_write_4(fdtbus_bs_tag, sysram, 0x0,
pmap_kextract((vm_offset_t)mpentry));
- cpu_idcache_wbinv_all();
- cpu_l2cache_wbinv_all();
+ dcache_wbinv_poc_all();
armv7_sev();
bus_space_unmap(fdtbus_bs_tag, sysram, 0x100);
diff --git a/sys/arm/ti/omap4/omap4_mp.c b/sys/arm/ti/omap4/omap4_mp.c
index 1a095ab6444c..6cea1cc697d2 100644
--- a/sys/arm/ti/omap4/omap4_mp.c
+++ b/sys/arm/ti/omap4/omap4_mp.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <machine/cpu.h>
#include <machine/smp.h>
#include <machine/fdt.h>
#include <machine/intr.h>
@@ -72,8 +73,8 @@ platform_mp_start_ap(void)
/* Enable the SCU */
*(volatile unsigned int *)scu_addr |= 1;
//*(volatile unsigned int *)(scu_addr + 0x30) |= 1;
- cpu_idcache_wbinv_all();
- cpu_l2cache_wbinv_all();
+ dcache_wbinv_poc_all();
+
ti_smc0(0x200, 0xfffffdff, MODIFY_AUX_CORE_0);
ti_smc0(pmap_kextract((vm_offset_t)mpentry), 0, WRITE_AUX_CORE_1);
armv7_sev();
diff --git a/sys/arm/ti/omap4/pandaboard/pandaboard.c b/sys/arm/ti/omap4/pandaboard/pandaboard.c
index 20e5e8a6da87..f557f736c56d 100644
--- a/sys/arm/ti/omap4/pandaboard/pandaboard.c
+++ b/sys/arm/ti/omap4/pandaboard/pandaboard.c
@@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$");
#include <vm/pmap.h>
#include <machine/bus.h>
-#include <machine/pte.h>
#include <machine/vmparam.h>
#include <machine/fdt.h>
diff --git a/sys/arm/ti/ti_cpuid.c b/sys/arm/ti/ti_cpuid.c
index 38af285c1abd..b2f0f65ab9b6 100644
--- a/sys/arm/ti/ti_cpuid.c
+++ b/sys/arm/ti/ti_cpuid.c
@@ -120,7 +120,7 @@ omap4_get_revision(void)
* the ARM cpuid to get the correct revision.
*/
if (revision == 0) {
- id_code = cpufunc_id();
+ id_code = cpu_ident();
revision = (id_code & 0xf) - 1;
}
diff --git a/sys/arm/versatile/versatile_machdep.c b/sys/arm/versatile/versatile_machdep.c
index 2869f1b5d668..ac3ebd22ed40 100644
--- a/sys/arm/versatile/versatile_machdep.c
+++ b/sys/arm/versatile/versatile_machdep.c
@@ -88,7 +88,7 @@ static struct arm_devmap_entry fdt_devmap[FDT_DEVMAP_MAX] = {
/*
- * Construct pmap_devmap[] with DT-derived config data.
+ * Construct devmap table with DT-derived config data.
*/
int
platform_devmap_init(void)
diff --git a/sys/arm/xilinx/zy7_ehci.c b/sys/arm/xilinx/zy7_ehci.c
index f74a02f3b27c..f03c131adb4b 100644
--- a/sys/arm/xilinx/zy7_ehci.c
+++ b/sys/arm/xilinx/zy7_ehci.c
@@ -138,6 +138,18 @@ __FBSDID("$FreeBSD$");
#define EHCI_REG_OFFSET ZY7_USB_CAPLENGTH_HCIVERSION
#define EHCI_REG_SIZE 0x100
+static void
+zy7_ehci_post_reset(struct ehci_softc *ehci_softc)
+{
+ uint32_t usbmode;
+
+ /* Force HOST mode */
+ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
+ usbmode &= ~EHCI_UM_CM;
+ usbmode |= EHCI_UM_CM_HOST;
+ EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
+}
+
static int
zy7_phy_config(device_t dev, bus_space_tag_t io_tag, bus_space_handle_t bsh)
{
@@ -275,8 +287,9 @@ zy7_ehci_attach(device_t dev)
}
/* Customization. */
- sc->sc_flags |= EHCI_SCFLG_SETMODE | EHCI_SCFLG_TT |
- EHCI_SCFLG_NORESTERM;
+ sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM;
+ sc->sc_vendor_post_reset = zy7_ehci_post_reset;
+ sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc;
/* Modify FIFO burst threshold from 2 to 8. */
bus_space_write_4(sc->sc_io_tag, bsh,
diff --git a/sys/arm/xilinx/zy7_mp.c b/sys/arm/xilinx/zy7_mp.c
index f71740ce395c..74528ef870b2 100644
--- a/sys/arm/xilinx/zy7_mp.c
+++ b/sys/arm/xilinx/zy7_mp.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <machine/cpu.h>
#include <machine/smp.h>
#include <machine/fdt.h>
#include <machine/intr.h>
@@ -104,8 +105,7 @@ platform_mp_start_ap(void)
* magic location, 0xfffffff0, isn't in the SCU's filtering range so it
* needs a write-back too.
*/
- cpu_idcache_wbinv_all();
- cpu_l2cache_wbinv_all();
+ dcache_wbinv_poc_all();
/* Wake up CPU1. */
armv7_sev();
diff --git a/sys/arm/xscale/i80321/ep80219_machdep.c b/sys/arm/xscale/i80321/ep80219_machdep.c
deleted file mode 100644
index 6c0d1f5af410..000000000000
--- a/sys/arm/xscale/i80321/ep80219_machdep.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */
-
-/*-
- * Copyright (c) 1994-1998 Mark Brinicombe.
- * Copyright (c) 1994 Brini.
- * All rights reserved.
- *
- * This code is derived from software written for Brini by Mark Brinicombe
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Brini.
- * 4. The name of the company nor the name of the author may be used to
- * endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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.
- *
- * RiscBSD kernel project
- *
- * machdep.c
- *
- * Machine dependant functions for kernel setup
- *
- * This file needs a lot of work.
- *
- * Created : 17/09/94
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_kstack_pages.h"
-
-#define _ARM32_BUS_DMA_PRIVATE
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/sysproto.h>
-#include <sys/signalvar.h>
-#include <sys/imgact.h>
-#include <sys/kernel.h>
-#include <sys/ktr.h>
-#include <sys/linker.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mutex.h>
-#include <sys/pcpu.h>
-#include <sys/proc.h>
-#include <sys/ptrace.h>
-#include <sys/cons.h>
-#include <sys/bio.h>
-#include <sys/bus.h>
-#include <sys/buf.h>
-#include <sys/exec.h>
-#include <sys/kdb.h>
-#include <sys/msgbuf.h>
-#include <machine/reg.h>
-#include <machine/cpu.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_object.h>
-#include <vm/vm_page.h>
-#include <vm/vm_map.h>
-#include <machine/devmap.h>
-#include <machine/vmparam.h>
-#include <machine/pcb.h>
-#include <machine/undefined.h>
-#include <machine/machdep.h>
-#include <machine/metadata.h>
-#include <machine/armreg.h>
-#include <machine/bus.h>
-#include <machine/physmem.h>
-#include <sys/reboot.h>
-
-#include <arm/xscale/i80321/i80321reg.h>
-#include <arm/xscale/i80321/i80321var.h>
-#include <arm/xscale/i80321/iq80321reg.h>
-#include <arm/xscale/i80321/obiovar.h>
-
-#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */
-#define KERNEL_PT_IOPXS 1
-#define KERNEL_PT_BEFOREKERN 2
-#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */
-#define KERNEL_PT_AFKERNEL_NUM 9
-
-/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */
-#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM)
-
-struct pv_addr kernel_pt_table[NUM_KERNEL_PTS];
-
-/* Physical and virtual addresses for some global pages */
-
-struct pv_addr systempage;
-struct pv_addr msgbufpv;
-struct pv_addr irqstack;
-struct pv_addr undstack;
-struct pv_addr abtstack;
-struct pv_addr kernelstack;
-struct pv_addr minidataclean;
-
-
-/* #define IQ80321_OBIO_BASE 0xfe800000UL */
-/* #define IQ80321_OBIO_SIZE 0x00100000UL */
-
-/* Static device mappings. */
-static const struct arm_devmap_entry ep80219_devmap[] = {
- /*
- * Map the on-board devices VA == PA so that we can access them
- * with the MMU on or off.
- */
- {
- IQ80321_OBIO_BASE,
- IQ80321_OBIO_BASE,
- IQ80321_OBIO_SIZE,
- VM_PROT_READ|VM_PROT_WRITE,
- PTE_DEVICE,
- },
- {
- IQ80321_IOW_VBASE,
- VERDE_OUT_XLATE_IO_WIN0_BASE,
- VERDE_OUT_XLATE_IO_WIN_SIZE,
- VM_PROT_READ|VM_PROT_WRITE,
- PTE_DEVICE,
- },
- {
- IQ80321_80321_VBASE,
- VERDE_PMMR_BASE,
- VERDE_PMMR_SIZE,
- VM_PROT_READ|VM_PROT_WRITE,
- PTE_DEVICE,
- },
- {
- 0,
- 0,
- 0,
- 0,
- 0,
- }
-};
-
-extern vm_offset_t xscale_cache_clean_addr;
-
-void *
-initarm(struct arm_boot_params *abp)
-{
- struct pv_addr kernel_l1pt;
- struct pv_addr dpcpu;
- int loop, i;
- u_int l1pagetable;
- vm_offset_t freemempos;
- vm_offset_t freemem_pt;
- vm_offset_t afterkern;
- vm_offset_t freemem_after;
- vm_offset_t lastaddr;
- uint32_t memsize, memstart;
-
- lastaddr = parse_boot_param(abp);
- arm_physmem_kernaddr = abp->abp_physaddr;
- set_cpufuncs();
- pcpu_init(pcpup, 0, sizeof(struct pcpu));
- PCPU_SET(curthread, &thread0);
-
- /* Do basic tuning, hz etc */
- init_param1();
-
- freemempos = 0xa0200000;
- /* Define a macro to simplify memory allocation */
-#define valloc_pages(var, np) \
- alloc_pages((var).pv_pa, (np)); \
- (var).pv_va = (var).pv_pa + 0x20000000;
-
-#define alloc_pages(var, np) \
- freemempos -= (np * PAGE_SIZE); \
- (var) = freemempos; \
- memset((char *)(var), 0, ((np) * PAGE_SIZE));
-
- while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0)
- freemempos -= PAGE_SIZE;
- valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
- for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
- if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) {
- valloc_pages(kernel_pt_table[loop],
- L2_TABLE_SIZE / PAGE_SIZE);
- } else {
- kernel_pt_table[loop].pv_pa = freemempos +
- (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) *
- L2_TABLE_SIZE_REAL;
- kernel_pt_table[loop].pv_va =
- kernel_pt_table[loop].pv_pa + 0x20000000;
- }
- }
- freemem_pt = freemempos;
- freemempos = 0xa0100000;
- /*
- * Allocate a page for the system page mapped to V0x00000000
- * This page will just contain the system vectors and can be
- * shared by all processes.
- */
- valloc_pages(systempage, 1);
-
- /* Allocate dynamic per-cpu area. */
- valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE);
- dpcpu_init((void *)dpcpu.pv_va, 0);
-
- /* Allocate stacks for all modes */
- valloc_pages(irqstack, IRQ_STACK_SIZE);
- valloc_pages(abtstack, ABT_STACK_SIZE);
- valloc_pages(undstack, UND_STACK_SIZE);
- valloc_pages(kernelstack, kstack_pages);
- alloc_pages(minidataclean.pv_pa, 1);
- valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
- /*
- * Allocate memory for the l1 and l2 page tables. The scheme to avoid
- * wasting memory by allocating the l1pt on the first 16k memory was
- * taken from NetBSD rpc_machdep.c. NKPT should be greater than 12 for
- * this to work (which is supposed to be the case).
- */
-
- /*
- * Now we start construction of the L1 page table
- * We start by mapping the L2 page tables into the L1.
- * This means that we can replace L1 mappings later on if necessary
- */
- l1pagetable = kernel_l1pt.pv_va;
-
- /* Map the L2 pages tables in the L1 page table */
- pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00100000 - 1),
- &kernel_pt_table[KERNEL_PT_SYS]);
- pmap_link_l2pt(l1pagetable, IQ80321_IOPXS_VBASE,
- &kernel_pt_table[KERNEL_PT_IOPXS]);
- pmap_link_l2pt(l1pagetable, KERNBASE,
- &kernel_pt_table[KERNEL_PT_BEFOREKERN]);
- pmap_map_chunk(l1pagetable, KERNBASE, IQ80321_SDRAM_START, 0x100000,
- VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
- pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, IQ80321_SDRAM_START + 0x100000,
- 0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
- pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, IQ80321_SDRAM_START + 0x200000,
- (((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE) & ~(L1_S_SIZE - 1),
- VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
- freemem_after = ((int)lastaddr + PAGE_SIZE) & ~(PAGE_SIZE - 1);
- afterkern = round_page(((vm_offset_t)lastaddr + L1_S_SIZE) & ~(L1_S_SIZE
- - 1));
- for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) {
- pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000,
- &kernel_pt_table[KERNEL_PT_AFKERNEL + i]);
- }
- pmap_map_entry(l1pagetable, afterkern, minidataclean.pv_pa,
- VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
-
-
- /* Map the Mini-Data cache clean area. */
- xscale_setup_minidata(l1pagetable, afterkern,
- minidataclean.pv_pa);
-
- /* Map the vector page. */
- pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
- VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
- arm_devmap_bootstrap(l1pagetable, ep80219_devmap);
- /*
- * Give the XScale global cache clean code an appropriately
- * sized chunk of unmapped VA space starting at 0xff000000
- * (our device mappings end before this address).
- */
- xscale_cache_clean_addr = 0xff000000U;
-
- cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
- setttb(kernel_l1pt.pv_pa);
- cpu_tlb_flushID();
- cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
- /*
- * Pages were allocated during the secondary bootstrap for the
- * stacks for different CPU modes.
- * We must now set the r13 registers in the different CPU modes to
- * point to these stacks.
- * Since the ARM stacks use STMFD etc. we must set r13 to the top end
- * of the stack memory.
- */
- set_stackptrs(0);
-
- /*
- * We must now clean the cache again....
- * Cleaning may be done by reading new data to displace any
- * dirty data in the cache. This will have happened in setttb()
- * but since we are boot strapping the addresses used for the read
- * may have just been remapped and thus the cache could be out
- * of sync. A re-clean after the switch will cure this.
- * After booting there are no gross relocations of the kernel thus
- * this problem will not occur after initarm().
- */
- cpu_idcache_wbinv_all();
- cpu_setup();
-
- /*
- * Fetch the SDRAM start/size from the i80321 SDRAM configration
- * registers.
- */
- i80321_calibrate_delay();
- i80321_sdram_bounds(obio_bs_tag, IQ80321_80321_VBASE + VERDE_MCU_BASE,
- &memstart, &memsize);
- physmem = memsize / PAGE_SIZE;
- cninit();
-
- undefined_init();
-
- init_proc0(kernelstack.pv_va);
-
- /* Enable MMU, I-cache, D-cache, write buffer. */
-
- arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
- vm_max_kernel_address = 0xe0000000;
- pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt);
- msgbufp = (void*)msgbufpv.pv_va;
- msgbufinit(msgbufp, msgbufsize);
- mutex_init();
-
- /*
- * Add the physical ram we have available.
- *
- * Exclude the kernel (and all the things we allocated which immediately
- * follow the kernel) from the VM allocation pool but not from crash
- * dumps. virtual_avail is a global variable which tracks the kva we've
- * "allocated" while setting up pmaps.
- *
- * Prepare the list of physical memory available to the vm subsystem.
- */
- arm_physmem_hardware_region(IQ80321_SDRAM_START, memsize);
- arm_physmem_exclude_region(freemem_pt, abp->abp_physaddr -
- freemem_pt, EXFLAG_NOALLOC);
- arm_physmem_exclude_region(freemempos, abp->abp_physaddr - 0x100000 -
- freemempos, EXFLAG_NOALLOC);
- arm_physmem_exclude_region(abp->abp_physaddr,
- virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC);
- arm_physmem_init_kernel_globals();
-
- init_param2(physmem);
- kdb_init();
- return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
- sizeof(struct pcb)));
-}
-
-extern int
-machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin)
-{
- int bus;
- int device;
- int func;
- uint32_t busno;
- struct i80321_pci_softc *sc = device_get_softc(pcib);
- bus = pci_get_bus(dev);
- device = pci_get_slot(dev);
- func = pci_get_function(dev);
- busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
- busno = PCIXSR_BUSNO(busno);
- if (busno == 0xff)
- busno = 0;
- if (bus != busno)
- goto no_mapping;
- switch (device) {
- /* EP80219 PCI */
- case 1: /* Ethernet i82555 10/100 */
- printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(0));
- return (ICU_INT_XINT(0));
- case 2: /* UART */
- printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(1));
- return (ICU_INT_XINT(1));
- case 3:
- /*
- * The S-ATA chips are behind the bridge, and all of
- * the S-ATA interrupts are wired together.
- */
- printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(2));
- return (ICU_INT_XINT(2));
- case 4: /* MINI-PIC_INT */
- printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(3));
- return( ICU_INT_XINT(3));
- default:
-no_mapping:
- printf("No mapping for %d/%d/%d/%c\n", bus, device, func, pin);
-
- }
- return (0);
-
-}
diff --git a/sys/arm/xscale/i80321/files.ep80219 b/sys/arm/xscale/i80321/files.ep80219
deleted file mode 100644
index 0eaf9db2872c..000000000000
--- a/sys/arm/xscale/i80321/files.ep80219
+++ /dev/null
@@ -1,11 +0,0 @@
-#$FreeBSD$
-#
-#
-# EP80219 Board Specific
-#
-arm/xscale/i80321/iq80321.c standard
-arm/xscale/i80321/ep80219_machdep.c standard
-arm/xscale/i80321/obio.c standard
-arm/xscale/i80321/uart_cpu_i80321.c optional uart
-arm/xscale/i80321/uart_bus_i80321.c optional uart
-dev/uart/uart_dev_ns8250.c optional uart
diff --git a/sys/arm/xscale/i80321/files.i80219 b/sys/arm/xscale/i80321/files.i80219
deleted file mode 100644
index 306376bbdd25..000000000000
--- a/sys/arm/xscale/i80321/files.i80219
+++ /dev/null
@@ -1,11 +0,0 @@
-#$FreeBSD$
-#
-# IOP Specific
-#
-arm/xscale/i80321/i80321.c standard
-arm/xscale/i80321/i80321_dma.c optional dma
-arm/xscale/i80321/i80321_mcu.c standard
-arm/xscale/i80321/i80321_pci.c optional pci
-arm/xscale/i80321/i80321_space.c standard
-arm/xscale/i80321/i80321_timer.c standard
-arm/xscale/i80321/i80321_wdog.c optional iopwdog
diff --git a/sys/arm/xscale/i80321/files.i80321 b/sys/arm/xscale/i80321/files.i80321
deleted file mode 100644
index bd318af1f650..000000000000
--- a/sys/arm/xscale/i80321/files.i80321
+++ /dev/null
@@ -1,9 +0,0 @@
-#$FreeBSD$
-arm/xscale/i80321/i80321.c standard
-arm/xscale/i80321/i80321_aau.c optional aau
-arm/xscale/i80321/i80321_dma.c optional dma
-arm/xscale/i80321/i80321_mcu.c standard
-arm/xscale/i80321/i80321_pci.c optional pci
-arm/xscale/i80321/i80321_space.c standard
-arm/xscale/i80321/i80321_timer.c standard
-arm/xscale/i80321/i80321_wdog.c optional iopwdog
diff --git a/sys/arm/xscale/i80321/files.iq31244 b/sys/arm/xscale/i80321/files.iq31244
deleted file mode 100644
index d28d49b3a6b1..000000000000
--- a/sys/arm/xscale/i80321/files.iq31244
+++ /dev/null
@@ -1,8 +0,0 @@
-#$FreeBSD$
-arm/xscale/i80321/iq80321.c standard
-arm/xscale/i80321/iq31244_machdep.c standard
-arm/xscale/i80321/iq31244_7seg.c optional iq31244_7seg
-arm/xscale/i80321/obio.c standard
-arm/xscale/i80321/uart_cpu_i80321.c optional uart
-arm/xscale/i80321/uart_bus_i80321.c optional uart
-dev/uart/uart_dev_ns8250.c optional uart
diff --git a/sys/arm/xscale/i80321/i80321.c b/sys/arm/xscale/i80321/i80321.c
deleted file mode 100644
index e65f38df5873..000000000000
--- a/sys/arm/xscale/i80321/i80321.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/* $NetBSD: i80321.c,v 1.15 2003/10/06 16:06:05 thorpej Exp $ */
-
-/*-
- * Copyright (c) 2002 Wasabi Systems, Inc.
- * All rights reserved.
- *
- * Written by Jason R. Thorpe for Wasabi Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
- * 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.
- */
-
-/*
- * Autoconfiguration support for the Intel i80321 I/O Processor.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-
-#define _ARM32_BUS_DMA_PRIVATE
-#include <machine/bus.h>
-#include <machine/intr.h>
-
-#include <arm/xscale/i80321/i80321reg.h>
-#include <arm/xscale/i80321/i80321var.h>
-#include <arm/xscale/i80321/i80321_intr.h>
-
-#include <dev/pci/pcireg.h>
-
-volatile uint32_t intr_enabled;
-uint32_t intr_steer = 0;
-/*
- * Statically-allocated bus_space stucture used to access the
- * i80321's own registers.
- */
-struct bus_space i80321_bs_tag;
-
-/*
- * There can be only one i80321, so we keep a global pointer to
- * the softc, so board-specific code can use features of the
- * i80321 without having to have a handle on the softc itself.
- */
-struct i80321_softc *i80321_softc;
-
-#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0)
-/*
- * i80321_attach:
- *
- * Board-independent attach routine for the i80321.
- */
-void
-i80321_attach(struct i80321_softc *sc)
-{
-
- i80321_softc = sc;
- uint32_t preg;
-
- /* We expect the Memory Controller to be already sliced off. */
-
- /*
- * Program the Inbound windows.
- */
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0,
- (0xffffffff - (sc->sc_iwin[0].iwin_size - 1)) & 0xffffffc0);
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR0,
- sc->sc_iwin[0].iwin_xlate);
- if (sc->sc_is_host) {
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- PCIR_BARS, sc->sc_iwin[0].iwin_base_lo);
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- PCIR_BARS + 0x04, sc->sc_iwin[0].iwin_base_hi);
- } else {
- sc->sc_iwin[0].iwin_base_lo = bus_space_read_4(sc->sc_st,
- sc->sc_atu_sh, PCIR_BARS);
- sc->sc_iwin[0].iwin_base_hi = bus_space_read_4(sc->sc_st,
- sc->sc_atu_sh, PCIR_BARS + 0x04);
- sc->sc_iwin[0].iwin_base_lo =
- PCI_MAPREG_MEM_ADDR(sc->sc_iwin[0].iwin_base_lo);
- }
-
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1,
- (0xffffffff - (sc->sc_iwin[1].iwin_size - 1)) & 0xffffffc0);
-
- /* no xlate for window 1 */
- if (sc->sc_is_host) {
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- PCIR_BARS + 0x08, sc->sc_iwin[1].iwin_base_lo);
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- PCIR_BARS + 0x0c, sc->sc_iwin[1].iwin_base_hi);
- } else {
- sc->sc_iwin[1].iwin_base_lo = bus_space_read_4(sc->sc_st,
- sc->sc_atu_sh, PCIR_BARS + 0x08);
- sc->sc_iwin[1].iwin_base_hi = bus_space_read_4(sc->sc_st,
- sc->sc_atu_sh, PCIR_BARS + 0x0c);
- sc->sc_iwin[1].iwin_base_lo =
- PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo);
- }
-
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2,
- (0xffffffff - (sc->sc_iwin[2].iwin_size - 1)) & 0xffffffc0);
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR2,
- sc->sc_iwin[2].iwin_xlate);
-
- if (sc->sc_is_host) {
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- PCIR_BARS + 0x10, sc->sc_iwin[2].iwin_base_lo);
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- PCIR_BARS + 0x14, sc->sc_iwin[2].iwin_base_hi);
- } else {
- sc->sc_iwin[2].iwin_base_lo = bus_space_read_4(sc->sc_st,
- sc->sc_atu_sh, PCIR_BARS + 0x10);
- sc->sc_iwin[2].iwin_base_hi = bus_space_read_4(sc->sc_st,
- sc->sc_atu_sh, PCIR_BARS + 0x14);
- sc->sc_iwin[2].iwin_base_lo =
- PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo);
- }
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR3,
- (0xffffffff - (sc->sc_iwin[3].iwin_size - 1)) & 0xffffffc0);
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR3,
- sc->sc_iwin[3].iwin_xlate);
-
- if (sc->sc_is_host) {
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- ATU_IABAR3, sc->sc_iwin[3].iwin_base_lo);
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- ATU_IAUBAR3, sc->sc_iwin[3].iwin_base_hi);
- } else {
- sc->sc_iwin[3].iwin_base_lo = bus_space_read_4(sc->sc_st,
- sc->sc_atu_sh, ATU_IABAR3);
- sc->sc_iwin[3].iwin_base_hi = bus_space_read_4(sc->sc_st,
- sc->sc_atu_sh, ATU_IAUBAR3);
- sc->sc_iwin[3].iwin_base_lo =
- PCI_MAPREG_MEM_ADDR(sc->sc_iwin[3].iwin_base_lo);
- }
- /*
- * Mask (disable) the ATU interrupt sources.
- * XXX May want to revisit this if we encounter
- * XXX an application that wants it.
- */
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- ATU_ATUIMR,
- ATUIMR_IMW1BU|ATUIMR_ISCEM|ATUIMR_RSCEM|ATUIMR_PST|
- ATUIMR_DPE|ATUIMR_P_SERR_ASRT|ATUIMR_PMA|ATUIMR_PTAM|
- ATUIMR_PTAT|ATUIMR_PMPE);
-
- /*
- * Program the outbound windows.
- */
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- ATU_OIOWTVR, sc->sc_ioout_xlate);
-
- if (!sc->sc_is_host) {
- sc->sc_owin[0].owin_xlate_lo = sc->sc_iwin[1].iwin_base_lo;
- sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi;
- }
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- ATU_OMWTVR0, sc->sc_owin[0].owin_xlate_lo);
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- ATU_OUMWTVR0, sc->sc_owin[0].owin_xlate_hi);
-
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- ATU_OMWTVR1, sc->sc_owin[1].owin_xlate_lo);
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- ATU_OUMWTVR1, sc->sc_owin[1].owin_xlate_hi);
-
- /*
- * Set up the ATU configuration register. All we do
- * right now is enable Outbound Windows.
- */
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUCR,
- ATUCR_OUT_EN);
-
- /*
- * Enable bus mastering, memory access, SERR, and parity
- * checking on the ATU.
- */
- if (sc->sc_is_host) {
- preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh,
- PCIR_COMMAND);
- preg |= PCIM_CMD_MEMEN |
- PCIM_CMD_BUSMASTEREN | PCIM_CMD_PERRESPEN |
- PCIM_CMD_SERRESPEN;
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
- PCIR_COMMAND, preg);
- }
- /* Initialize the bus space tags. */
- i80321_io_bs_init(&sc->sc_pci_iot, sc);
- i80321_mem_bs_init(&sc->sc_pci_memt, sc);
- intr_enabled = 0;
- i80321_set_intrmask();
- i80321_set_intrsteer();
-}
-
-
-static __inline uint32_t
-i80321_iintsrc_read(void)
-{
- uint32_t iintsrc;
-
- __asm __volatile("mrc p6, 0, %0, c8, c0, 0"
- : "=r" (iintsrc));
-
- /*
- * The IINTSRC register shows bits that are active even
- * if they are masked in INTCTL, so we have to mask them
- * off with the interrupts we consider enabled.
- */
- return (iintsrc & intr_enabled);
-}
-
-int
-arm_get_next_irq(int last __unused)
-{
- int irq;
-
- if ((irq = i80321_iintsrc_read()))
- return (ffs(irq) - 1);
- return (-1);
-}
diff --git a/sys/arm/xscale/i80321/i80321_aau.c b/sys/arm/xscale/i80321/i80321_aau.c
deleted file mode 100644
index 288411b71974..000000000000
--- a/sys/arm/xscale/i80321/i80321_aau.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*-
- * Copyright (c) 2005 Olivier Houchard. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-#include <sys/rman.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_map.h>
-#include <machine/bus.h>
-#include <machine/cpu.h>
-#include <machine/md_var.h>
-
-#include <arm/xscale/i80321/i80321reg.h>
-#include <arm/xscale/i80321/i80321var.h>
-#include <arm/xscale/i80321/iq80321reg.h>
-#include <arm/xscale/i80321/iq80321var.h>
-#include <arm/xscale/i80321/i80321_intr.h>
-
-typedef struct i80321_aaudesc_s {
- vm_paddr_t next_desc;
- uint32_t sar[4];
- vm_paddr_t local_addr;
- vm_size_t count;
- uint32_t descr_ctrl;
-} __packed i80321_aaudesc_t;
-
-typedef struct i80321_aauring_s {
- i80321_aaudesc_t *desc;
- vm_paddr_t phys_addr;
- bus_dmamap_t map;
-} i80321_aauring_t;
-
-#define AAU_RING_SIZE 64
-
-struct i80321_aau_softc {
- bus_space_tag_t sc_st;
- bus_space_handle_t sc_aau_sh;
- bus_dma_tag_t dmatag;
- i80321_aauring_t aauring[AAU_RING_SIZE];
- int flags;
-#define BUSY 0x1
- int unit;
- struct mtx mtx;
-};
-
-static int
-i80321_aau_probe(device_t dev)
-{
- device_set_desc(dev, "I80321 AAU");
- return (0);
-}
-
-static struct i80321_aau_softc *aau_softc;
-
-static void
-i80321_mapphys(void *arg, bus_dma_segment_t *segs, int nseg, int error)
-{
- vm_paddr_t *addr = (vm_paddr_t *)arg;
-
- *addr = segs->ds_addr;
-}
-
-#define AAU_REG_WRITE(softc, reg, val) \
- bus_space_write_4((softc)->sc_st, (softc)->sc_aau_sh, \
- (reg), (val))
-#define AAU_REG_READ(softc, reg) \
- bus_space_read_4((softc)->sc_st, (softc)->sc_aau_sh, \
- (reg))
-
-static int aau_bzero(void *, int, int);
-
-static int
-i80321_aau_attach(device_t dev)
-{
- struct i80321_aau_softc *softc = device_get_softc(dev);
- struct i80321_softc *sc = device_get_softc(device_get_parent(dev));
- struct i80321_aaudesc_s *aaudescs;
-
- mtx_init(&softc->mtx, "AAU mtx", NULL, MTX_SPIN);
- softc->sc_st = sc->sc_st;
- if (bus_space_subregion(softc->sc_st, sc->sc_sh, VERDE_AAU_BASE,
- VERDE_AAU_SIZE, &softc->sc_aau_sh) != 0)
- panic("%s: unable to subregion AAU registers",
- device_get_name(dev));
- if (bus_dma_tag_create(NULL, sizeof(i80321_aaudesc_t), 0,
- BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
- AAU_RING_SIZE * sizeof(i80321_aaudesc_t),
- 1, sizeof(i80321_aaudesc_t), BUS_DMA_ALLOCNOW, busdma_lock_mutex,
- &Giant, &softc->dmatag))
- panic("Couldn't create a dma tag");
- if (bus_dmamem_alloc(softc->dmatag, (void **)&aaudescs,
- BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &softc->aauring[0].map))
- panic("Couldn't alloc dma memory");
-
- for (int i = 0; i < AAU_RING_SIZE; i++) {
- if (i > 0)
- if (bus_dmamap_create(softc->dmatag, 0,
- &softc->aauring[i].map))
- panic("Couldn't create dma map");
- softc->aauring[i].desc = &aaudescs[i];
- bus_dmamap_load(softc->dmatag, softc->aauring[i].map,
- softc->aauring[i].desc, sizeof(i80321_aaudesc_t),
- i80321_mapphys, &softc->aauring[i].phys_addr, 0);
- bzero(softc->aauring[i].desc, sizeof(i80321_aaudesc_t));
- }
- aau_softc = softc;
- _arm_bzero = aau_bzero;
- _min_bzero_size = 1024;
- return (0);
-}
-
-static __inline void
-test_virt_addr(void *addr, int len)
-{
- int to_nextpage;
-
- while (len > 0) {
- *(char *)addr = 0;
- to_nextpage = ((vm_offset_t)addr & ~PAGE_MASK) +
- PAGE_SIZE - (vm_offset_t)addr;
- if (to_nextpage >= len)
- break;
- len -= to_nextpage;
- addr = (void *)((vm_offset_t)addr + to_nextpage);
- }
-}
-
-static int
-aau_bzero(void *dst, int len, int flags)
-{
- struct i80321_aau_softc *sc = aau_softc;
- i80321_aaudesc_t *desc;
- int ret;
- int csr;
- int descnb = 0;
- int tmplen = len;
- int to_nextpagedst;
- int min_hop;
- vm_paddr_t pa, tmppa;
-
- if (!sc)
- return (-1);
- mtx_lock_spin(&sc->mtx);
- if (sc->flags & BUSY) {
- mtx_unlock_spin(&sc->mtx);
- return (-1);
- }
- sc->flags |= BUSY;
- mtx_unlock_spin(&sc->mtx);
- desc = sc->aauring[0].desc;
- if (flags & IS_PHYSICAL) {
- desc->local_addr = (vm_paddr_t)dst;
- desc->next_desc = 0;
- desc->count = len;
- desc->descr_ctrl = 2 << 1 | 1 << 31; /* Fill, enable dest write */
- bus_dmamap_sync(sc->dmatag, sc->aauring[0].map,
- BUS_DMASYNC_PREWRITE);
- } else {
- test_virt_addr(dst, len);
- if ((vm_offset_t)dst & (31))
- cpu_dcache_wb_range((vm_offset_t)dst & ~31, 32);
- if (((vm_offset_t)dst + len) & 31)
- cpu_dcache_wb_range(((vm_offset_t)dst + len) & ~31,
- 32);
- cpu_dcache_inv_range((vm_offset_t)dst, len);
- while (tmplen > 0) {
- pa = vtophys(dst);
- to_nextpagedst = ((vm_offset_t)dst & ~PAGE_MASK) +
- PAGE_SIZE - (vm_offset_t)dst;
- while (to_nextpagedst < tmplen) {
- tmppa = vtophys((vm_offset_t)dst +
- to_nextpagedst);
- if (tmppa != pa + to_nextpagedst)
- break;
- to_nextpagedst += PAGE_SIZE;
- }
- min_hop = to_nextpagedst;
- if (min_hop < 64) {
- tmplen -= min_hop;
- bzero(dst, min_hop);
- cpu_dcache_wbinv_range((vm_offset_t)dst,
- min_hop);
-
- dst = (void *)((vm_offset_t)dst + min_hop);
- if (tmplen <= 0 && descnb > 0) {
- sc->aauring[descnb - 1].desc->next_desc
- = 0;
- bus_dmamap_sync(sc->dmatag,
- sc->aauring[descnb - 1].map,
- BUS_DMASYNC_PREWRITE);
- }
- continue;
- }
- desc->local_addr = pa;
- desc->count = tmplen > min_hop ? min_hop : tmplen;
- desc->descr_ctrl = 2 << 1 | 1 << 31; /* Fill, enable dest write */;
- if (min_hop < tmplen) {
- tmplen -= min_hop;
- dst = (void *)((vm_offset_t)dst + min_hop);
- } else
- tmplen = 0;
- if (descnb + 1 >= AAU_RING_SIZE) {
- mtx_lock_spin(&sc->mtx);
- sc->flags &= ~BUSY;
- mtx_unlock_spin(&sc->mtx);
- return (-1);
- }
- if (tmplen > 0) {
- desc->next_desc = sc->aauring[descnb + 1].
- phys_addr;
- bus_dmamap_sync(sc->dmatag,
- sc->aauring[descnb].map,
- BUS_DMASYNC_PREWRITE);
- desc = sc->aauring[descnb + 1].desc;
- descnb++;
- } else {
- desc->next_desc = 0;
- bus_dmamap_sync(sc->dmatag,
- sc->aauring[descnb].map,
- BUS_DMASYNC_PREWRITE);
- }
-
- }
-
- }
- AAU_REG_WRITE(sc, 0x0c /* Descriptor addr */,
- sc->aauring[0].phys_addr);
- AAU_REG_WRITE(sc, 0 /* Control register */, 1 << 0/* Start transfer */);
- while ((csr = AAU_REG_READ(sc, 0x4)) & (1 << 10));
- /* Wait until it's done. */
- if (csr & (1 << 5)) /* error */
- ret = -1;
- else
- ret = 0;
- /* Clear the interrupt. */
- AAU_REG_WRITE(sc, 0x4, csr);
- /* Stop the AAU. */
- AAU_REG_WRITE(sc, 0, 0);
- mtx_lock_spin(&sc->mtx);
- sc->flags &= ~BUSY;
- mtx_unlock_spin(&sc->mtx);
- return (ret);
-}
-
-static device_method_t i80321_aau_methods[] = {
- DEVMETHOD(device_probe, i80321_aau_probe),
- DEVMETHOD(device_attach, i80321_aau_attach),
- {0, 0},
-};
-
-static driver_t i80321_aau_driver = {
- "i80321_aau",
- i80321_aau_methods,
- sizeof(struct i80321_aau_softc),
-};
-
-static devclass_t i80321_aau_devclass;
-
-DRIVER_MODULE(i80321_aau, iq, i80321_aau_driver, i80321_aau_devclass, 0, 0);
diff --git a/sys/arm/xscale/i80321/i80321_dma.c b/sys/arm/xscale/i80321/i80321_dma.c
deleted file mode 100644
index abf7dcc970e8..000000000000
--- a/sys/arm/xscale/i80321/i80321_dma.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/*-
- * Copyright (c) 2005 Olivier Houchard. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-#include <sys/rman.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_map.h>
-#include <machine/bus.h>
-#include <machine/cpu.h>
-#include <machine/md_var.h>
-
-#include <arm/xscale/i80321/i80321reg.h>
-#include <arm/xscale/i80321/i80321var.h>
-#include <arm/xscale/i80321/iq80321reg.h>
-#include <arm/xscale/i80321/iq80321var.h>
-#include <arm/xscale/i80321/i80321_intr.h>
-
-typedef struct i80321_dmadesc_s {
- vm_paddr_t next_desc;
- vm_paddr_t low_pciaddr;
- vm_paddr_t high_pciaddr;
- vm_paddr_t local_addr;
- vm_size_t count;
- uint32_t descr_ctrl;
- uint64_t unused;
-} __packed i80321_dmadesc_t;
-
-typedef struct i80321_dmaring_s {
- i80321_dmadesc_t *desc;
- vm_paddr_t phys_addr;
- bus_dmamap_t map;
-} i80321_dmaring_t;
-
-#define DMA_RING_SIZE 64
-
-struct i80321_dma_softc {
- bus_space_tag_t sc_st;
- bus_space_handle_t sc_dma_sh;
- bus_dma_tag_t dmatag;
- i80321_dmaring_t dmaring[DMA_RING_SIZE];
- int flags;
-#define BUSY 0x1
- int unit;
- struct mtx mtx;
-};
-
-static int
-i80321_dma_probe(device_t dev)
-{
- device_set_desc(dev, "I80321 DMA Unit");
- return (0);
-}
-
-static struct i80321_dma_softc *softcs[2]; /* XXX */
-
-static void
-i80321_mapphys(void *arg, bus_dma_segment_t *segs, int nseg, int error)
-{
- vm_paddr_t *addr = (vm_paddr_t *)arg;
-
- *addr = segs->ds_addr;
-}
-
-#define DMA_REG_WRITE(softc, reg, val) \
- bus_space_write_4((softc)->sc_st, (softc)->sc_dma_sh, \
- (reg), (val))
-#define DMA_REG_READ(softc, reg) \
- bus_space_read_4((softc)->sc_st, (softc)->sc_dma_sh, \
- (reg))
-
-#define DMA_CLEAN_MASK (0x2|0x4|0x8|0x20|0x100|0x200)
-static int dma_memcpy(void *, void *, int, int);
-
-static int
-i80321_dma_attach(device_t dev)
-{
- struct i80321_dma_softc *softc = device_get_softc(dev);
- struct i80321_softc *sc = device_get_softc(device_get_parent(dev));
- int unit = device_get_unit(dev);
- i80321_dmadesc_t *dmadescs;
-
- mtx_init(&softc->mtx, "DMA engine mtx", NULL, MTX_SPIN);
- softc->sc_st = sc->sc_st;
- if (bus_space_subregion(softc->sc_st, sc->sc_sh, unit == 0 ?
- VERDE_DMA_BASE0 : VERDE_DMA_BASE1, VERDE_DMA_SIZE,
- &softc->sc_dma_sh) != 0)
- panic("%s: unable to subregion DMA registers",
- device_get_name(dev));
- if (bus_dma_tag_create(NULL, sizeof(i80321_dmadesc_t),
- 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
- DMA_RING_SIZE * sizeof(i80321_dmadesc_t), 1,
- sizeof(i80321_dmadesc_t), BUS_DMA_ALLOCNOW, busdma_lock_mutex,
- &Giant, &softc->dmatag))
- panic("Couldn't create a dma tag");
- DMA_REG_WRITE(softc, 0, 0);
- if (bus_dmamem_alloc(softc->dmatag, (void **)&dmadescs,
- BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &softc->dmaring[0].map))
- panic("Couldn't alloc dma memory");
- for (int i = 0; i < DMA_RING_SIZE; i++) {
- if (i > 0)
- if (bus_dmamap_create(softc->dmatag, 0,
- &softc->dmaring[i].map))
- panic("Couldn't alloc dmamap");
- softc->dmaring[i].desc = &dmadescs[i];
- bus_dmamap_load(softc->dmatag, softc->dmaring[i].map,
- softc->dmaring[i].desc, sizeof(i80321_dmadesc_t),
- i80321_mapphys, &softc->dmaring[i].phys_addr, 0);
- }
- softc->unit = unit;
- softcs[unit] = softc;
- _arm_memcpy = dma_memcpy;
- _min_memcpy_size = 1024;
- return (0);
-}
-
-static __inline int
-virt_addr_is_valid(void *addr, int len, int write, int is_kernel)
-{
- int to_nextpage;
- char tmp = 0;
-
- while (len > 0) {
- if (write) {
- if (is_kernel)
- *(char *)addr = 0;
- else if (subyte(addr, 0) != 0) {
- return (0);
- }
- } else {
- if (is_kernel)
- badaddr_read(addr, 1, &tmp);
- else if (fubyte(addr) == -1) {
- return (0);
- }
- }
- to_nextpage = ((vm_offset_t)addr & ~PAGE_MASK) +
- PAGE_SIZE - (vm_offset_t)addr;
- if (to_nextpage >= len)
- break;
- len -= to_nextpage;
- addr = (void *)((vm_offset_t)addr + to_nextpage);
- }
- return (1);
-}
-
-static int
-dma_memcpy(void *dst, void *src, int len, int flags)
-{
- struct i80321_dma_softc *sc;
- i80321_dmadesc_t *desc;
- int ret;
- int csr;
- int descnb = 0;
- int tmplen = len;
- int to_nextpagesrc, to_nextpagedst;
- int min_hop;
- vm_paddr_t pa, pa2, tmppa;
- pmap_t pmap = vmspace_pmap(curthread->td_proc->p_vmspace);
-
- if (!softcs[0] || !softcs[1])
- return (-1);
- mtx_lock_spin(&softcs[0]->mtx);
- if (softcs[0]->flags & BUSY) {
- mtx_unlock_spin(&softcs[0]->mtx);
- mtx_lock_spin(&softcs[1]->mtx);
- if (softcs[1]->flags & BUSY) {
- mtx_unlock(&softcs[1]->mtx);
- return (-1);
- }
- sc = softcs[1];
- } else
- sc = softcs[0];
- sc->flags |= BUSY;
- mtx_unlock_spin(&sc->mtx);
- desc = sc->dmaring[0].desc;
- if (flags & IS_PHYSICAL) {
- desc->next_desc = 0;
- desc->low_pciaddr = (vm_paddr_t)src;
- desc->high_pciaddr = 0;
- desc->local_addr = (vm_paddr_t)dst;
- desc->count = len;
- desc->descr_ctrl = 1 << 6; /* Local memory to local memory. */
- bus_dmamap_sync(sc->dmatag,
- sc->dmaring[0].map,
- BUS_DMASYNC_PREWRITE);
- } else {
- if (!virt_addr_is_valid(dst, len, 1, !(flags & DST_IS_USER)) ||
- !virt_addr_is_valid(src, len, 0, !(flags & SRC_IS_USER))) {
- mtx_lock_spin(&sc->mtx);
- sc->flags &= ~BUSY;
- mtx_unlock_spin(&sc->mtx);
- return (-1);
- }
- cpu_dcache_wb_range((vm_offset_t)src, len);
- if ((vm_offset_t)dst & (31))
- cpu_dcache_wb_range((vm_offset_t)dst & ~31, 32);
- if (((vm_offset_t)dst + len) & 31)
- cpu_dcache_wb_range(((vm_offset_t)dst + len) & ~31,
- 32);
- cpu_dcache_inv_range((vm_offset_t)dst, len);
- while (tmplen > 0) {
- pa = (flags & SRC_IS_USER) ?
- pmap_extract(pmap, (vm_offset_t)src) :
- vtophys(src);
- pa2 = (flags & DST_IS_USER) ?
- pmap_extract(pmap, (vm_offset_t)dst) :
- vtophys(dst);
- to_nextpagesrc = ((vm_offset_t)src & ~PAGE_MASK) +
- PAGE_SIZE - (vm_offset_t)src;
- to_nextpagedst = ((vm_offset_t)dst & ~PAGE_MASK) +
- PAGE_SIZE - (vm_offset_t)dst;
- while (to_nextpagesrc < tmplen) {
- tmppa = (flags & SRC_IS_USER) ?
- pmap_extract(pmap, (vm_offset_t)src +
- to_nextpagesrc) :
- vtophys((vm_offset_t)src +
- to_nextpagesrc);
- if (tmppa != pa + to_nextpagesrc)
- break;
- to_nextpagesrc += PAGE_SIZE;
- }
- while (to_nextpagedst < tmplen) {
- tmppa = (flags & DST_IS_USER) ?
- pmap_extract(pmap, (vm_offset_t)dst +
- to_nextpagedst) :
- vtophys((vm_offset_t)dst +
- to_nextpagedst);
- if (tmppa != pa2 + to_nextpagedst)
- break;
- to_nextpagedst += PAGE_SIZE;
- }
- min_hop = to_nextpagedst > to_nextpagesrc ?
- to_nextpagesrc : to_nextpagedst;
- if (min_hop < 64) {
- tmplen -= min_hop;
- memcpy(dst, src, min_hop);
- cpu_dcache_wbinv_range((vm_offset_t)dst,
- min_hop);
-
- src = (void *)((vm_offset_t)src + min_hop);
- dst = (void *)((vm_offset_t)dst + min_hop);
- if (tmplen <= 0 && descnb > 0) {
- sc->dmaring[descnb - 1].desc->next_desc
- = 0;
- bus_dmamap_sync(sc->dmatag,
- sc->dmaring[descnb - 1].map,
- BUS_DMASYNC_PREWRITE);
- }
- continue;
- }
- desc->low_pciaddr = pa;
- desc->high_pciaddr = 0;
- desc->local_addr = pa2;
- desc->count = tmplen > min_hop ? min_hop : tmplen;
- desc->descr_ctrl = 1 << 6;
- if (min_hop < tmplen) {
- tmplen -= min_hop;
- src = (void *)((vm_offset_t)src + min_hop);
- dst = (void *)((vm_offset_t)dst + min_hop);
- } else
- tmplen = 0;
- if (descnb + 1 >= DMA_RING_SIZE) {
- mtx_lock_spin(&sc->mtx);
- sc->flags &= ~BUSY;
- mtx_unlock_spin(&sc->mtx);
- return (-1);
- }
- if (tmplen > 0) {
- desc->next_desc = sc->dmaring[descnb + 1].
- phys_addr;
- bus_dmamap_sync(sc->dmatag,
- sc->dmaring[descnb].map,
- BUS_DMASYNC_PREWRITE);
- desc = sc->dmaring[descnb + 1].desc;
- descnb++;
- } else {
- desc->next_desc = 0;
- bus_dmamap_sync(sc->dmatag,
- sc->dmaring[descnb].map,
- BUS_DMASYNC_PREWRITE);
- }
-
- }
-
- }
- DMA_REG_WRITE(sc, 4 /* Status register */,
- DMA_REG_READ(sc, 4) | DMA_CLEAN_MASK);
- DMA_REG_WRITE(sc, 0x10 /* Descriptor addr */,
- sc->dmaring[0].phys_addr);
- DMA_REG_WRITE(sc, 0 /* Control register */, 1 | 2/* Start transfer */);
- while ((csr = DMA_REG_READ(sc, 0x4)) & (1 << 10));
- /* Wait until it's done. */
- if (csr & 0x2e) /* error */
- ret = -1;
- else
- ret = 0;
- DMA_REG_WRITE(sc, 0, 0);
- mtx_lock_spin(&sc->mtx);
- sc->flags &= ~BUSY;
- mtx_unlock_spin(&sc->mtx);
- return (ret);
-}
-
-static device_method_t i80321_dma_methods[] = {
- DEVMETHOD(device_probe, i80321_dma_probe),
- DEVMETHOD(device_attach, i80321_dma_attach),
- {0, 0},
-};
-
-static driver_t i80321_dma_driver = {
- "i80321_dma",
- i80321_dma_methods,
- sizeof(struct i80321_dma_softc),
-};
-
-static devclass_t i80321_dma_devclass;
-
-DRIVER_MODULE(i80321_dma, iq, i80321_dma_driver, i80321_dma_devclass, 0, 0);
diff --git a/sys/arm/xscale/i80321/i80321_intr.h b/sys/arm/xscale/i80321/i80321_intr.h
deleted file mode 100644
index 29003a05ce56..000000000000
--- a/sys/arm/xscale/i80321/i80321_intr.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/* $NetBSD: i80321_intr.h,v 1.5 2004/01/12 10:25:06 scw Exp $ */
-
-/*-
- * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
- * All rights reserved.
- *
- * Written by Jason R. Thorpe for Wasabi Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- *
- */
-
-#ifndef _I80321_INTR_H_
-#define _I80321_INTR_H_
-
-#define ARM_IRQ_HANDLER _C_LABEL(i80321_intr_dispatch)
-
-#ifndef _LOCORE
-
-#include <machine/armreg.h>
-#include <machine/cpufunc.h>
-
-#include <arm/xscale/i80321/i80321reg.h>
-
-void i80321_do_pending(void);
-
-extern __volatile uint32_t intr_enabled;
-extern uint32_t intr_steer;
-
-static __inline void __attribute__((__unused__))
-i80321_set_intrmask(void)
-{
-
- __asm __volatile("mcr p6, 0, %0, c0, c0, 0"
- :
- : "r" (intr_enabled & ICU_INT_HWMASK));
-}
-
-static __inline void
-i80321_set_intrsteer(void)
-{
-
- __asm __volatile("mcr p6, 0, %0, c4, c0, 0"
- :
- : "r" (intr_steer & ICU_INT_HWMASK));
-}
-
-#if defined ( CPU_XSCALE_80219 )
-#define INT_SWMASK \
- ((1U << ICU_INT_bit26) | \
- (1U << ICU_INT_bit25) | \
- (1U << ICU_INT_bit23) | \
- (1U << ICU_INT_bit22) | \
- (1U << ICU_INT_bit7) | \
- (1U << ICU_INT_bit6) | \
- (1U << ICU_INT_bit5) | \
- (1U << ICU_INT_bit4))
-#else
-#define INT_SWMASK \
- ((1U << ICU_INT_bit26) | (1U << ICU_INT_bit22) | \
- (1U << ICU_INT_bit5) | (1U << ICU_INT_bit4))
-#endif
-
-#if 0
-static __inline void __attribute__((__unused__))
-i80321_splx(int new)
-{
- extern __volatile uint32_t intr_enabled;
- extern __volatile int current_spl_level;
- extern __volatile int i80321_ipending;
- extern void i80321_do_pending(void);
- int oldirqstate, hwpend;
-
- /* Don't let the compiler re-order this code with preceding code */
- __insn_barrier();
-
- current_spl_level = new;
-
- hwpend = (i80321_ipending & ICU_INT_HWMASK) & ~new;
- if (hwpend != 0) {
- oldirqstate = disable_interrupts(PSR_I);
- intr_enabled |= hwpend;
- i80321_set_intrmask();
- restore_interrupts(oldirqstate);
- }
-
- if ((i80321_ipending & INT_SWMASK) & ~new)
- i80321_do_pending();
-}
-
-static __inline int __attribute__((__unused__))
-i80321_splraise(int ipl)
-{
- extern __volatile int current_spl_level;
- extern int i80321_imask[];
- int old;
-
- old = current_spl_level;
- current_spl_level |= i80321_imask[ipl];
-
- /* Don't let the compiler re-order this code with subsequent code */
- __insn_barrier();
-
- return (old);
-}
-
-static __inline int __attribute__((__unused__))
-i80321_spllower(int ipl)
-{
- extern __volatile int current_spl_level;
- extern int i80321_imask[];
- int old = current_spl_level;
-
- i80321_splx(i80321_imask[ipl]);
- return(old);
-}
-
-#endif
-#if !defined(EVBARM_SPL_NOINLINE)
-
-#define splx(new) i80321_splx(new)
-#define _spllower(ipl) i80321_spllower(ipl)
-#define _splraise(ipl) i80321_splraise(ipl)
-void _setsoftintr(int);
-
-#else
-
-int _splraise(int);
-int _spllower(int);
-void splx(int);
-void _setsoftintr(int);
-
-#endif /* ! EVBARM_SPL_NOINLINE */
-
-#endif /* _LOCORE */
-
-#endif /* _I80321_INTR_H_ */
diff --git a/sys/arm/xscale/i80321/i80321_mcu.c b/sys/arm/xscale/i80321/i80321_mcu.c
deleted file mode 100644
index a51a43348618..000000000000
--- a/sys/arm/xscale/i80321/i80321_mcu.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/* $NetBSD: i80321_mcu.c,v 1.2 2003/07/15 00:24:54 lukem Exp $ */
-
-/*-
- * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
- * All rights reserved.
- *
- * Written by Jason R. Thorpe for Wasabi Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
- * 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.
- */
-
-/*
- * Intel i80321 I/O Processor memory controller support.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-
-#include <machine/bus.h>
-
-#include <arm/xscale/i80321/i80321reg.h>
-#include <arm/xscale/i80321/i80321var.h>
-
-/*
- * i80321_sdram_bounds:
- *
- * Retrieve the start and size of SDRAM.
- */
-void
-i80321_sdram_bounds(bus_space_tag_t st, bus_space_handle_t sh,
- vm_paddr_t *start, vm_size_t *size)
-{
- uint32_t sdbr, sbr0, sbr1;
- uint32_t bank0, bank1;
-
- sdbr = bus_space_read_4(st, sh, MCU_SDBR);
- sbr0 = bus_space_read_4(st, sh, MCU_SBR0);
- sbr1 = bus_space_read_4(st, sh, MCU_SBR1);
-
-#ifdef VERBOSE_INIT_ARM
- printf("i80321: SBDR = 0x%08x SBR0 = 0x%08x SBR1 = 0x%08x\n",
- sdbr, sbr0, sbr1);
-#endif
-
- *start = sdbr;
-
- sdbr = (sdbr >> 25) & 0x1f;
-
- sbr0 &= 0x3f;
- sbr1 &= 0x3f;
-
- bank0 = (sbr0 - sdbr) << 25;
- bank1 = (sbr1 - sbr0) << 25;
-
-#ifdef VERBOSE_INIT_ARM
- printf("i80321: BANK0 = 0x%08x BANK1 = 0x%08x\n", bank0, bank1);
-#endif
-
- *size = bank0 + bank1;
-}
diff --git a/sys/arm/xscale/i80321/i80321_pci.c b/sys/arm/xscale/i80321/i80321_pci.c
deleted file mode 100644
index 5f78577e8704..000000000000
--- a/sys/arm/xscale/i80321/i80321_pci.c
+++ /dev/null
@@ -1,401 +0,0 @@
-/* $NetBSD: i80321_pci.c,v 1.4 2003/07/15 00:24:54 lukem Exp $ */
-
-/*-
- * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
- * All rights reserved.
- *
- * Written by Jason R. Thorpe for Wasabi Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
- * 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.
- */
-
-/*
- * PCI configuration support for i80321 I/O Processor chip.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/rman.h>
-
-#include <machine/bus.h>
-#include <machine/cpu.h>
-#include <machine/pcb.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_extern.h>
-
-#include <arm/xscale/i80321/i80321reg.h>
-#include <arm/xscale/i80321/i80321var.h>
-#include <arm/xscale/i80321/i80321_intr.h>
-
-#include <dev/pci/pcib_private.h>
-#include "pcib_if.h"
-
-#include <dev/pci/pcireg.h>
-extern struct i80321_softc *i80321_softc;
-
-static int
-i80321_pci_probe(device_t dev)
-{
- device_set_desc(dev, "i80321 PCI bus");
- return (0);
-}
-
-static int
-i80321_pci_attach(device_t dev)
-{
-
- uint32_t busno;
- struct i80321_pci_softc *sc = device_get_softc(dev);
-
- sc->sc_st = i80321_softc->sc_st;
- sc->sc_atu_sh = i80321_softc->sc_atu_sh;
- busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
- busno = PCIXSR_BUSNO(busno);
- if (busno == 0xff)
- busno = 0;
- sc->sc_dev = dev;
- sc->sc_busno = busno;
- sc->sc_pciio = &i80321_softc->sc_pci_iot;
- sc->sc_pcimem = &i80321_softc->sc_pci_memt;
- sc->sc_mem = i80321_softc->sc_owin[0].owin_xlate_lo +
- VERDE_OUT_XLATE_MEM_WIN_SIZE;
-
- sc->sc_io = i80321_softc->sc_iow_vaddr;
- /* Initialize memory and i/o rmans. */
- sc->sc_io_rman.rm_type = RMAN_ARRAY;
- sc->sc_io_rman.rm_descr = "I80321 PCI I/O Ports";
- if (rman_init(&sc->sc_io_rman) != 0 ||
- rman_manage_region(&sc->sc_io_rman,
- sc->sc_io,
- sc->sc_io +
- VERDE_OUT_XLATE_IO_WIN_SIZE) != 0) {
- panic("i80321_pci_probe: failed to set up I/O rman");
- }
- sc->sc_mem_rman.rm_type = RMAN_ARRAY;
- sc->sc_mem_rman.rm_descr = "I80321 PCI Memory";
- if (rman_init(&sc->sc_mem_rman) != 0 ||
- rman_manage_region(&sc->sc_mem_rman,
- 0, VERDE_OUT_XLATE_MEM_WIN_SIZE) != 0) {
- panic("i80321_pci_probe: failed to set up memory rman");
- }
- sc->sc_irq_rman.rm_type = RMAN_ARRAY;
- sc->sc_irq_rman.rm_descr = "i80321 PCI IRQs";
- if (rman_init(&sc->sc_irq_rman) != 0 ||
- rman_manage_region(&sc->sc_irq_rman, 26, 32) != 0)
- panic("i80321_pci_probe: failed to set up IRQ rman");
- device_add_child(dev, "pci", -1);
- return (bus_generic_attach(dev));
-}
-
-static int
-i80321_pci_maxslots(device_t dev)
-{
- return (PCI_SLOTMAX);
-}
-
-
-
-static int
-i80321_pci_conf_setup(struct i80321_pci_softc *sc, int bus, int slot, int func,
- int reg, uint32_t *addr)
-{
- uint32_t busno;
-
- busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
- busno = PCIXSR_BUSNO(busno);
- if (busno == 0xff)
- busno = 0;
-
- /*
- * If the bus # is the same as our own, then use Type 0 cycles,
- * else use Type 1.
- *
- * XXX We should filter out all non-private devices here!
- * XXX How does private space interact with PCI-PCI bridges?
- */
- if (bus == busno) {
- if (slot > (31 - 16))
- return (1);
- /*
- * NOTE: PCI-X requires that that devices updated their
- * PCIXSR on every config write with the device number
- * specified in AD[15:11]. If we don't set this field,
- * each device could end of thinking it is at device 0,
- * which can cause a number of problems. Doing this
- * unconditionally should be OK when only PCI devices
- * are present.
- */
- bus &= 0xff;
- slot &= 0x1f;
- func &= 0x07;
-
- *addr = (1U << (slot + 16)) |
- (slot << 11) | (func << 8) | reg;
- } else {
- *addr = (bus << 16) | (slot << 11) | (func << 8) | reg | 1;
- }
-
- return (0);
-}
-
-static u_int32_t
-i80321_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func,
- u_int reg, int bytes)
-{
- struct i80321_pci_softc *sc = device_get_softc(dev);
- uint32_t isr;
- uint32_t addr;
- u_int32_t ret = 0;
- vm_offset_t va;
- int err = 0;
- if (i80321_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr))
- return (-1);
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCAR,
- addr);
-
- va = sc->sc_atu_sh;
- switch (bytes) {
- case 1:
- err = badaddr_read((void*)(va + ATU_OCCDR + (reg & 3)), 1, &ret);
- break;
- case 2:
- err = badaddr_read((void*)(va + ATU_OCCDR + (reg & 3)), 2, &ret);
- break;
- case 4:
- err = badaddr_read((void *)(va + ATU_OCCDR), 4, &ret);
- break;
- default:
- printf("i80321_read_config: invalid size %d\n", bytes);
- ret = -1;
- }
- if (err) {
-
- isr = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUISR);
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUISR,
- isr & (ATUISR_P_SERR_DET|ATUISR_PMA|ATUISR_PTAM|
- ATUISR_PTAT|ATUISR_PMPE));
- return (-1);
- }
- return (ret);
-}
-
-static void
-i80321_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
- u_int reg, u_int32_t data, int bytes)
-{
- struct i80321_pci_softc *sc = device_get_softc(dev);
- uint32_t addr;
-
- if (i80321_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr))
- return;
-
-
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCAR,
- addr);
- switch (bytes) {
- case 1:
- bus_space_write_1(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR +
- (reg & 3), data);
- break;
- case 2:
- bus_space_write_2(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR +
- (reg & 3), data);
- break;
- case 4:
- bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR, data);
- break;
- default:
- printf("i80321_pci_write_config: Invalid size : %d\n", bytes);
- }
-
-}
-
-static int
-i80321_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
-{
- struct i80321_pci_softc *sc = device_get_softc(dev);
- switch (which) {
- case PCIB_IVAR_DOMAIN:
- *result = 0;
- return (0);
- case PCIB_IVAR_BUS:
- *result = sc->sc_busno;
- return (0);
-
- }
- return (ENOENT);
-}
-
-static int
-i80321_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
-{
- struct i80321_pci_softc * sc = device_get_softc(dev);
-
- switch (which) {
- case PCIB_IVAR_DOMAIN:
- return (EINVAL);
- case PCIB_IVAR_BUS:
- sc->sc_busno = result;
- return (0);
- }
- return (ENOENT);
-}
-
-static struct resource *
-i80321_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
- u_long start, u_long end, u_long count, u_int flags)
-{
- struct i80321_pci_softc *sc = device_get_softc(bus);
- struct resource *rv;
- struct rman *rm;
- bus_space_tag_t bt = NULL;
- bus_space_handle_t bh = 0;
-
- switch (type) {
- case SYS_RES_IRQ:
- rm = &sc->sc_irq_rman;
- break;
- case SYS_RES_MEMORY:
- rm = &sc->sc_mem_rman;
- bt = sc->sc_pcimem;
- bh = (start >= 0x80000000 && start < 0x84000000) ? 0x80000000 :
- sc->sc_mem;
- start &= (0x1000000 - 1);
- end &= (0x1000000 - 1);
- break;
- case SYS_RES_IOPORT:
- rm = &sc->sc_io_rman;
- bt = sc->sc_pciio;
- bh = sc->sc_io;
- if (start < sc->sc_io) {
- start = start - 0x90000000 + sc->sc_io;
- end = end - 0x90000000 + sc->sc_io;
- }
- break;
- default:
- return (NULL);
- }
-
- rv = rman_reserve_resource(rm, start, end, count, flags, child);
- if (rv == NULL)
- return (NULL);
- rman_set_rid(rv, *rid);
- if (type != SYS_RES_IRQ) {
- if (type == SYS_RES_MEMORY)
- bh += (rman_get_start(rv));
- rman_set_bustag(rv, bt);
- rman_set_bushandle(rv, bh);
- if (flags & RF_ACTIVE) {
- if (bus_activate_resource(child, type, *rid, rv)) {
- rman_release_resource(rv);
- return (NULL);
- }
- }
- }
- return (rv);
-}
-
-static int
-i80321_pci_activate_resource(device_t bus, device_t child, int type, int rid,
- struct resource *r)
-{
- u_long p;
- int error;
-
- if (type == SYS_RES_MEMORY) {
- error = bus_space_map(rman_get_bustag(r),
- rman_get_bushandle(r), rman_get_size(r), 0, &p);
- if (error)
- return (error);
- rman_set_bushandle(r, p);
-
- }
- return (rman_activate_resource(r));
-}
-
-static int
-i80321_pci_setup_intr(device_t dev, device_t child,
- struct resource *ires, int flags, driver_filter_t *filt,
- driver_intr_t *intr, void *arg, void **cookiep)
-{
- return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
- filt, intr, arg, cookiep));
-}
-
-static int
-i80321_pci_teardown_intr(device_t dev, device_t child, struct resource *res,
- void *cookie)
-{
- return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
-}
-
-static device_method_t i80321_pci_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, i80321_pci_probe),
- DEVMETHOD(device_attach, i80321_pci_attach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
-
- /* Bus interface */
- DEVMETHOD(bus_read_ivar, i80321_read_ivar),
- DEVMETHOD(bus_write_ivar, i80321_write_ivar),
- DEVMETHOD(bus_alloc_resource, i80321_pci_alloc_resource),
- DEVMETHOD(bus_release_resource, bus_generic_release_resource),
- DEVMETHOD(bus_activate_resource, i80321_pci_activate_resource),
- DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_setup_intr, i80321_pci_setup_intr),
- DEVMETHOD(bus_teardown_intr, i80321_pci_teardown_intr),
-
- /* pcib interface */
- DEVMETHOD(pcib_maxslots, i80321_pci_maxslots),
- DEVMETHOD(pcib_read_config, i80321_pci_read_config),
- DEVMETHOD(pcib_write_config, i80321_pci_write_config),
- DEVMETHOD(pcib_route_interrupt, machdep_pci_route_interrupt),
-
- DEVMETHOD_END
-};
-
-static driver_t i80321_pci_driver = {
- "pcib",
- i80321_pci_methods,
- sizeof(struct i80321_pci_softc),
-};
-
-static devclass_t i80321_pci_devclass;
-
-DRIVER_MODULE(ipci, iq, i80321_pci_driver, i80321_pci_devclass, 0, 0);
diff --git a/sys/arm/xscale/i80321/i80321_space.c b/sys/arm/xscale/i80321/i80321_space.c
deleted file mode 100644
index 64c222522cd2..000000000000
--- a/sys/arm/xscale/i80321/i80321_space.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/* $NetBSD: i80321_space.c,v 1.6 2003/10/06 15:43:35 thorpej Exp $ */
-
-/*-
- * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
- * All rights reserved.
- *
- * Written by Jason R. Thorpe for Wasabi Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
- * 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.
- */
-
-/*
- * bus_space functions for i80321 I/O Processor.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-
-#include <machine/pcb.h>
-
-#include <vm/vm.h>
-#include <vm/vm_kern.h>
-#include <vm/pmap.h>
-#include <vm/vm_page.h>
-#include <vm/vm_extern.h>
-
-#include <machine/bus.h>
-
-#include <arm/xscale/i80321/i80321reg.h>
-#include <arm/xscale/i80321/i80321var.h>
-
-/* Prototypes for all the bus_space structure functions */
-bs_protos(i80321);
-bs_protos(i80321_io);
-bs_protos(i80321_mem);
-
-void
-i80321_bs_init(bus_space_tag_t bs, void *cookie)
-{
-
- *bs = *arm_base_bs_tag;
- bs->bs_privdata = cookie;
-}
-
-void
-i80321_io_bs_init(bus_space_tag_t bs, void *cookie)
-{
-
- *bs = *arm_base_bs_tag;
- bs->bs_privdata = cookie;
-
- bs->bs_map = i80321_io_bs_map;
- bs->bs_unmap = i80321_io_bs_unmap;
- bs->bs_alloc = i80321_io_bs_alloc;
- bs->bs_free = i80321_io_bs_free;
-
-}
-
-void
-i80321_mem_bs_init(bus_space_tag_t bs, void *cookie)
-{
-
- *bs = *arm_base_bs_tag;
- bs->bs_privdata = cookie;
-
- bs->bs_map = i80321_mem_bs_map;
- bs->bs_unmap = i80321_mem_bs_unmap;
- bs->bs_alloc = i80321_mem_bs_alloc;
- bs->bs_free = i80321_mem_bs_free;
-
-}
-
-/* *** Routines shared by i80321, PCI IO, and PCI MEM. *** */
-
-int
-i80321_bs_subregion(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset,
- bus_size_t size, bus_space_handle_t *nbshp)
-{
-
- *nbshp = bsh + offset;
- return (0);
-}
-
-void
-i80321_bs_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset,
- bus_size_t len, int flags)
-{
-
- /* Nothing to do. */
-}
-
-/* *** Routines for PCI IO. *** */
-
-extern struct i80321_softc *i80321_softc;
-int
-i80321_io_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags,
- bus_space_handle_t *bshp)
-{
- struct i80321_softc *sc = i80321_softc;
- vm_offset_t winvaddr;
- uint32_t busbase;
-
- if (bpa >= sc->sc_ioout_xlate &&
- bpa < (sc->sc_ioout_xlate + VERDE_OUT_XLATE_IO_WIN_SIZE)) {
- busbase = sc->sc_ioout_xlate;
- winvaddr = sc->sc_iow_vaddr;
- } else
- return (EINVAL);
-
- if ((bpa + size) >= (busbase + VERDE_OUT_XLATE_IO_WIN_SIZE))
- return (EINVAL);
-
- /*
- * Found the window -- PCI I/O space is mapped at a fixed
- * virtual address by board-specific code. Translate the
- * bus address to the virtual address.
- */
- *bshp = winvaddr + (bpa - busbase);
-
- return (0);
-}
-
-void
-i80321_io_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size)
-{
-
- /* Nothing to do. */
-}
-
-int
-i80321_io_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend,
- bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
- bus_addr_t *bpap, bus_space_handle_t *bshp)
-{
-
- panic("i80321_io_bs_alloc(): not implemented");
-}
-
-void
-i80321_io_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size)
-{
-
- panic("i80321_io_bs_free(): not implemented");
-}
-
-
-/* *** Routines for PCI MEM. *** */
-extern int badaddr_read(void *, int, void *);
-int
-i80321_mem_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags,
- bus_space_handle_t *bshp)
-{
-
- *bshp = (vm_offset_t)pmap_mapdev(bpa, size);
- return (0);
-}
-
-void
-i80321_mem_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size)
-{
-
- pmap_unmapdev((vm_offset_t)h, size);
-}
-
-int
-i80321_mem_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend,
- bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
- bus_addr_t *bpap, bus_space_handle_t *bshp)
-{
-
- panic("i80321_mem_bs_alloc(): not implemented");
-}
-
-void
-i80321_mem_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size)
-{
-
- panic("i80321_mem_bs_free(): not implemented");
-}
diff --git a/sys/arm/xscale/i80321/iq31244_7seg.c b/sys/arm/xscale/i80321/iq31244_7seg.c
deleted file mode 100644
index 3737094b2172..000000000000
--- a/sys/arm/xscale/i80321/iq31244_7seg.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/* $NetBSD: iq31244_7seg.c,v 1.2 2003/07/15 00:25:01 lukem Exp $ */
-
-/*-
- * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
- * All rights reserved.
- *
- * Written by Jason R. Thorpe for Wasabi Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Support for the 7-segment display on the Intel IQ31244.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/sysctl.h>
-
-#include <machine/bus.h>
-
-#include <arm/xscale/i80321/iq80321reg.h>
-#include <arm/xscale/i80321/iq80321var.h>
-
-#define WRITE(x, v) *((__volatile uint8_t *) (x)) = (v)
-
-static int snakestate;
-
-/*
- * The 7-segment display looks like so:
- *
- * A
- * +-----+
- * | |
- * F | | B
- * | G |
- * +-----+
- * | |
- * E | | C
- * | D |
- * +-----+ o DP
- *
- * Setting a bit clears the corresponding segment on the
- * display.
- */
-#define SEG_A (1 << 0)
-#define SEG_B (1 << 1)
-#define SEG_C (1 << 2)
-#define SEG_D (1 << 3)
-#define SEG_E (1 << 4)
-#define SEG_F (1 << 5)
-#define SEG_G (1 << 6)
-#define SEG_DP (1 << 7)
-
-static const uint8_t digitmap[] = {
-/* +#####+
- * # #
- * # #
- * # #
- * +-----+
- * # #
- * # #
- * # #
- * +#####+
- */
- SEG_G,
-
-/* +-----+
- * | #
- * | #
- * | #
- * +-----+
- * | #
- * | #
- * | #
- * +-----+
- */
- SEG_A|SEG_D|SEG_E|SEG_F|SEG_G,
-
-/* +#####+
- * | #
- * | #
- * | #
- * +#####+
- * # |
- * # |
- * # |
- * +#####+
- */
- SEG_C|SEG_F,
-
-/* +#####+
- * | #
- * | #
- * | #
- * +#####+
- * | #
- * | #
- * | #
- * +#####+
- */
- SEG_E|SEG_F,
-
-/* +-----+
- * # #
- * # #
- * # #
- * +#####+
- * | #
- * | #
- * | #
- * +-----+
- */
- SEG_A|SEG_D|SEG_E,
-
-/* +#####+
- * # |
- * # |
- * # |
- * +#####+
- * | #
- * | #
- * | #
- * +#####+
- */
- SEG_B|SEG_E,
-
-/* +#####+
- * # |
- * # |
- * # |
- * +#####+
- * # #
- * # #
- * # #
- * +#####+
- */
- SEG_B,
-
-/* +#####+
- * | #
- * | #
- * | #
- * +-----+
- * | #
- * | #
- * | #
- * +-----+
- */
- SEG_D|SEG_E|SEG_F,
-
-/* +#####+
- * # #
- * # #
- * # #
- * +#####+
- * # #
- * # #
- * # #
- * +#####+
- */
- 0,
-
-/* +#####+
- * # #
- * # #
- * # #
- * +#####+
- * | #
- * | #
- * | #
- * +-----+
- */
- SEG_D|SEG_E,
-};
-
-static uint8_t
-iq80321_7seg_xlate(char c)
-{
- uint8_t rv;
-
- if (c >= '0' && c <= '9')
- rv = digitmap[c - '0'];
- else if (c == '.')
- rv = (uint8_t) ~SEG_DP;
- else
- rv = 0xff;
-
- return (rv);
-}
-
-void
-iq80321_7seg(char a, char b)
-{
- uint8_t msb, lsb;
-
- msb = iq80321_7seg_xlate(a);
- lsb = iq80321_7seg_xlate(b);
-
- snakestate = 0;
-
- WRITE(IQ80321_7SEG_MSB, msb);
- WRITE(IQ80321_7SEG_LSB, lsb);
-}
-
-static const uint8_t snakemap[][2] = {
-
-/* +#####+ +#####+
- * | | | |
- * | | | |
- * | | | |
- * +-----+ +-----+
- * | | | |
- * | | | |
- * | | | |
- * +-----+ +-----+
- */
- { ~SEG_A, ~SEG_A },
-
-/* +-----+ +-----+
- * # | | #
- * # | | #
- * # | | #
- * +-----+ +-----+
- * | | | |
- * | | | |
- * | | | |
- * +-----+ +-----+
- */
- { ~SEG_F, ~SEG_B },
-
-/* +-----+ +-----+
- * | | | |
- * | | | |
- * | | | |
- * +#####+ +#####+
- * | | | |
- * | | | |
- * | | | |
- * +-----+ +-----+
- */
- { ~SEG_G, ~SEG_G },
-
-/* +-----+ +-----+
- * | | | |
- * | | | |
- * | | | |
- * +-----+ +-----+
- * | # # |
- * | # # |
- * | # # |
- * +-----+ +-----+
- */
- { ~SEG_C, ~SEG_E },
-
-/* +-----+ +-----+
- * | | | |
- * | | | |
- * | | | |
- * +-----+ +-----+
- * | | | |
- * | | | |
- * | | | |
- * +#####+ +#####+
- */
- { ~SEG_D, ~SEG_D },
-
-/* +-----+ +-----+
- * | | | |
- * | | | |
- * | | | |
- * +-----+ +-----+
- * # | | #
- * # | | #
- * # | | #
- * +-----+ +-----+
- */
- { ~SEG_E, ~SEG_C },
-
-/* +-----+ +-----+
- * | | | |
- * | | | |
- * | | | |
- * +#####+ +#####+
- * | | | |
- * | | | |
- * | | | |
- * +-----+ +-----+
- */
- { ~SEG_G, ~SEG_G },
-
-/* +-----+ +-----+
- * | # # |
- * | # # |
- * | # # |
- * +-----+ +-----+
- * | | | |
- * | | | |
- * | | | |
- * +-----+ +-----+
- */
- { ~SEG_B, ~SEG_F },
-};
-
-static SYSCTL_NODE(_hw, OID_AUTO, sevenseg, CTLFLAG_RD, 0, "7 seg");
-static int freq = 20;
-SYSCTL_INT(_hw_sevenseg, OID_AUTO, freq, CTLFLAG_RW, &freq, 0,
- "7 Seg update frequency");
-static void
-iq31244_7seg_snake(void)
-{
- static int snakefreq;
- int cur = snakestate;
-
- snakefreq++;
- if ((snakefreq % freq))
- return;
- WRITE(IQ80321_7SEG_MSB, snakemap[cur][0]);
- WRITE(IQ80321_7SEG_LSB, snakemap[cur][1]);
-
- snakestate = (cur + 1) & 7;
-}
-
-struct iq31244_7seg_softc {
- device_t dev;
-};
-
-static int
-iq31244_7seg_probe(device_t dev)
-{
-
- device_set_desc(dev, "IQ31244 7seg");
- return (0);
-}
-
-extern void (*i80321_hardclock_hook)(void);
-static int
-iq31244_7seg_attach(device_t dev)
-{
-
- i80321_hardclock_hook = iq31244_7seg_snake;
- return (0);
-}
-
-static device_method_t iq31244_7seg_methods[] = {
- DEVMETHOD(device_probe, iq31244_7seg_probe),
- DEVMETHOD(device_attach, iq31244_7seg_attach),
- {0, 0},
-};
-
-static driver_t iq31244_7seg_driver = {
- "iqseg",
- iq31244_7seg_methods,
- sizeof(struct iq31244_7seg_softc),
-};
-static devclass_t iq31244_7seg_devclass;
-
-DRIVER_MODULE(iqseg, iq, iq31244_7seg_driver, iq31244_7seg_devclass, 0, 0);
diff --git a/sys/arm/xscale/i80321/iq31244_machdep.c b/sys/arm/xscale/i80321/iq31244_machdep.c
deleted file mode 100644
index eb19f78d2a3e..000000000000
--- a/sys/arm/xscale/i80321/iq31244_machdep.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */
-
-/*-
- * Copyright (c) 1994-1998 Mark Brinicombe.
- * Copyright (c) 1994 Brini.
- * All rights reserved.
- *
- * This code is derived from software written for Brini by Mark Brinicombe
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Brini.
- * 4. The name of the company nor the name of the author may be used to
- * endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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.
- *
- * RiscBSD kernel project
- *
- * machdep.c
- *
- * Machine dependant functions for kernel setup
- *
- * This file needs a lot of work.
- *
- * Created : 17/09/94
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_kstack_pages.h"
-
-#define _ARM32_BUS_DMA_PRIVATE
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/sysproto.h>
-#include <sys/signalvar.h>
-#include <sys/imgact.h>
-#include <sys/kernel.h>
-#include <sys/ktr.h>
-#include <sys/linker.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mutex.h>
-#include <sys/pcpu.h>
-#include <sys/proc.h>
-#include <sys/ptrace.h>
-#include <sys/cons.h>
-#include <sys/bio.h>
-#include <sys/bus.h>
-#include <sys/buf.h>
-#include <sys/exec.h>
-#include <sys/kdb.h>
-#include <sys/msgbuf.h>
-#include <machine/reg.h>
-#include <machine/cpu.h>
-#include <machine/physmem.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_object.h>
-#include <vm/vm_page.h>
-#include <vm/vm_map.h>
-#include <machine/devmap.h>
-#include <machine/vmparam.h>
-#include <machine/pcb.h>
-#include <machine/undefined.h>
-#include <machine/machdep.h>
-#include <machine/metadata.h>
-#include <machine/armreg.h>
-#include <machine/bus.h>
-#include <sys/reboot.h>
-
-#include <arm/xscale/i80321/i80321reg.h>
-#include <arm/xscale/i80321/i80321var.h>
-#include <arm/xscale/i80321/iq80321reg.h>
-#include <arm/xscale/i80321/obiovar.h>
-
-#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */
-#define KERNEL_PT_IOPXS 1
-#define KERNEL_PT_BEFOREKERN 2
-#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */
-#define KERNEL_PT_AFKERNEL_NUM 9
-
-/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */
-#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM)
-
-struct pv_addr kernel_pt_table[NUM_KERNEL_PTS];
-
-/* Physical and virtual addresses for some global pages */
-
-struct pv_addr systempage;
-struct pv_addr msgbufpv;
-struct pv_addr irqstack;
-struct pv_addr undstack;
-struct pv_addr abtstack;
-struct pv_addr kernelstack;
-struct pv_addr minidataclean;
-
-#define IQ80321_OBIO_BASE 0xfe800000UL
-#define IQ80321_OBIO_SIZE 0x00100000UL
-/* Static device mappings. */
-static const struct arm_devmap_entry iq80321_devmap[] = {
- /*
- * Map the on-board devices VA == PA so that we can access them
- * with the MMU on or off.
- */
- {
- IQ80321_OBIO_BASE,
- IQ80321_OBIO_BASE,
- IQ80321_OBIO_SIZE,
- VM_PROT_READ|VM_PROT_WRITE,
- PTE_DEVICE,
- },
- {
- IQ80321_IOW_VBASE,
- VERDE_OUT_XLATE_IO_WIN0_BASE,
- VERDE_OUT_XLATE_IO_WIN_SIZE,
- VM_PROT_READ|VM_PROT_WRITE,
- PTE_DEVICE,
- },
-
- {
- IQ80321_80321_VBASE,
- VERDE_PMMR_BASE,
- VERDE_PMMR_SIZE,
- VM_PROT_READ|VM_PROT_WRITE,
- PTE_DEVICE,
- },
- {
- 0,
- 0,
- 0,
- 0,
- 0,
- }
-};
-
-#define SDRAM_START 0xa0000000
-
-extern vm_offset_t xscale_cache_clean_addr;
-
-void *
-initarm(struct arm_boot_params *abp)
-{
- struct pv_addr kernel_l1pt;
- struct pv_addr dpcpu;
- int loop, i;
- u_int l1pagetable;
- vm_offset_t freemempos;
- vm_offset_t freemem_pt;
- vm_offset_t afterkern;
- vm_offset_t freemem_after;
- vm_offset_t lastaddr;
- uint32_t memsize, memstart;
-
- lastaddr = parse_boot_param(abp);
- arm_physmem_kernaddr = abp->abp_physaddr;
- set_cpufuncs();
- pcpu_init(pcpup, 0, sizeof(struct pcpu));
- PCPU_SET(curthread, &thread0);
-
- /* Do basic tuning, hz etc */
- init_param1();
-
- freemempos = 0xa0200000;
- /* Define a macro to simplify memory allocation */
-#define valloc_pages(var, np) \
- alloc_pages((var).pv_pa, (np)); \
- (var).pv_va = (var).pv_pa + 0x20000000;
-
-#define alloc_pages(var, np) \
- freemempos -= (np * PAGE_SIZE); \
- (var) = freemempos; \
- memset((char *)(var), 0, ((np) * PAGE_SIZE));
-
- while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0)
- freemempos -= PAGE_SIZE;
- valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
- for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
- if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) {
- valloc_pages(kernel_pt_table[loop],
- L2_TABLE_SIZE / PAGE_SIZE);
- } else {
- kernel_pt_table[loop].pv_pa = freemempos +
- (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) *
- L2_TABLE_SIZE_REAL;
- kernel_pt_table[loop].pv_va =
- kernel_pt_table[loop].pv_pa + 0x20000000;
- }
- }
- freemem_pt = freemempos;
- freemempos = 0xa0100000;
- /*
- * Allocate a page for the system page mapped to V0x00000000
- * This page will just contain the system vectors and can be
- * shared by all processes.
- */
- valloc_pages(systempage, 1);
-
- /* Allocate dynamic per-cpu area. */
- valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE);
- dpcpu_init((void *)dpcpu.pv_va, 0);
-
- /* Allocate stacks for all modes */
- valloc_pages(irqstack, IRQ_STACK_SIZE);
- valloc_pages(abtstack, ABT_STACK_SIZE);
- valloc_pages(undstack, UND_STACK_SIZE);
- valloc_pages(kernelstack, kstack_pages);
- alloc_pages(minidataclean.pv_pa, 1);
- valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
- /*
- * Allocate memory for the l1 and l2 page tables. The scheme to avoid
- * wasting memory by allocating the l1pt on the first 16k memory was
- * taken from NetBSD rpc_machdep.c. NKPT should be greater than 12 for
- * this to work (which is supposed to be the case).
- */
-
- /*
- * Now we start construction of the L1 page table
- * We start by mapping the L2 page tables into the L1.
- * This means that we can replace L1 mappings later on if necessary
- */
- l1pagetable = kernel_l1pt.pv_va;
-
- /* Map the L2 pages tables in the L1 page table */
- pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00100000 - 1),
- &kernel_pt_table[KERNEL_PT_SYS]);
- pmap_link_l2pt(l1pagetable, IQ80321_IOPXS_VBASE,
- &kernel_pt_table[KERNEL_PT_IOPXS]);
- pmap_link_l2pt(l1pagetable, KERNBASE,
- &kernel_pt_table[KERNEL_PT_BEFOREKERN]);
- pmap_map_chunk(l1pagetable, KERNBASE, SDRAM_START, 0x100000,
- VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
- pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, SDRAM_START + 0x100000,
- 0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
- pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, SDRAM_START + 0x200000,
- (((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE) & ~(L1_S_SIZE - 1),
- VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
- freemem_after = ((int)lastaddr + PAGE_SIZE) & ~(PAGE_SIZE - 1);
- afterkern = round_page(((vm_offset_t)lastaddr + L1_S_SIZE) & ~(L1_S_SIZE
- - 1));
- for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) {
- pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000,
- &kernel_pt_table[KERNEL_PT_AFKERNEL + i]);
- }
- pmap_map_entry(l1pagetable, afterkern, minidataclean.pv_pa,
- VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
-
-
- /* Map the Mini-Data cache clean area. */
- xscale_setup_minidata(l1pagetable, afterkern,
- minidataclean.pv_pa);
-
- /* Map the vector page. */
- pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
- VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
- arm_devmap_bootstrap(l1pagetable, iq80321_devmap);
- /*
- * Give the XScale global cache clean code an appropriately
- * sized chunk of unmapped VA space starting at 0xff000000
- * (our device mappings end before this address).
- */
- xscale_cache_clean_addr = 0xff000000U;
-
- cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
- setttb(kernel_l1pt.pv_pa);
- cpu_tlb_flushID();
- cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
- /*
- * Pages were allocated during the secondary bootstrap for the
- * stacks for different CPU modes.
- * We must now set the r13 registers in the different CPU modes to
- * point to these stacks.
- * Since the ARM stacks use STMFD etc. we must set r13 to the top end
- * of the stack memory.
- */
- set_stackptrs(0);
-
- /*
- * We must now clean the cache again....
- * Cleaning may be done by reading new data to displace any
- * dirty data in the cache. This will have happened in setttb()
- * but since we are boot strapping the addresses used for the read
- * may have just been remapped and thus the cache could be out
- * of sync. A re-clean after the switch will cure this.
- * After booting there are no gross relocations of the kernel thus
- * this problem will not occur after initarm().
- */
- cpu_idcache_wbinv_all();
- cpu_setup();
-
- /*
- * Fetch the SDRAM start/size from the i80321 SDRAM configration
- * registers.
- */
- i80321_calibrate_delay();
- i80321_sdram_bounds(obio_bs_tag, IQ80321_80321_VBASE + VERDE_MCU_BASE,
- &memstart, &memsize);
- physmem = memsize / PAGE_SIZE;
- cninit();
-
- undefined_init();
-
- init_proc0(kernelstack.pv_va);
-
- /* Enable MMU, I-cache, D-cache, write buffer. */
-
- arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
- pmap_curmaxkvaddr = afterkern + PAGE_SIZE;
- vm_max_kernel_address = 0xe0000000;
- pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt);
- msgbufp = (void*)msgbufpv.pv_va;
- msgbufinit(msgbufp, msgbufsize);
- mutex_init();
-
- /*
- * Add the physical ram we have available.
- *
- * Exclude the kernel (and all the things we allocated which immediately
- * follow the kernel) from the VM allocation pool but not from crash
- * dumps. virtual_avail is a global variable which tracks the kva we've
- * "allocated" while setting up pmaps.
- *
- * Prepare the list of physical memory available to the vm subsystem.
- */
- arm_physmem_hardware_region(SDRAM_START, memsize);
- arm_physmem_exclude_region(freemem_pt, abp->abp_physaddr -
- freemem_pt, EXFLAG_NOALLOC);
- arm_physmem_exclude_region(freemempos, abp->abp_physaddr - 0x100000 -
- freemempos, EXFLAG_NOALLOC);
- arm_physmem_exclude_region(abp->abp_physaddr,
- virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC);
- arm_physmem_init_kernel_globals();
-
- init_param2(physmem);
- kdb_init();
- return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
- sizeof(struct pcb)));
-}
-
-extern int
-machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin)
-{
- int bus;
- int device;
- int func;
- uint32_t busno;
- struct i80321_pci_softc *sc = device_get_softc(pcib);
- bus = pci_get_bus(dev);
- device = pci_get_slot(dev);
- func = pci_get_function(dev);
- busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
- busno = PCIXSR_BUSNO(busno);
- if (busno == 0xff)
- busno = 0;
- if (bus != busno)
- goto no_mapping;
- switch (device) {
- /* IQ31244 PCI */
- case 1: /* PCIX-PCIX bridge */
- /*
- * The S-ATA chips are behind the bridge, and all of
- * the S-ATA interrupts are wired together.
- */
- return (ICU_INT_XINT(2));
- case 2: /* PCI slot */
- /* All pins are wired together. */
- return (ICU_INT_XINT(3));
- case 3: /* i82546 dual Gig-E */
- if (pin == 1 || pin == 2)
- return (ICU_INT_XINT(0));
- goto no_mapping;
- /* IQ80321 PCI */
- case 4: /* i82544 Gig-E */
- case 8: /*
- * Apparently you can set the device for the ethernet adapter
- * to 8 with a jumper, so handle that as well
- */
- if (pin == 1)
- return (ICU_INT_XINT(0));
- goto no_mapping;
- case 6: /* S-PCI-X slot */
- if (pin == 1)
- return (ICU_INT_XINT(2));
- if (pin == 2)
- return (ICU_INT_XINT(3));
- goto no_mapping;
- default:
-no_mapping:
- printf("No mapping for %d/%d/%d/%c\n", bus, device, func, pin);
-
- }
- return (0);
-
-}
diff --git a/sys/arm/xscale/i80321/iq80321.c b/sys/arm/xscale/i80321/iq80321.c
deleted file mode 100644
index fb344556ccb0..000000000000
--- a/sys/arm/xscale/i80321/iq80321.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/* $NetBSD: i80321_mainbus.c,v 1.13 2003/12/17 22:03:24 abs Exp $ */
-
-/*-
- * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
- * All rights reserved.
- *
- * Written by Jason R. Thorpe for Wasabi Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
- * 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.
- */
-
-/*
- * IQ80321 front-end for the i80321 I/O Processor. We take care
- * of setting up the i80321 memory map, PCI interrupt routing, etc.,
- * which are all specific to the board the i80321 is wired up to.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#define _ARM32_BUS_DMA_PRIVATE
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-#include <sys/rman.h>
-#include <machine/armreg.h>
-#include <machine/bus.h>
-#include <machine/intr.h>
-
-#include <arm/xscale/i80321/i80321reg.h>
-#include <arm/xscale/i80321/i80321var.h>
-#include <arm/xscale/i80321/iq80321reg.h>
-#include <arm/xscale/i80321/iq80321var.h>
-#include <arm/xscale/i80321/i80321_intr.h>
-
-#include <dev/pci/pcireg.h>
-
-
-int iq80321_probe(device_t);
-void iq80321_identify(driver_t *, device_t);
-int iq80321_attach(device_t);
-
-int
-iq80321_probe(device_t dev)
-{
- device_set_desc(dev, "Intel 80321");
- return (BUS_PROBE_NOWILDCARD);
-}
-
-void
-iq80321_identify(driver_t *driver, device_t parent)
-{
-
- BUS_ADD_CHILD(parent, 0, "iq", 0);
-}
-
-static struct arm32_dma_range i80321_dr;
-static int dma_range_init = 0;
-
-struct arm32_dma_range *
-bus_dma_get_range(void)
-{
- if (dma_range_init == 0)
- return (NULL);
- return (&i80321_dr);
-}
-
-int
-bus_dma_get_range_nb(void)
-{
- if (dma_range_init == 0)
- return (0);
- return (1);
-}
-
-#define PCI_MAPREG_MEM_PREFETCHABLE_MASK 0x00000008
-#define PCI_MAPREG_MEM_TYPE_64BIT 0x00000004
-
-int
-iq80321_attach(device_t dev)
-{
- struct i80321_softc *sc = device_get_softc(dev);
- int b0u, b0l, b1u, b1l;
- vm_paddr_t memstart = 0;
- vm_size_t memsize = 0;
- int busno;
-
- /*
- * Fill in the space tag for the i80321's own devices,
- * and hand-craft the space handle for it (the device
- * was mapped during early bootstrap).
- */
- i80321_bs_init(&i80321_bs_tag, sc);
- sc->sc_st = &i80321_bs_tag;
- sc->sc_sh = IQ80321_80321_VBASE;
- sc->dev = dev;
- sc->sc_is_host = 1;
-
- /*
- * Slice off a subregion for the Memory Controller -- we need it
- * here in order read the memory size.
- */
- if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_MCU_BASE,
- VERDE_MCU_SIZE, &sc->sc_mcu_sh))
- panic("%s: unable to subregion MCU registers",
- device_get_name(dev));
-
- if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE,
- VERDE_ATU_SIZE, &sc->sc_atu_sh))
- panic("%s: unable to subregion ATU registers",
- device_get_name(dev));
-
- /*
- * We have mapped the PCI I/O windows in the early
- * bootstrap phase.
- */
- sc->sc_iow_vaddr = IQ80321_IOW_VBASE;
-
- /*
- * Check the configuration of the ATU to see if another BIOS
- * has configured us. If a PC BIOS didn't configure us, then:
- * IQ80321: BAR0 00000000.0000000c BAR1 is 00000000.8000000c.
- * IQ31244: BAR0 00000000.00000004 BAR1 is 00000000.0000000c.
- * If a BIOS has configured us, at least one of those should be
- * different. This is pretty fragile, but it's not clear what
- * would work better.
- */
- b0l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x0);
- b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x4);
- b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x8);
- b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0xc);
-
-#ifdef VERBOSE_INIT_ARM
- printf("i80321: BAR0 = %08x.%08x BAR1 = %08x.%08x\n",
- b0l,b0u, b1l, b1u );
-#endif
-
-#define PCI_MAPREG_MEM_ADDR_MASK 0xfffffff0
- b0l &= PCI_MAPREG_MEM_ADDR_MASK;
- b0u &= PCI_MAPREG_MEM_ADDR_MASK;
- b1l &= PCI_MAPREG_MEM_ADDR_MASK;
- b1u &= PCI_MAPREG_MEM_ADDR_MASK;
-
-#ifdef VERBOSE_INIT_ARM
- printf("i80219: BAR0 = %08x.%08x BAR1 = %08x.%08x\n",
- b0l,b0u, b1l, b1u );
-#endif
-
- if ((b0u != b1u) || (b0l != 0) || ((b1l & ~0x80000000U) != 0))
- sc->sc_is_host = 0;
- else
- sc->sc_is_host = 1;
-
- /* FIXME: i force it's */
-
-#ifdef CPU_XSCALE_80219
- sc->sc_is_host = 1;
-#endif
-
- i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize);
- /*
- * We set up the Inbound Windows as follows:
- *
- * 0 Access to i80321 PMMRs
- *
- * 1 Reserve space for private devices
- *
- * 2 RAM access
- *
- * 3 Unused.
- *
- * This chunk needs to be customized for each IOP321 application.
- */
-#if 0
- sc->sc_iwin[0].iwin_base_lo = VERDE_PMMR_BASE;
- sc->sc_iwin[0].iwin_base_hi = 0;
- sc->sc_iwin[0].iwin_xlate = VERDE_PMMR_BASE;
- sc->sc_iwin[0].iwin_size = VERDE_PMMR_SIZE;
-#endif
- if (sc->sc_is_host) {
-
- /* Map PCI:Local 1:1. */
- sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE |
- PCI_MAPREG_MEM_PREFETCHABLE_MASK |
- PCI_MAPREG_MEM_TYPE_64BIT;
- sc->sc_iwin[1].iwin_base_hi = 0;
- } else {
-
- sc->sc_iwin[1].iwin_base_lo = 0;
- sc->sc_iwin[1].iwin_base_hi = 0;
- }
- sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE;
- sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE;
-
- if (sc->sc_is_host) {
- sc->sc_iwin[2].iwin_base_lo = memstart |
- PCI_MAPREG_MEM_PREFETCHABLE_MASK |
- PCI_MAPREG_MEM_TYPE_64BIT;
- sc->sc_iwin[2].iwin_base_hi = 0;
- } else {
- sc->sc_iwin[2].iwin_base_lo = 0;
- sc->sc_iwin[2].iwin_base_hi = 0;
- }
- sc->sc_iwin[2].iwin_xlate = memstart;
- sc->sc_iwin[2].iwin_size = memsize;
-
- if (sc->sc_is_host) {
- sc->sc_iwin[3].iwin_base_lo = 0 |
- PCI_MAPREG_MEM_PREFETCHABLE_MASK |
- PCI_MAPREG_MEM_TYPE_64BIT;
- } else {
- sc->sc_iwin[3].iwin_base_lo = 0;
- }
- sc->sc_iwin[3].iwin_base_hi = 0;
- sc->sc_iwin[3].iwin_xlate = 0;
- sc->sc_iwin[3].iwin_size = 0;
-
-#ifdef VERBOSE_INIT_ARM
- printf("i80321: Reserve space for private devices (Inbound Window 1) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n",
- sc->sc_iwin[1].iwin_base_hi,
- sc->sc_iwin[1].iwin_base_lo,
- sc->sc_iwin[1].iwin_xlate,
- sc->sc_iwin[1].iwin_size
- );
- printf("i80321: RAM access (Inbound Window 2) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n",
- sc->sc_iwin[2].iwin_base_hi,
- sc->sc_iwin[2].iwin_base_lo,
- sc->sc_iwin[2].iwin_xlate,
- sc->sc_iwin[2].iwin_size
- );
-#endif
-
- /*
- * We set up the Outbound Windows as follows:
- *
- * 0 Access to private PCI space.
- *
- * 1 Unused.
- */
-#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0)
- sc->sc_owin[0].owin_xlate_lo =
- PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo);
- sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi;
- /*
- * Set the Secondary Outbound I/O window to map
- * to PCI address 0 for all 64K of the I/O space.
- */
- sc->sc_ioout_xlate = 0;
- i80321_attach(sc);
- i80321_dr.dr_sysbase = sc->sc_iwin[2].iwin_xlate;
- i80321_dr.dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo);
- i80321_dr.dr_len = sc->sc_iwin[2].iwin_size;
- dma_range_init = 1;
- busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
- busno = PCIXSR_BUSNO(busno);
- if (busno == 0xff)
- busno = 0;
- sc->sc_irq_rman.rm_type = RMAN_ARRAY;
- sc->sc_irq_rman.rm_descr = "i80321 IRQs";
- if (rman_init(&sc->sc_irq_rman) != 0 ||
- rman_manage_region(&sc->sc_irq_rman, 0, 25) != 0)
- panic("i80321_attach: failed to set up IRQ rman");
-
- device_add_child(dev, "obio", 0);
- device_add_child(dev, "itimer", 0);
- device_add_child(dev, "iopwdog", 0);
-#ifndef CPU_XSCALE_80219
- device_add_child(dev, "iqseg", 0);
-#endif
- device_add_child(dev, "pcib", busno);
- device_add_child(dev, "i80321_dma", 0);
- device_add_child(dev, "i80321_dma", 1);
-#ifndef CPU_XSCALE_80219
- device_add_child(dev, "i80321_aau", 0);
-#endif
- bus_generic_probe(dev);
- bus_generic_attach(dev);
-
- return (0);
-}
-
-void
-arm_mask_irq(uintptr_t nb)
-{
- intr_enabled &= ~(1 << nb);
- i80321_set_intrmask();
-}
-
-void
-arm_unmask_irq(uintptr_t nb)
-{
- intr_enabled |= (1 << nb);
- i80321_set_intrmask();
-}
-
-
-void
-cpu_reset()
-{
- (void) disable_interrupts(PSR_I|PSR_F);
- *(__volatile uint32_t *)(IQ80321_80321_VBASE + VERDE_ATU_BASE +
- ATU_PCSR) = PCSR_RIB | PCSR_RPB;
- printf("Reset failed!\n");
- for(;;);
-}
-
-static struct resource *
-iq80321_alloc_resource(device_t dev, device_t child, int type, int *rid,
- u_long start, u_long end, u_long count, u_int flags)
-{
- struct i80321_softc *sc = device_get_softc(dev);
- struct resource *rv;
-
- if (type == SYS_RES_IRQ) {
- rv = rman_reserve_resource(&sc->sc_irq_rman,
- start, end, count, flags, child);
- if (rv != NULL)
- rman_set_rid(rv, *rid);
- return (rv);
- }
- return (NULL);
-}
-
-static int
-iq80321_setup_intr(device_t dev, device_t child,
- struct resource *ires, int flags, driver_filter_t *filt,
- driver_intr_t *intr, void *arg, void **cookiep)
-{
- int error;
-
- error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
- filt, intr, arg, cookiep);
- if (error)
- return (error);
- intr_enabled |= 1 << rman_get_start(ires);
- i80321_set_intrmask();
-
- return (0);
-}
-
-static int
-iq80321_teardown_intr(device_t dev, device_t child, struct resource *res,
- void *cookie)
-{
- return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
-}
-
-static device_method_t iq80321_methods[] = {
- DEVMETHOD(device_probe, iq80321_probe),
- DEVMETHOD(device_attach, iq80321_attach),
- DEVMETHOD(device_identify, iq80321_identify),
- DEVMETHOD(bus_alloc_resource, iq80321_alloc_resource),
- DEVMETHOD(bus_setup_intr, iq80321_setup_intr),
- DEVMETHOD(bus_teardown_intr, iq80321_teardown_intr),
- {0, 0},
-};
-
-static driver_t iq80321_driver = {
- "iq",
- iq80321_methods,
- sizeof(struct i80321_softc),
-};
-static devclass_t iq80321_devclass;
-
-DRIVER_MODULE(iq, nexus, iq80321_driver, iq80321_devclass, 0, 0);
diff --git a/sys/arm/xscale/i80321/iq80321reg.h b/sys/arm/xscale/i80321/iq80321reg.h
deleted file mode 100644
index d887fcd92663..000000000000
--- a/sys/arm/xscale/i80321/iq80321reg.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* $NetBSD: iq80321reg.h,v 1.4 2003/05/14 19:46:39 thorpej Exp $ */
-
-/*-
- * Copyright (c) 2002 Wasabi Systems, Inc.
- * All rights reserved.
- *
- * Written by Jason R. Thorpe for Wasabi Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- *
- */
-
-#ifndef _IQ80321REG_H_
-#define _IQ80321REG_H_
-
-/*
- * Memory map and register definitions for the Intel IQ80321
- * Evaluation Board.
- */
-
-/*
- * The memory map of the IQ80321 looks like so:
- *
- * ------------------------------
- * Intel 80321 IOP Reserved
- * FFFF E900 ------------------------------
- * Peripheral Memory Mapped
- * Registers
- * FFFF E000 ------------------------------
- * On-board devices
- * FE80 0000 ------------------------------
- * SDRAM
- * A000 0000 ------------------------------
- * Reserved
- * 9100 0000 ------------------------------
- * Flash
- * 9080 0000 ------------------------------
- * Reserved
- * 9002 0000 ------------------------------
- * ATU Outbound Transaction
- * Windows
- * 8000 0000 ------------------------------
- * ATU Outbound Direct
- * Addressing Windows
- * 0000 1000 ------------------------------
- * Initialization Boot Code
- * from Flash
- * 0000 0000 ------------------------------
- */
-
-/*
- * We allocate a page table for VA 0xfe400000 (4MB) and map the
- * PCI I/O space (64K) and i80321 memory-mapped registers (4K) there.
- */
-#define IQ80321_IOPXS_VBASE 0xfe400000UL
-#define IQ80321_IOW_VBASE IQ80321_IOPXS_VBASE
-#define IQ80321_80321_VBASE (IQ80321_IOW_VBASE + \
- VERDE_OUT_XLATE_IO_WIN_SIZE)
-
-#define IQ80321_SDRAM_START 0xa0000000
-/*
- * The IQ80321 on-board devices are mapped VA==PA during bootstrap.
- * Conveniently, the size of the on-board register space is 1 section
- * mapping.
- */
-#define IQ80321_OBIO_BASE 0xfe800000UL
-#define IQ80321_OBIO_SIZE 0x00100000UL /* 1MB */
-
-#define IQ80321_UART1 0xfe800000UL /* TI 16550 */
-
-#if defined( CPU_XSCALE_80321 )
-#define IQ80321_7SEG_MSB 0xfe840000UL
-#define IQ80321_7SEG_LSB 0xfe850000UL
-
-#define IQ80321_ROT_SWITCH 0xfe8d0000UL
-
-#define IQ80321_BATTERY_STAT 0xfe8f0000UL
-#define BATTERY_STAT_PRES (1U << 0)
-#define BATTERY_STAT_CHRG (1U << 1)
-#define BATTERY_STAT_DISCHRG (1U << 2)
-#endif /* CPU_XSCALE_80321 */
-
-#endif /* _IQ80321REG_H_ */
diff --git a/sys/arm/xscale/i80321/iq80321var.h b/sys/arm/xscale/i80321/iq80321var.h
deleted file mode 100644
index 4a035001bdf5..000000000000
--- a/sys/arm/xscale/i80321/iq80321var.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* $NetBSD: iq80321var.h,v 1.1 2002/03/27 21:51:30 thorpej Exp $ */
-
-/*-
- * Copyright (c) 2002 Wasabi Systems, Inc.
- * All rights reserved.
- *
- * Written by Jason R. Thorpe for Wasabi Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- *
- */
-
-#ifndef _IQ80321_IQ80321VAR_H_
-#define _IQ80321_IQ80321VAR_H_
-
-#include <dev/pci/pcivar.h>
-
-void iq80321_7seg(char, char);
-void iq80321_7seg_snake(void);
-
-#if 0
-void iq80321_pci_init(pci_chipset_tag_t, void *);
-#endif
-
-#endif /* _IQ80321_IQ80321VAR_H_ */
diff --git a/sys/arm/xscale/i80321/obio.c b/sys/arm/xscale/i80321/obio.c
deleted file mode 100644
index 55218ccd20d1..000000000000
--- a/sys/arm/xscale/i80321/obio.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/* $NetBSD: obio.c,v 1.11 2003/07/15 00:25:05 lukem Exp $ */
-
-/*-
- * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
- * All rights reserved.
- *
- * Written by Jason R. Thorpe for Wasabi Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
- * 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.
- */
-
-/*
- * On-board device autoconfiguration support for Intel IQ80321
- * evaluation boards.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/rman.h>
-#include <sys/malloc.h>
-
-#include <machine/bus.h>
-
-#include <arm/xscale/i80321/i80321reg.h>
-
-#include <arm/xscale/i80321/iq80321reg.h>
-#include <arm/xscale/i80321/obiovar.h>
-
-bus_space_tag_t obio_bs_tag;
-
-int obio_probe(device_t);
-int obio_attach(device_t);
-
-int
-obio_probe(device_t dev)
-{
- return (0);
-}
-
-int
-obio_attach(device_t dev)
-{
- struct obio_softc *sc = device_get_softc(dev);
-
- obio_bs_tag = arm_base_bs_tag;
- sc->oba_st = obio_bs_tag;
- sc->oba_addr = IQ80321_OBIO_BASE;
- sc->oba_size = IQ80321_OBIO_SIZE;
- sc->oba_rman.rm_type = RMAN_ARRAY;
- sc->oba_rman.rm_descr = "OBIO I/O";
- if (rman_init(&sc->oba_rman) != 0 ||
- rman_manage_region(&sc->oba_rman,
- sc->oba_addr, sc->oba_addr + sc->oba_size) != 0)
- panic("obio_attach: failed to set up I/O rman");
- sc->oba_irq_rman.rm_type = RMAN_ARRAY;
- sc->oba_irq_rman.rm_descr = "OBIO IRQ";
- if (rman_init(&sc->oba_irq_rman) != 0 ||
- rman_manage_region(&sc->oba_irq_rman, 28, 28) != 0)
- panic("obio_attach: failed to set up IRQ rman");
- device_add_child(dev, "uart", 0);
- bus_generic_probe(dev);
- bus_generic_attach(dev);
- return (0);
-}
-
-static struct resource *
-obio_alloc_resource(device_t bus, device_t child, int type, int *rid,
- u_long start, u_long end, u_long count, u_int flags)
-{
- struct resource *rv;
- struct rman *rm;
- bus_space_tag_t bt = NULL;
- bus_space_handle_t bh = 0;
- struct obio_softc *sc = device_get_softc(bus);
-
- switch (type) {
- case SYS_RES_IRQ:
- rm = &sc->oba_irq_rman;
- break;
- case SYS_RES_MEMORY:
- return (NULL);
- case SYS_RES_IOPORT:
- rm = &sc->oba_rman;
- bt = sc->oba_st;
- bh = sc->oba_addr;
- start = bh;
- break;
- default:
- return (NULL);
- }
-
-
- rv = rman_reserve_resource(rm, start, end, count, flags, child);
- if (rv == NULL)
- return (NULL);
- if (type == SYS_RES_IRQ)
- return (rv);
- rman_set_rid(rv, *rid);
- rman_set_bustag(rv, bt);
- rman_set_bushandle(rv, bh);
-
- return (rv);
-
-}
-
-static int
-obio_activate_resource(device_t bus, device_t child, int type, int rid,
- struct resource *r)
-{
- return (0);
-}
-static device_method_t obio_methods[] = {
- DEVMETHOD(device_probe, obio_probe),
- DEVMETHOD(device_attach, obio_attach),
-
- DEVMETHOD(bus_alloc_resource, obio_alloc_resource),
- DEVMETHOD(bus_activate_resource, obio_activate_resource),
- DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
- DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
-
- {0, 0},
-};
-
-static driver_t obio_driver = {
- "obio",
- obio_methods,
- sizeof(struct obio_softc),
-};
-static devclass_t obio_devclass;
-
-DRIVER_MODULE(obio, iq, obio_driver, obio_devclass, 0, 0);
diff --git a/sys/arm/xscale/i80321/obiovar.h b/sys/arm/xscale/i80321/obiovar.h
deleted file mode 100644
index 182b52f57f5a..000000000000
--- a/sys/arm/xscale/i80321/obiovar.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* $NetBSD: obiovar.h,v 1.4 2003/06/16 17:40:53 thorpej Exp $ */
-
-/*-
- * Copyright (c) 2002, 2003 Wasabi Systems, Inc.
- * All rights reserved.
- *
- * Written by Jason R. Thorpe for Wasabi Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- *
- */
-
-#ifndef _IQ80321_OBIOVAR_H_
-#define _IQ80321_OBIOVAR_H_
-
-#include <sys/rman.h>
-
-struct obio_softc {
- bus_space_tag_t oba_st; /* bus space tag */
- bus_addr_t oba_addr; /* address of device */
- bus_size_t oba_size; /* size of device */
- int oba_width; /* bus width */
- int oba_irq; /* XINT interrupt bit # */
- struct rman oba_rman;
- struct rman oba_irq_rman;
-
-};
-extern bus_space_tag_t obio_bs_tag;
-
-#endif /* _IQ80321_OBIOVAR_H_ */
diff --git a/sys/arm/xscale/i80321/std.ep80219 b/sys/arm/xscale/i80321/std.ep80219
deleted file mode 100644
index 9f5cbb755519..000000000000
--- a/sys/arm/xscale/i80321/std.ep80219
+++ /dev/null
@@ -1,7 +0,0 @@
-#EP80219 board configuration
-#$FreeBSD$
-include "../xscale/i80321/std.i80219"
-files "../xscale/i80321/files.ep80219"
-makeoptions KERNPHYSADDR=0xa0200000
-makeoptions KERNVIRTADDR=0xc0200000
-options COUNTS_PER_SEC=198000000
diff --git a/sys/arm/xscale/i80321/std.i80219 b/sys/arm/xscale/i80321/std.i80219
deleted file mode 100644
index 7cc8f377a876..000000000000
--- a/sys/arm/xscale/i80321/std.i80219
+++ /dev/null
@@ -1,5 +0,0 @@
-#XScale i80219 generic configuration
-#$FreeBSD$
-files "../xscale/i80321/files.i80219"
-include "../xscale/std.xscale-be"
-cpu CPU_XSCALE_80219
diff --git a/sys/arm/xscale/i80321/std.i80321 b/sys/arm/xscale/i80321/std.i80321
deleted file mode 100644
index 8142bdf0803e..000000000000
--- a/sys/arm/xscale/i80321/std.i80321
+++ /dev/null
@@ -1,5 +0,0 @@
-#XScale i80321 generic configuration
-#$FreeBSD$
-files "../xscale/i80321/files.i80321"
-include "../xscale/std.xscale-be"
-cpu CPU_XSCALE_80321
diff --git a/sys/arm/xscale/i80321/std.iq31244 b/sys/arm/xscale/i80321/std.iq31244
deleted file mode 100644
index c4c23bf7d620..000000000000
--- a/sys/arm/xscale/i80321/std.iq31244
+++ /dev/null
@@ -1,7 +0,0 @@
-#IQ31244 board configuration
-#$FreeBSD$
-include "../xscale/i80321/std.i80321"
-files "../xscale/i80321/files.iq31244"
-makeoptions KERNPHYSADDR=0xa0200000
-makeoptions KERNVIRTADDR=0xc0200000
-options COUNTS_PER_SEC=198000000
diff --git a/sys/arm/xscale/i80321/uart_bus_i80321.c b/sys/arm/xscale/i80321/uart_bus_i80321.c
deleted file mode 100644
index 5bb903df64cd..000000000000
--- a/sys/arm/xscale/i80321/uart_bus_i80321.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*-
- * Copyright (c) 2004 Olivier Houchard. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <machine/bus.h>
-#include <sys/rman.h>
-#include <machine/resource.h>
-
-#include <dev/pci/pcivar.h>
-
-#include <dev/uart/uart.h>
-#include <dev/uart/uart_bus.h>
-#include <dev/uart/uart_cpu.h>
-
-#include "uart_if.h"
-
-static int uart_i80321_probe(device_t dev);
-
-static device_method_t uart_i80321_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, uart_i80321_probe),
- DEVMETHOD(device_attach, uart_bus_attach),
- DEVMETHOD(device_detach, uart_bus_detach),
- { 0, 0 }
-};
-
-static driver_t uart_i80321_driver = {
- uart_driver_name,
- uart_i80321_methods,
- sizeof(struct uart_softc),
-};
-
-extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
-static int
-uart_i80321_probe(device_t dev)
-{
- struct uart_softc *sc;
-
- sc = device_get_softc(dev);
- sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
- sc->sc_class = &uart_ns8250_class;
- bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
- return(uart_bus_probe(dev, 0, 0, 0, 0));
-}
-
-
-DRIVER_MODULE(uart, obio, uart_i80321_driver, uart_devclass, 0, 0);
diff --git a/sys/arm/xscale/i8134x/crb_machdep.c b/sys/arm/xscale/i8134x/crb_machdep.c
index 2bd77a5f30a7..293696364a32 100644
--- a/sys/arm/xscale/i8134x/crb_machdep.c
+++ b/sys/arm/xscale/i8134x/crb_machdep.c
@@ -92,7 +92,7 @@ __FBSDID("$FreeBSD$");
#include <sys/reboot.h>
-#include <arm/xscale/i80321/i80321var.h> /* For i80321_calibrate_delay() */
+#include <arm/xscale/i8134x/i80321var.h> /* For i80321_calibrate_delay() */
#include <arm/xscale/i8134x/i81342reg.h>
#include <arm/xscale/i8134x/i81342var.h>
@@ -267,7 +267,7 @@ initarm(struct arm_boot_params *abp)
xscale_cache_clean_addr = 0xff000000U;
cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
- setttb(kernel_l1pt.pv_pa);
+ cpu_setttb(kernel_l1pt.pv_pa);
cpu_tlb_flushID();
cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
/*
@@ -284,7 +284,7 @@ initarm(struct arm_boot_params *abp)
/*
* We must now clean the cache again....
* Cleaning may be done by reading new data to displace any
- * dirty data in the cache. This will have happened in setttb()
+ * dirty data in the cache. This will have happened in cpu_setttb()
* but since we are boot strapping the addresses used for the read
* may have just been remapped and thus the cache could be out
* of sync. A re-clean after the switch will cure this.
diff --git a/sys/arm/xscale/i8134x/files.i81342 b/sys/arm/xscale/i8134x/files.i81342
index ed93e6bf855a..63c715cb4be7 100644
--- a/sys/arm/xscale/i8134x/files.i81342
+++ b/sys/arm/xscale/i8134x/files.i81342
@@ -1,7 +1,7 @@
# $FreeBSD$
arm/arm/bus_space_base.c standard
-arm/xscale/i80321/i80321_timer.c standard
-arm/xscale/i80321/i80321_wdog.c optional iopwdog
+arm/xscale/i8134x/i80321_timer.c standard
+arm/xscale/i8134x/i80321_wdog.c optional iopwdog
arm/xscale/i8134x/i81342.c standard
arm/xscale/i8134x/i81342_mcu.c standard
arm/xscale/i8134x/i81342_pci.c optional pci
diff --git a/sys/arm/xscale/i80321/i80321_timer.c b/sys/arm/xscale/i8134x/i80321_timer.c
index 3b4e5a11b552..ea15d920bf01 100644
--- a/sys/arm/xscale/i80321/i80321_timer.c
+++ b/sys/arm/xscale/i8134x/i80321_timer.c
@@ -59,8 +59,8 @@ __FBSDID("$FreeBSD$");
#include <machine/frame.h>
#include <machine/resource.h>
#include <machine/intr.h>
-#include <arm/xscale/i80321/i80321reg.h>
-#include <arm/xscale/i80321/i80321var.h>
+#include <arm/xscale/i8134x/i80321reg.h>
+#include <arm/xscale/i8134x/i80321var.h>
#ifdef CPU_XSCALE_81342
#define ICU_INT_TIMER0 (8) /* XXX: Can't include i81342reg.h because
diff --git a/sys/arm/xscale/i80321/i80321_wdog.c b/sys/arm/xscale/i8134x/i80321_wdog.c
index 9be98d2f7e25..c11c78a48e33 100644
--- a/sys/arm/xscale/i80321/i80321_wdog.c
+++ b/sys/arm/xscale/i8134x/i80321_wdog.c
@@ -54,8 +54,8 @@ __FBSDID("$FreeBSD$");
#include <machine/cpufunc.h>
#include <machine/machdep.h>
-#include <arm/xscale/i80321/i80321reg.h>
-#include <arm/xscale/i80321/i80321var.h>
+#include <arm/xscale/i8134x/i80321reg.h>
+#include <arm/xscale/i8134x/i80321var.h>
struct iopwdog_softc {
diff --git a/sys/arm/xscale/i80321/i80321reg.h b/sys/arm/xscale/i8134x/i80321reg.h
index 53617f956582..b6dd4fea14da 100644
--- a/sys/arm/xscale/i80321/i80321reg.h
+++ b/sys/arm/xscale/i8134x/i80321reg.h
@@ -91,19 +91,9 @@
#define VERDE_MCU_BASE 0x0500
#define VERDE_MCU_SIZE 0x0100
-#if defined(CPU_XSCALE_80321)
-#define VERDE_SSP_BASE 0x0600
-#define VERDE_SSP_SIZE 0x0080
-#endif
-
#define VERDE_PBIU_BASE 0x0680
#define VERDE_PBIU_SIZE 0x0080
-#if defined(CPU_XSCALE_80321)
-#define VERDE_AAU_BASE 0x0800
-#define VERDE_AAU_SIZE 0x0100
-#endif
-
#define VERDE_I2C_BASE 0x1680
#define VERDE_I2C_BASE0 (VERDE_I2C_BASE + 0x00)
#define VERDE_I2C_BASE1 (VERDE_I2C_BASE + 0x20)
@@ -340,21 +330,13 @@
#define ICU_INT_XINT(x) ((x) + ICU_INT_XINT0)
#define ICU_INT_bit26 26
-#if defined (CPU_XSCALE_80219)
-#define ICU_INT_bit25 25 /* reserved */
-#else
/* CPU_XSCALE_80321 */
#define ICU_INT_SSP 25 /* SSP serial port */
-#endif
#define ICU_INT_MUE 24 /* msg unit error */
-#if defined (CPU_XSCALE_80219)
-#define ICU_INT_bit23 23 /* reserved */
-#else
/* CPU_XSCALE_80321 */
#define ICU_INT_AAUE 23 /* AAU error */
-#endif
#define ICU_INT_bit22 22
#define ICU_INT_DMA1E 21 /* DMA Ch 1 error */
@@ -372,14 +354,9 @@
#define ICU_INT_TMR0 9 /* timer 0 */
#define ICU_INT_CPPM 8 /* core processor PMU */
-#if defined(CPU_XSCALE_80219)
-#define ICU_INT_bit7 7 /* reserved */
-#define ICU_INT_bit6 6 /* reserved */
-#else
/* CPU_XSCALE_80321 */
#define ICU_INT_AAU_EOC 7 /* AAU end-of-chain */
#define ICU_INT_AAU_EOT 6 /* AAU end-of-transfer */
-#endif
#define ICU_INT_bit5 5
#define ICU_INT_bit4 4
@@ -388,81 +365,12 @@
#define ICU_INT_DMA0_EOC 1 /* DMA0 end-of-chain */
#define ICU_INT_DMA0_EOT 0 /* DMA0 end-of-transfer */
-#if defined (CPU_XSCALE_80219)
-#define ICU_INT_HWMASK (0xffffffff & \
- ~((1 << ICU_INT_bit26) | \
- (1 << ICU_INT_bit25) | \
- (1 << ICU_INT_bit23) | \
- (1 << ICU_INT_bit22) | \
- (1 << ICU_INT_bit7) | \
- (1 << ICU_INT_bit6) | \
- (1 << ICU_INT_bit5) | \
- (1 << ICU_INT_bit4)))
-
-#else
/* CPU_XSCALE_80321 */
#define ICU_INT_HWMASK (0xffffffff & \
~((1 << ICU_INT_bit26) | \
(1 << ICU_INT_bit22) | \
(1 << ICU_INT_bit5) | \
(1 << ICU_INT_bit4)))
-#endif
-
-/*
- * SSP Serial Port
- */
-#if defined (CPU_XSCALE_80321)
-
-#define SSP_SSCR0 0x00 /* SSC control 0 */
-#define SSP_SSCR1 0x04 /* SSC control 1 */
-#define SSP_SSSR 0x08 /* SSP status */
-#define SSP_SSITR 0x0c /* SSP interrupt test */
-#define SSP_SSDR 0x10 /* SSP data */
-
-#define SSP_SSCR0_DSIZE(x) ((x) - 1)/* data size: 4..16 */
-#define SSP_SSCR0_FRF_SPI (0 << 4) /* Motorola Serial Periph Iface */
-#define SSP_SSCR0_FRF_SSP (1U << 4)/* TI Sync. Serial Protocol */
-#define SSP_SSCR0_FRF_UWIRE (2U << 4)/* NatSemi Microwire */
-#define SSP_SSCR0_FRF_rsvd (3U << 4)/* reserved */
-#define SSP_SSCR0_ECS (1U << 6)/* external clock select */
-#define SSP_SSCR0_SSE (1U << 7)/* sync. serial port enable */
-#define SSP_SSCR0_SCR(x) ((x) << 8)/* serial clock rate */
- /* bit rate = 3.6864 * 10e6 /
- (2 * (SCR + 1)) */
-
-#define SSP_SSCR1_RIE (1U << 0)/* Rx FIFO interrupt enable */
-#define SSP_SSCR1_TIE (1U << 1)/* Tx FIFO interrupt enable */
-#define SSP_SSCR1_LBM (1U << 2)/* loopback mode enable */
-#define SSP_SSCR1_SPO (1U << 3)/* Moto SPI SSCLK pol. (1 = high) */
-#define SSP_SSCR1_SPH (1U << 4)/* Moto SPI SSCLK phase:
- 0 = inactive full at start,
- 1/2 at end of frame
- 1 = inactive 1/2 at start,
- full at end of frame */
-#define SSP_SSCR1_MWDS (1U << 5)/* Microwire data size:
- 0 = 8 bit
- 1 = 16 bit */
-#define SSP_SSCR1_TFT (((x) - 1) << 6) /* Tx FIFO threshold */
-#define SSP_SSCR1_RFT (((x) - 1) << 10)/* Rx FIFO threshold */
-#define SSP_SSCR1_EFWR (1U << 14)/* enab. FIFO write/read */
-#define SSP_SSCR1_STRF (1U << 15)/* FIFO write/read FIFO select:
- 0 = Tx FIFO
- 1 = Rx FIFO */
-
-#define SSP_SSSR_TNF (1U << 2)/* Tx FIFO not full */
-#define SSP_SSSR_RNE (1U << 3)/* Rx FIFO not empty */
-#define SSP_SSSR_BSY (1U << 4)/* SSP is busy */
-#define SSP_SSSR_TFS (1U << 5)/* Tx FIFO service request */
-#define SSP_SSSR_RFS (1U << 6)/* Rx FIFO service request */
-#define SSP_SSSR_ROR (1U << 7)/* Rx FIFO overrun */
-#define SSP_SSSR_TFL(x) (((x) >> 8) & 0xf) /* Tx FIFO level */
-#define SSP_SSSR_RFL(x) (((x) >> 12) & 0xf)/* Rx FIFO level */
-
-#define SSP_SSITR_TTFS (1U << 5)/* Test Tx FIFO service */
-#define SSP_SSITR_TRFS (1U << 6)/* Test Rx FIFO service */
-#define SSP_SSITR_TROR (1U << 7)/* Test Rx overrun */
-
-#endif /* CPU_XSCALE_80321 */
/*
* Peripheral Bus Interface Unit
diff --git a/sys/arm/xscale/i80321/i80321var.h b/sys/arm/xscale/i8134x/i80321var.h
index 0fead2577a2e..0fead2577a2e 100644
--- a/sys/arm/xscale/i80321/i80321var.h
+++ b/sys/arm/xscale/i8134x/i80321var.h
diff --git a/sys/arm/xscale/ixp425/avila_machdep.c b/sys/arm/xscale/ixp425/avila_machdep.c
index e033e1357b64..f8632e10ad37 100644
--- a/sys/arm/xscale/ixp425/avila_machdep.c
+++ b/sys/arm/xscale/ixp425/avila_machdep.c
@@ -353,7 +353,7 @@ initarm(struct arm_boot_params *abp)
xscale_cache_clean_addr = 0xff000000U;
cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
- setttb(kernel_l1pt.pv_pa);
+ cpu_setttb(kernel_l1pt.pv_pa);
cpu_tlb_flushID();
cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
@@ -370,7 +370,7 @@ initarm(struct arm_boot_params *abp)
/*
* We must now clean the cache again....
* Cleaning may be done by reading new data to displace any
- * dirty data in the cache. This will have happened in setttb()
+ * dirty data in the cache. This will have happened in cpu_setttb()
* but since we are boot strapping the addresses used for the read
* may have just been remapped and thus the cache could be out
* of sync. A re-clean after the switch will cure this.
diff --git a/sys/arm/xscale/pxa/pxa_machdep.c b/sys/arm/xscale/pxa/pxa_machdep.c
index 5cc8d46c0823..2bbb8350a577 100644
--- a/sys/arm/xscale/pxa/pxa_machdep.c
+++ b/sys/arm/xscale/pxa/pxa_machdep.c
@@ -267,7 +267,7 @@ initarm(struct arm_boot_params *abp)
xscale_cache_clean_addr = 0xff000000U;
cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
- setttb(kernel_l1pt.pv_pa);
+ cpu_setttb(kernel_l1pt.pv_pa);
cpu_tlb_flushID();
cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
@@ -284,7 +284,7 @@ initarm(struct arm_boot_params *abp)
/*
* We must now clean the cache again....
* Cleaning may be done by reading new data to displace any
- * dirty data in the cache. This will have happened in setttb()
+ * dirty data in the cache. This will have happened in cpu_setttb()
* but since we are boot strapping the addresses used for the read
* may have just been remapped and thus the cache could be out
* of sync. A re-clean after the switch will cure this.
diff --git a/sys/arm64/arm64/copystr.c b/sys/arm64/arm64/copystr.c
index 008fdd1b5645..ebb4acddfbaf 100644
--- a/sys/arm64/arm64/copystr.c
+++ b/sys/arm64/arm64/copystr.c
@@ -56,6 +56,6 @@ copystr(const void * __restrict kfaddr, void * __restrict kdaddr, size_t len,
if (lencopied != NULL)
*lencopied = pos;
- return (0);
+ return (error);
}
diff --git a/sys/arm64/arm64/db_disasm.c b/sys/arm64/arm64/db_disasm.c
index 03784837b074..e24e0998fff5 100644
--- a/sys/arm64/arm64/db_disasm.c
+++ b/sys/arm64/arm64/db_disasm.c
@@ -31,11 +31,40 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <ddb/ddb.h>
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+
+#include <machine/disassem.h>
+
+static u_int db_disasm_read_word(vm_offset_t);
+static void db_disasm_printaddr(vm_offset_t);
+
+/* Glue code to interface db_disasm to the generic ARM disassembler */
+static const struct disasm_interface db_disasm_interface = {
+ db_disasm_read_word,
+ db_disasm_printaddr,
+ db_printf
+};
+
+static u_int
+db_disasm_read_word(vm_offset_t address)
+{
+
+ return (db_get_value(address, INSN_SIZE, 0));
+}
+
+static void
+db_disasm_printaddr(vm_offset_t address)
+{
+
+ db_printsym((db_addr_t)address, DB_STGY_ANY);
+}
vm_offset_t
db_disasm(vm_offset_t loc, bool altfmt)
{
- return 0;
+
+ return (disasm(&db_disasm_interface, loc, altfmt));
}
/* End of db_disasm.c */
diff --git a/sys/arm64/arm64/disassem.c b/sys/arm64/arm64/disassem.c
new file mode 100644
index 000000000000..46b62285f385
--- /dev/null
+++ b/sys/arm64/arm64/disassem.c
@@ -0,0 +1,330 @@
+/*-
+ * Copyright (c) 2016 Cavium
+ * All rights reserved.
+ *
+ * This software was developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include <sys/param.h>
+
+#include <sys/systm.h>
+#include <machine/disassem.h>
+#include <machine/armreg.h>
+#include <ddb/ddb.h>
+
+#define ARM64_MAX_TOKEN_LEN 8
+#define ARM64_MAX_TOKEN_CNT 10
+
+static const char *w_reg[] = {
+ "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
+ "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
+ "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
+ "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wSP",
+};
+
+static const char *x_reg[] = {
+ "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
+ "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
+ "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
+ "x24", "x25", "x26", "x27", "x28", "x29", "LR", "SP",
+};
+
+static const char *shift_2[] = {
+ "LSL", "LSR", "ASR", "RSV"
+};
+
+/*
+ * Structure representing single token (operand) inside instruction.
+ * name - name of operand
+ * pos - position within the instruction (in bits)
+ * len - operand length (in bits)
+ */
+struct arm64_insn_token {
+ char name[ARM64_MAX_TOKEN_LEN];
+ int pos;
+ int len;
+};
+
+/*
+ * Define generic types for instruction printing.
+ */
+enum arm64_format_type {
+ TYPE_01, /* OP <RD>, <RN>, <RM>{, <shift [LSL, LSR, ASR]> #<imm>} SF32/64
+ OP <RD>, <RN>, #<imm>{, <shift [0, 12]>} SF32/64 */
+};
+
+/*
+ * Structure representing single parsed instruction format.
+ * name - opcode name
+ * format - opcode format in a human-readable way
+ * type - syntax type for printing
+ * special_ops - special options passed to a printer (if any)
+ * mask - bitmask for instruction matching
+ * pattern - pattern to look for
+ * tokens - array of tokens (operands) inside instruction
+ */
+struct arm64_insn {
+ char* name;
+ char* format;
+ enum arm64_format_type type;
+ uint64_t special_ops;
+ uint32_t mask;
+ uint32_t pattern;
+ struct arm64_insn_token tokens[ARM64_MAX_TOKEN_CNT];
+};
+
+/*
+ * Specify instruction opcode format in a human-readable way. Use notation
+ * obtained from ARM Architecture Reference Manual for ARMv8-A.
+ *
+ * Format string description:
+ * Each group must be separated by "|". Group made of 0/1 is used to
+ * generate mask and pattern for instruction matching. Groups containing
+ * an operand token (in format NAME(length_bits)) are used to retrieve any
+ * operand data from the instruction. Names here must be meaningful
+ * and match the one described in the Manual.
+ *
+ * Token description:
+ * SF - "0" represents 32-bit access, "1" represents 64-bit access
+ * SHIFT - type of shift (instruction dependent)
+ * IMM - immediate value
+ * Rx - register number
+ */
+static struct arm64_insn arm64_i[] = {
+ { "add", "SF(1)|0001011|SHIFT(2)|0|RM(5)|IMM(6)|RN(5)|RD(5)", TYPE_01, 0 },
+ { "mov", "SF(1)|001000100000000000000|RN(5)|RD(5)", TYPE_01, 0 },
+ { "add", "SF(1)|0010001|SHIFT(2)|IMM(12)|RN(5)|RD(5)", TYPE_01, 0 },
+ { NULL, NULL }
+};
+
+static void
+arm64_disasm_generate_masks(struct arm64_insn *tab)
+{
+ uint32_t mask, val;
+ int a, i;
+ int len, ret;
+ int token = 0;
+ char *format;
+ int error;
+
+ while (tab->name != NULL) {
+ mask = 0;
+ val = 0;
+ format = tab->format;
+ token = 0;
+ error = 0;
+
+ /*
+ * For each entry analyze format strings from the
+ * left (i.e. from the MSB).
+ */
+ a = (INSN_SIZE * NBBY) - 1;
+ while (*format != '\0' && (a >= 0)) {
+ switch(*format) {
+ case '0':
+ /* Bit is 0, add to mask and pattern */
+ mask |= (1 << a);
+ a--;
+ format++;
+ break;
+ case '1':
+ /* Bit is 1, add to mask and pattern */
+ mask |= (1 << a);
+ val |= (1 << a);
+ a--;
+ format++;
+ break;
+ case '|':
+ /* skip */
+ format++;
+ break;
+ default:
+ /* Token found, copy the name */
+ memset(tab->tokens[token].name, 0,
+ sizeof(tab->tokens[token].name));
+ i = 0;
+ while (*format != '(') {
+ tab->tokens[token].name[i] = *format;
+ i++;
+ format++;
+ if (i >= ARM64_MAX_TOKEN_LEN) {
+ printf("ERROR: token too long in op %s\n",
+ tab->name);
+ error = 1;
+ break;
+ }
+ }
+ if (error != 0)
+ break;
+
+ /* Read the length value */
+ ret = sscanf(format, "(%d)", &len);
+ if (ret == 1) {
+ if (token >= ARM64_MAX_TOKEN_CNT) {
+ printf("ERROR: to many tokens in op %s\n",
+ tab->name);
+ error = 1;
+ break;
+ }
+
+ a -= len;
+ tab->tokens[token].pos = a + 1;
+ tab->tokens[token].len = len;
+ token++;
+ }
+
+ /* Skip to the end of the token */
+ while (*format != 0 && *format != '|')
+ format++;
+ }
+ }
+
+ /* Write mask and pattern to the instruction array */
+ tab->mask = mask;
+ tab->pattern = val;
+
+ /*
+ * If we got here, format string must be parsed and "a"
+ * should point to -1. If it's not, wrong number of bits
+ * in format string. Mark this as invalid and prevent
+ * from being matched.
+ */
+ if (*format != 0 || (a != -1) || (error != 0)) {
+ tab->mask = 0;
+ tab->pattern = 0xffffffff;
+ printf("ERROR: skipping instruction op %s\n",
+ tab->name);
+ }
+
+ tab++;
+ }
+}
+
+static int
+arm64_disasm_read_token(struct arm64_insn *insn, u_int opcode,
+ const char *token, int *val)
+{
+ int i;
+
+ for (i = 0; i < ARM64_MAX_TOKEN_CNT; i++) {
+ if (strcmp(insn->tokens[i].name, token) == 0) {
+ *val = (opcode >> insn->tokens[i].pos &
+ ((1 << insn->tokens[i].len) - 1));
+ return (0);
+ }
+ }
+
+ return (EINVAL);
+}
+
+static const char *
+arm64_reg(int b64, int num)
+{
+
+ if (b64 != 0)
+ return (x_reg[num]);
+
+ return (w_reg[num]);
+}
+
+vm_offset_t
+disasm(const struct disasm_interface *di, vm_offset_t loc, int altfmt)
+{
+ struct arm64_insn *i_ptr = arm64_i;
+ uint32_t insn;
+ int matchp;
+ int ret;
+ int shift, rm, rd, rn, imm, sf;
+ int rm_absent;
+
+ /* Initialize defaults, all are 0 except SF indicating 64bit access */
+ shift = rd = rm = rn = imm = 0;
+ sf = 1;
+
+ matchp = 0;
+ insn = di->di_readword(loc);
+ while (i_ptr->name) {
+ /* If mask is 0 then the parser was not initialized yet */
+ if ((i_ptr->mask != 0) &&
+ ((insn & i_ptr->mask) == i_ptr->pattern)) {
+ matchp = 1;
+ break;
+ }
+ i_ptr++;
+ }
+ if (matchp == 0)
+ goto undefined;
+
+ switch (i_ptr->type) {
+ case TYPE_01:
+ /* OP <RD>, <RN>, <RM>{, <shift [LSL, LSR, ASR]> #<imm>} SF32/64
+ OP <RD>, <RN>, #<imm>{, <shift [0, 12]>} SF32/64 */
+
+ /* Mandatory tokens */
+ ret = arm64_disasm_read_token(i_ptr, insn, "SF", &sf);
+ ret |= arm64_disasm_read_token(i_ptr, insn, "RD", &rd);
+ ret |= arm64_disasm_read_token(i_ptr, insn, "RN", &rn);
+ if (ret != 0) {
+ printf("ERROR: Missing mandatory token for op %s type %d\n",
+ i_ptr->name, i_ptr->type);
+ goto undefined;
+ }
+
+ /* Optional tokens */
+ arm64_disasm_read_token(i_ptr, insn, "IMM", &imm);
+ arm64_disasm_read_token(i_ptr, insn, "SHIFT", &shift);
+ rm_absent = arm64_disasm_read_token(i_ptr, insn, "RM", &rm);
+
+ di->di_printf("%s\t%s, %s", i_ptr->name, arm64_reg(sf, rd),
+ arm64_reg(sf, rn));
+
+ /* If RM is present use it, otherwise use immediate notation */
+ if (rm_absent == 0) {
+ di->di_printf(", %s", arm64_reg(sf, rm));
+ if (imm != 0)
+ di->di_printf(", %s #%d", shift_2[shift], imm);
+ } else {
+ if (imm != 0 || shift != 0)
+ di->di_printf(", #0x%x", imm);
+ if (shift != 0)
+ di->di_printf(" LSL #12");
+ }
+ break;
+ default:
+ goto undefined;
+ }
+
+ di->di_printf("\n");
+ return(loc + INSN_SIZE);
+
+undefined:
+ di->di_printf("undefined\t%08x\n", insn);
+ return(loc + INSN_SIZE);
+}
+
+/* Parse format strings at the very beginning */
+SYSINIT(arm64_disasm_generate_masks, SI_SUB_DDB_SERVICES,
+ SI_ORDER_FIRST, arm64_disasm_generate_masks, arm64_i);
diff --git a/sys/arm64/arm64/genassym.c b/sys/arm64/arm64/genassym.c
index 214b99d727d6..67c295f2ed9a 100644
--- a/sys/arm64/arm64/genassym.c
+++ b/sys/arm64/arm64/genassym.c
@@ -49,10 +49,12 @@ ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
/* Size of pcb, rounded to keep stack alignment */
ASSYM(PCB_SIZE, roundup2(sizeof(struct pcb), STACKALIGNBYTES + 1));
+ASSYM(PCB_SINGLE_STEP_SHIFT, PCB_SINGLE_STEP_SHIFT);
ASSYM(PCB_REGS, offsetof(struct pcb, pcb_x));
ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp));
ASSYM(PCB_L1ADDR, offsetof(struct pcb, pcb_l1addr));
ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
+ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
ASSYM(SF_UC, offsetof(struct sigframe, sf_uc));
diff --git a/sys/arm64/arm64/gic_fdt.c b/sys/arm64/arm64/gic_fdt.c
index 924a08b1cf66..075f1d6b8523 100644
--- a/sys/arm64/arm64/gic_fdt.c
+++ b/sys/arm64/arm64/gic_fdt.c
@@ -158,12 +158,17 @@ arm_gic_fdt_attach(device_t dev)
OF_getencprop(root, "#size-cells", &sc->sc_size_cells,
sizeof(sc->sc_size_cells));
+ /* If we have no children don't probe for them */
+ child = OF_child(root);
+ if (child == 0)
+ return (0);
+
if (gic_fill_ranges(root, sc) < 0) {
device_printf(dev, "could not get ranges\n");
return (ENXIO);
}
- for (child = OF_child(root); child != 0; child = OF_peer(child)) {
+ for (; child != 0; child = OF_peer(child)) {
dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO);
if (ofw_bus_gen_setup_devinfo(&dinfo->obdinfo, child) != 0) {
diff --git a/sys/arm64/arm64/intr_machdep.c b/sys/arm64/arm64/intr_machdep.c
index e297ff9f2279..3389c69da942 100644
--- a/sys/arm64/arm64/intr_machdep.c
+++ b/sys/arm64/arm64/intr_machdep.c
@@ -472,9 +472,6 @@ ipi_all_but_self(u_int ipi)
other_cpus = all_cpus;
CPU_CLR(PCPU_GET(cpuid), &other_cpus);
- /* ARM64TODO: This will be fixed with arm_intrng */
- ipi += 16;
-
CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
PIC_IPI_SEND(root_pic, other_cpus, ipi);
}
diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S
index 5a61c4a1f7cf..87abee18e483 100644
--- a/sys/arm64/arm64/locore.S
+++ b/sys/arm64/arm64/locore.S
@@ -369,8 +369,8 @@ create_pagetables:
sub x8, x7, x6
/* Get the number of l2 pages to allocate, rounded down */
lsr x10, x8, #(L2_SHIFT)
- /* Add 4 MiB for any rounding above and the module data */
- add x10, x10, #2
+ /* Add 8 MiB for any rounding above and the module data */
+ add x10, x10, #4
/* Create the kernel space L2 table */
mov x6, x26
@@ -628,11 +628,11 @@ tcr_early:
sctlr_set:
/* Bits to set */
.quad (SCTLR_UCI | SCTLR_nTWE | SCTLR_nTWI | SCTLR_UCT | SCTLR_DZE | \
- SCTLR_I | SCTLR_SED | SCTLR_C | SCTLR_M)
+ SCTLR_I | SCTLR_SED | SCTLR_SA0 | SCTLR_SA | SCTLR_C | SCTLR_M)
sctlr_clear:
/* Bits to clear */
.quad (SCTLR_EE | SCTLR_EOE | SCTLR_WXN | SCTLR_UMA | SCTLR_ITD | \
- SCTLR_THEE | SCTLR_CP15BEN | SCTLR_SA0 | SCTLR_SA | SCTLR_A)
+ SCTLR_THEE | SCTLR_CP15BEN | SCTLR_A)
.globl abort
abort:
diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c
index 409ecd316b27..f7552c46adae 100644
--- a/sys/arm64/arm64/machdep.c
+++ b/sys/arm64/arm64/machdep.c
@@ -233,7 +233,8 @@ int
ptrace_single_step(struct thread *td)
{
- /* TODO; */
+ td->td_frame->tf_spsr |= PSR_SS;
+ td->td_pcb->pcb_flags |= PCB_SINGLE_STEP;
return (0);
}
@@ -241,7 +242,8 @@ int
ptrace_clear_single_step(struct thread *td)
{
- /* TODO; */
+ td->td_frame->tf_spsr &= ~PSR_SS;
+ td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP;
return (0);
}
diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c
index 19cee7788c3f..b89982d32e9c 100644
--- a/sys/arm64/arm64/mp_machdep.c
+++ b/sys/arm64/arm64/mp_machdep.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_extern.h>
#include <vm/vm_kern.h>
+#include <machine/debug_monitor.h>
#include <machine/intr.h>
#include <machine/smp.h>
#ifdef VFP
@@ -247,6 +248,8 @@ init_secondary(uint64_t cpu)
vfp_init();
#endif
+ dbg_monitor_init();
+
/* Enable interrupts */
intr_enable();
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index dcd6e5dc8021..37b9480b620c 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -596,7 +596,8 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen)
* up to the physical address KERNBASE points at.
*/
map_slot = avail_slot = 0;
- for (; map_slot < (physmap_idx * 2); map_slot += 2) {
+ for (; map_slot < (physmap_idx * 2) &&
+ avail_slot < (PHYS_AVAIL_SIZE - 2); map_slot += 2) {
if (physmap[map_slot] == physmap[map_slot + 1])
continue;
@@ -612,7 +613,7 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen)
}
/* Add the memory before the kernel */
- if (physmap[avail_slot] < pa) {
+ if (physmap[avail_slot] < pa && avail_slot < (PHYS_AVAIL_SIZE - 2)) {
phys_avail[avail_slot] = physmap[map_slot];
phys_avail[avail_slot + 1] = pa;
physmem += (phys_avail[avail_slot + 1] -
diff --git a/sys/arm64/arm64/swtch.S b/sys/arm64/arm64/swtch.S
index bc2e52103416..3175e879114d 100644
--- a/sys/arm64/arm64/swtch.S
+++ b/sys/arm64/arm64/swtch.S
@@ -37,10 +37,37 @@
__FBSDID("$FreeBSD$");
+.macro clear_step_flag pcbflags, tmp
+ tbz \pcbflags, #PCB_SINGLE_STEP_SHIFT, 999f
+ mrs \tmp, mdscr_el1
+ bic \tmp, \tmp, #1
+ msr mdscr_el1, \tmp
+ isb
+999:
+.endm
+
+.macro set_step_flag pcbflags, tmp
+ tbz \pcbflags, #PCB_SINGLE_STEP_SHIFT, 999f
+ mrs \tmp, mdscr_el1
+ orr \tmp, \tmp, #1
+ msr mdscr_el1, \tmp
+ isb
+999:
+.endm
+
/*
* void cpu_throw(struct thread *old, struct thread *new)
*/
ENTRY(cpu_throw)
+ /* Of old == NULL skip disabling stepping */
+ cbz x0, 1f
+
+ /* If we were single stepping, disable it */
+ ldr x4, [x0, #TD_PCB]
+ ldr w5, [x4, #PCB_FLAGS]
+ clear_step_flag w5, x6
+1:
+
#ifdef VFP
/* Backup the new thread pointer around a call to C code */
mov x19, x1
@@ -69,6 +96,10 @@ ENTRY(cpu_throw)
dsb sy
isb
+ /* If we are single stepping, enable it */
+ ldr w5, [x4, #PCB_FLAGS]
+ set_step_flag w5, x6
+
/* Restore the registers */
ldp x5, x6, [x4, #PCB_SP]
mov sp, x5
@@ -127,6 +158,10 @@ ENTRY(cpu_switch)
mrs x6, tpidr_el0
stp x5, x6, [x4, #PCB_SP]
+ /* If we were single stepping, disable it */
+ ldr w5, [x4, #PCB_FLAGS]
+ clear_step_flag w5, x6
+
#ifdef VFP
mov x19, x0
mov x20, x1
@@ -166,15 +201,18 @@ ENTRY(cpu_switch)
*/
str x2, [x0, #TD_LOCK]
#if defined(SCHED_ULE) && defined(SMP)
- /* Read the value in blocked_lock */
- ldr x0, =_C_LABEL(blocked_lock)
- ldr x2, [x0]
+ /* Spin if TD_LOCK points to a blocked_lock */
+ ldr x2, =_C_LABEL(blocked_lock)
1:
ldar x3, [x1, #TD_LOCK]
cmp x3, x2
b.eq 1b
#endif
+ /* If we are single stepping, enable it */
+ ldr w5, [x4, #PCB_FLAGS]
+ set_step_flag w5, x6
+
/* Restore the registers */
ldp x5, x6, [x4, #PCB_SP]
mov sp, x5
diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c
index ac810adad27c..10e3f416c2a1 100644
--- a/sys/arm64/arm64/trap.c
+++ b/sys/arm64/arm64/trap.c
@@ -138,7 +138,6 @@ svc_handler(struct trapframe *frame)
int error;
td = curthread;
- td->td_frame = frame;
error = syscallenter(td, &sa);
syscallret(td, error, &sa);
@@ -338,6 +337,9 @@ do_el0_sync(struct trapframe *frame)
("Invalid pcpu address from userland: %p (tpidr %lx)",
get_pcpu(), READ_SPECIALREG(tpidr_el1)));
+ td = curthread;
+ td->td_frame = frame;
+
esr = READ_SPECIALREG(esr_el1);
exception = ESR_ELx_EXCEPTION(esr);
switch (exception) {
@@ -372,16 +374,27 @@ do_el0_sync(struct trapframe *frame)
case EXCP_UNKNOWN:
el0_excp_unknown(frame);
break;
+ case EXCP_SP_ALIGN:
+ call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_sp);
+ userret(td, frame);
+ break;
case EXCP_PC_ALIGN:
- td = curthread;
call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_elr);
userret(td, frame);
break;
case EXCP_BRK:
- td = curthread;
call_trapsignal(td, SIGTRAP, TRAP_BRKPT, (void *)frame->tf_elr);
userret(td, frame);
break;
+ case EXCP_SOFTSTP_EL0:
+ td->td_frame->tf_spsr &= ~PSR_SS;
+ td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP;
+ WRITE_SPECIALREG(MDSCR_EL1,
+ READ_SPECIALREG(MDSCR_EL1) & ~DBG_MDSCR_SS);
+ call_trapsignal(td, SIGTRAP, TRAP_TRACE,
+ (void *)frame->tf_elr);
+ userret(td, frame);
+ break;
default:
print_registers(frame);
panic("Unknown userland exception %x esr_el1 %lx\n", exception,
diff --git a/sys/arm64/arm64/uma_machdep.c b/sys/arm64/arm64/uma_machdep.c
index 9b9df5c68ed4..a9dae0f42573 100644
--- a/sys/arm64/arm64/uma_machdep.c
+++ b/sys/arm64/arm64/uma_machdep.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/systm.h>
+#include <sys/taskqueue.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <vm/vm_pageout.h>
diff --git a/sys/arm64/arm64/vm_machdep.c b/sys/arm64/arm64/vm_machdep.c
index 6794b1b411e2..3b6891496e68 100644
--- a/sys/arm64/arm64/vm_machdep.c
+++ b/sys/arm64/arm64/vm_machdep.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sf_buf.h>
#include <sys/signal.h>
#include <sys/unistd.h>
+#include <sys/taskqueue.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
diff --git a/sys/arm64/cavium/thunder_pcie.c b/sys/arm64/cavium/thunder_pcie.c
index 9785739a858f..ca2fd6f7ea68 100644
--- a/sys/arm64/cavium/thunder_pcie.c
+++ b/sys/arm64/cavium/thunder_pcie.c
@@ -28,6 +28,7 @@
*/
/* PCIe root complex driver for Cavium Thunder SOC */
+#include "opt_platform.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -43,9 +44,6 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/cpuset.h>
-#include <dev/ofw/openfirm.h>
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcib_private.h>
@@ -82,23 +80,6 @@ __FBSDID("$FreeBSD$");
#define THUNDER_ECAM6_CFG_BASE 0x94a000000000UL
#define THUNDER_ECAM7_CFG_BASE 0x94b000000000UL
-#define OFW_CELL_TO_UINT64(cell) \
- (((uint64_t)(*(cell)) << 32) | (uint64_t)(*((cell) + 1)))
-
-#define SPACE_CODE_SHIFT 24
-#define SPACE_CODE_MASK 0x3
-#define SPACE_CODE_IO_SPACE 0x1
-#define PROPS_CELL_SIZE 1
-#define PCI_ADDR_CELL_SIZE 2
-
-struct thunder_pcie_softc {
- struct pcie_range ranges[RANGES_TUPLES_MAX];
- struct rman mem_rman;
- struct resource *res;
- int ecam;
- device_t dev;
-};
-
/*
* ThunderX supports up to 4 ethernet interfaces, so it's good
* value to use as default for numbers of VFs, since each eth
@@ -109,39 +90,16 @@ SYSCTL_INT(_hw, OID_AUTO, thunder_pcie_max_vfs, CTLFLAG_RWTUN,
&thunder_pcie_max_vfs, 0, "Max VFs supported by ThunderX internal PCIe");
/* Forward prototypes */
-static struct resource *thunder_pcie_alloc_resource(device_t,
- device_t, int, int *, rman_res_t, rman_res_t, rman_res_t, u_int);
-static int thunder_pcie_attach(device_t);
static int thunder_pcie_identify_pcib(device_t);
static int thunder_pcie_maxslots(device_t);
-static int parse_pci_mem_ranges(struct thunder_pcie_softc *);
-static int thunder_pcie_probe(device_t);
static uint32_t thunder_pcie_read_config(device_t, u_int, u_int, u_int, u_int,
int);
static int thunder_pcie_read_ivar(device_t, device_t, int, uintptr_t *);
-static int thunder_pcie_release_resource(device_t, device_t, int, int,
- struct resource *);
static void thunder_pcie_write_config(device_t, u_int, u_int,
u_int, u_int, uint32_t, int);
static int thunder_pcie_write_ivar(device_t, device_t, int, uintptr_t);
-static int
-thunder_pcie_probe(device_t dev)
-{
-
- if (!ofw_bus_status_okay(dev))
- return (ENXIO);
-
- if (ofw_bus_is_compatible(dev, "cavium,thunder-pcie") ||
- ofw_bus_is_compatible(dev, "cavium,pci-host-thunder-ecam")) {
- device_set_desc(dev, "Cavium Integrated PCI/PCI-E Controller");
- return (BUS_PROBE_DEFAULT);
- }
-
- return (ENXIO);
-}
-
-static int
+int
thunder_pcie_attach(device_t dev)
{
int rid;
@@ -167,13 +125,6 @@ thunder_pcie_attach(device_t dev)
sc->mem_rman.rm_type = RMAN_ARRAY;
sc->mem_rman.rm_descr = "PCIe Memory";
- /* Retrieve 'ranges' property from FDT */
- if (bootverbose)
- device_printf(dev, "parsing FDT for ECAM%d:\n",
- sc->ecam);
- if (parse_pci_mem_ranges(sc))
- return (ENXIO);
-
/* Initialize rman and allocate memory regions */
error = rman_init(&sc->mem_rman);
if (error) {
@@ -199,115 +150,6 @@ thunder_pcie_attach(device_t dev)
return (bus_generic_attach(dev));
}
-static int
-parse_pci_mem_ranges(struct thunder_pcie_softc *sc)
-{
- phandle_t node;
- pcell_t pci_addr_cells, parent_addr_cells, size_cells;
- pcell_t attributes;
- pcell_t *ranges_buf, *cell_ptr;
- int cells_count, tuples_count;
- int tuple;
- int rv;
-
- node = ofw_bus_get_node(sc->dev);
-
- /* Find address cells if present */
- if (OF_getencprop(node, "#address-cells", &pci_addr_cells,
- sizeof(pci_addr_cells)) < sizeof(pci_addr_cells))
- pci_addr_cells = 2;
-
- /* Find size cells if present */
- if (OF_getencprop(node, "#size-cells", &size_cells,
- sizeof(size_cells)) < sizeof(size_cells))
- size_cells = 1;
-
- /* Find parent address cells if present */
- if (OF_getencprop(OF_parent(node), "#address-cells",
- &parent_addr_cells, sizeof(parent_addr_cells)) < sizeof(parent_addr_cells))
- parent_addr_cells = 2;
-
- /* Check if FDT format matches driver requirements */
- if ((parent_addr_cells != 2) || (pci_addr_cells != 3) ||
- (size_cells != 2)) {
- device_printf(sc->dev,
- "Unexpected number of address or size cells in FDT "
- " %d:%d:%d\n",
- parent_addr_cells, pci_addr_cells, size_cells);
- return (ENXIO);
- }
-
- cells_count = OF_getencprop_alloc(node, "ranges",
- sizeof(pcell_t), (void **)&ranges_buf);
- if (cells_count == -1) {
- device_printf(sc->dev, "Error parsing FDT 'ranges' property\n");
- return (ENXIO);
- }
-
- tuples_count = cells_count /
- (pci_addr_cells + parent_addr_cells + size_cells);
- if (tuples_count > RANGES_TUPLES_MAX) {
- device_printf(sc->dev,
- "Unexpected number of 'ranges' tuples in FDT\n");
- rv = ENXIO;
- goto out;
- }
-
- cell_ptr = ranges_buf;
-
- for (tuple = 0; tuple < tuples_count; tuple++) {
- /*
- * TUPLE FORMAT:
- * attributes - 32-bit attributes field
- * PCI address - bus address combined of two cells in
- * a following format:
- * <ADDR MSB> <ADDR LSB>
- * PA address - physical address combined of two cells in
- * a following format:
- * <ADDR MSB> <ADDR LSB>
- * size - range size combined of two cells in
- * a following format:
- * <ADDR MSB> <ADDR LSB>
- */
- attributes = *cell_ptr;
- attributes = (attributes >> SPACE_CODE_SHIFT) & SPACE_CODE_MASK;
- if (attributes == SPACE_CODE_IO_SPACE) {
- /* Internal PCIe does not support IO space, ignore. */
- sc->ranges[tuple].phys_base = 0;
- sc->ranges[tuple].size = 0;
- cell_ptr +=
- (pci_addr_cells + parent_addr_cells + size_cells);
- continue;
- }
- cell_ptr += PROPS_CELL_SIZE;
- sc->ranges[tuple].pci_base = OFW_CELL_TO_UINT64(cell_ptr);
- cell_ptr += PCI_ADDR_CELL_SIZE;
- sc->ranges[tuple].phys_base = OFW_CELL_TO_UINT64(cell_ptr);
- cell_ptr += parent_addr_cells;
- sc->ranges[tuple].size = OFW_CELL_TO_UINT64(cell_ptr);
- cell_ptr += size_cells;
-
- if (bootverbose) {
- device_printf(sc->dev,
- "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx\n",
- sc->ranges[tuple].pci_base,
- sc->ranges[tuple].phys_base,
- sc->ranges[tuple].size);
- }
-
- }
- for (; tuple < RANGES_TUPLES_MAX; tuple++) {
- /* zero-fill remaining tuples to mark empty elements in array */
- sc->ranges[tuple].phys_base = 0;
- sc->ranges[tuple].size = 0;
- }
-
- rv = 0;
-out:
- free(ranges_buf, M_OFWPROP);
- return (rv);
-}
-
static uint32_t
thunder_pcie_read_config(device_t dev, u_int bus, u_int slot,
u_int func, u_int reg, int bytes)
@@ -417,19 +259,19 @@ thunder_pcie_write_ivar(device_t dev, device_t child, int index,
return (ENOENT);
}
-static int
+int
thunder_pcie_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *res)
{
if (type != SYS_RES_MEMORY)
- return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
+ return (bus_generic_release_resource(dev, child,
type, rid, res));
return (rman_release_resource(res));
}
-static struct resource *
+struct resource *
thunder_pcie_alloc_resource(device_t dev, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
@@ -446,7 +288,7 @@ thunder_pcie_alloc_resource(device_t dev, device_t child, int type, int *rid,
rm = &sc->mem_rman;
break;
default:
- return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
+ return (bus_generic_alloc_resource(dev, child,
type, rid, start, end, count, flags));
};
@@ -558,8 +400,6 @@ thunder_pcie_identify_pcib(device_t dev)
}
static device_method_t thunder_pcie_methods[] = {
- DEVMETHOD(device_probe, thunder_pcie_probe),
- DEVMETHOD(device_attach, thunder_pcie_attach),
DEVMETHOD(pcib_maxslots, thunder_pcie_maxslots),
DEVMETHOD(pcib_read_config, thunder_pcie_read_config),
DEVMETHOD(pcib_write_config, thunder_pcie_write_config),
@@ -581,15 +421,5 @@ static device_method_t thunder_pcie_methods[] = {
DEVMETHOD_END
};
-static driver_t thunder_pcie_driver = {
- "pcib",
- thunder_pcie_methods,
- sizeof(struct thunder_pcie_softc),
-};
-
-static devclass_t thunder_pcie_devclass;
-
-DRIVER_MODULE(thunder_pcib, simplebus, thunder_pcie_driver,
-thunder_pcie_devclass, 0, 0);
-DRIVER_MODULE(thunder_pcib, ofwbus, thunder_pcie_driver,
-thunder_pcie_devclass, 0, 0);
+DEFINE_CLASS_0(pcib, thunder_pcie_driver, thunder_pcie_methods,
+ sizeof(struct thunder_pcie_softc));
diff --git a/sys/arm64/cavium/thunder_pcie_common.c b/sys/arm64/cavium/thunder_pcie_common.c
index e1b7fb2c0d95..58239f1eed9f 100644
--- a/sys/arm64/cavium/thunder_pcie_common.c
+++ b/sys/arm64/cavium/thunder_pcie_common.c
@@ -35,13 +35,18 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/bus.h>
+#include <sys/rman.h>
+
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/intr.h>
#include "thunder_pcie_common.h"
+MALLOC_DEFINE(M_THUNDER_PCIE, "Thunder PCIe driver", "Thunder PCIe driver memory");
+
uint32_t
range_addr_is_pci(struct pcie_range *ranges, uint64_t addr, uint64_t size)
{
diff --git a/sys/arm64/cavium/thunder_pcie_common.h b/sys/arm64/cavium/thunder_pcie_common.h
index 731675b9b0b4..548a43518c68 100644
--- a/sys/arm64/cavium/thunder_pcie_common.h
+++ b/sys/arm64/cavium/thunder_pcie_common.h
@@ -32,6 +32,10 @@
#define RANGES_TUPLES_MAX 6
#define RANGES_TUPLES_INVALID (RANGES_TUPLES_MAX + 1)
+DECLARE_CLASS(thunder_pcie_driver);
+
+MALLOC_DECLARE(M_THUNDER_PCIE);
+
struct pcie_range {
uint64_t pci_base;
uint64_t phys_base;
@@ -39,6 +43,14 @@ struct pcie_range {
uint64_t flags;
};
+struct thunder_pcie_softc {
+ struct pcie_range ranges[RANGES_TUPLES_MAX];
+ struct rman mem_rman;
+ struct resource *res;
+ int ecam;
+ device_t dev;
+};
+
uint32_t range_addr_is_pci(struct pcie_range *, uint64_t, uint64_t);
uint32_t range_addr_is_phys(struct pcie_range *, uint64_t, uint64_t);
uint64_t range_addr_pci_to_phys(struct pcie_range *, uint64_t);
@@ -48,4 +60,11 @@ int thunder_common_map_msi(device_t, device_t, int, uint64_t *, uint32_t *);
int thunder_common_release_msi(device_t, device_t, int, int *);
int thunder_common_release_msix(device_t, device_t, int);
+struct resource *thunder_pcie_alloc_resource(device_t,
+ device_t, int, int *, rman_res_t, rman_res_t, rman_res_t, u_int);
+int thunder_pcie_release_resource(device_t, device_t, int, int,
+ struct resource *);
+
+int thunder_pcie_attach(device_t);
+
#endif /* _CAVIUM_THUNDER_PCIE_COMMON_H_ */
diff --git a/sys/arm64/cavium/thunder_pcie_fdt.c b/sys/arm64/cavium/thunder_pcie_fdt.c
new file mode 100644
index 000000000000..f1624f615484
--- /dev/null
+++ b/sys/arm64/cavium/thunder_pcie_fdt.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2016 Cavium Inc.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/cpuset.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "thunder_pcie_common.h"
+
+#define OFW_CELL_TO_UINT64(cell) \
+ (((uint64_t)(*(cell)) << 32) | (uint64_t)(*((cell) + 1)))
+
+#define SPACE_CODE_SHIFT 24
+#define SPACE_CODE_MASK 0x3
+#define SPACE_CODE_IO_SPACE 0x1
+#define PROPS_CELL_SIZE 1
+#define PCI_ADDR_CELL_SIZE 2
+
+static int thunder_pcie_fdt_probe(device_t);
+static int thunder_pcie_fdt_attach(device_t);
+
+static struct resource * thunder_pcie_ofw_bus_alloc_res(device_t, device_t,
+ int, int *, rman_res_t, rman_res_t, rman_res_t, u_int);
+static int thunder_pcie_ofw_bus_rel_res(device_t, device_t, int, int,
+ struct resource *);
+
+static const struct ofw_bus_devinfo *thunder_pcie_ofw_get_devinfo(device_t,
+ device_t);
+
+static device_method_t thunder_pcie_fdt_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, thunder_pcie_fdt_probe),
+ DEVMETHOD(device_attach, thunder_pcie_fdt_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_alloc_resource, thunder_pcie_ofw_bus_alloc_res),
+ DEVMETHOD(bus_release_resource, thunder_pcie_ofw_bus_rel_res),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_devinfo, thunder_pcie_ofw_get_devinfo),
+ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
+ DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
+ DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
+ DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
+ DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
+
+ /* End */
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(pcib, thunder_pcie_fdt_driver, thunder_pcie_fdt_methods,
+ sizeof(struct thunder_pcie_softc), thunder_pcie_driver);
+
+static devclass_t thunder_pcie_fdt_devclass;
+
+DRIVER_MODULE(thunder_pcib, simplebus, thunder_pcie_fdt_driver,
+ thunder_pcie_fdt_devclass, 0, 0);
+DRIVER_MODULE(thunder_pcib, ofwbus, thunder_pcie_fdt_driver,
+ thunder_pcie_fdt_devclass, 0, 0);
+
+static int thunder_pcie_fdt_ranges(device_t);
+static int thunder_pcie_ofw_bus_attach(device_t);
+
+static int
+thunder_pcie_fdt_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "cavium,thunder-pcie") ||
+ ofw_bus_is_compatible(dev, "cavium,pci-host-thunder-ecam")) {
+ device_set_desc(dev, "Cavium Integrated PCI/PCI-E Controller");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+thunder_pcie_fdt_attach(device_t dev)
+{
+ int err;
+
+ /* Retrieve 'ranges' property from FDT */
+ if (thunder_pcie_fdt_ranges(dev) != 0)
+ return (ENXIO);
+
+ err = thunder_pcie_ofw_bus_attach(dev);
+ if (err != 0)
+ return (err);
+
+ return (thunder_pcie_attach(dev));
+}
+
+static __inline void
+get_addr_size_cells(phandle_t node, pcell_t *addr_cells, pcell_t *size_cells)
+{
+
+ *addr_cells = 2;
+ /* Find address cells if present */
+ OF_getencprop(node, "#address-cells", addr_cells, sizeof(*addr_cells));
+
+ *size_cells = 2;
+ /* Find size cells if present */
+ OF_getencprop(node, "#size-cells", size_cells, sizeof(*size_cells));
+}
+
+static int
+thunder_pcie_fdt_ranges(device_t dev)
+{
+ struct thunder_pcie_softc *sc;
+ phandle_t node;
+ pcell_t pci_addr_cells, parent_addr_cells, size_cells;
+ pcell_t attributes;
+ pcell_t *ranges_buf, *cell_ptr;
+ int cells_count, tuples_count;
+ int tuple;
+ int rv;
+
+ sc = device_get_softc(dev);
+ node = ofw_bus_get_node(dev);
+
+ get_addr_size_cells(node, &pci_addr_cells, &size_cells);
+
+ /* Find parent address cells if present */
+ if (OF_getencprop(OF_parent(node), "#address-cells",
+ &parent_addr_cells, sizeof(parent_addr_cells)) < sizeof(parent_addr_cells))
+ parent_addr_cells = 2;
+
+ /* Check if FDT format matches driver requirements */
+ if ((parent_addr_cells != 2) || (pci_addr_cells != 3) ||
+ (size_cells != 2)) {
+ device_printf(dev,
+ "Unexpected number of address or size cells in FDT "
+ " %d:%d:%d\n",
+ parent_addr_cells, pci_addr_cells, size_cells);
+ return (ENXIO);
+ }
+
+ cells_count = OF_getencprop_alloc(node, "ranges",
+ sizeof(pcell_t), (void **)&ranges_buf);
+ if (cells_count == -1) {
+ device_printf(dev, "Error parsing FDT 'ranges' property\n");
+ return (ENXIO);
+ }
+
+ tuples_count = cells_count /
+ (pci_addr_cells + parent_addr_cells + size_cells);
+ if (tuples_count > RANGES_TUPLES_MAX) {
+ device_printf(dev,
+ "Unexpected number of 'ranges' tuples in FDT\n");
+ rv = ENXIO;
+ goto out;
+ }
+
+ cell_ptr = ranges_buf;
+
+ for (tuple = 0; tuple < tuples_count; tuple++) {
+ /*
+ * TUPLE FORMAT:
+ * attributes - 32-bit attributes field
+ * PCI address - bus address combined of two cells in
+ * a following format:
+ * <ADDR MSB> <ADDR LSB>
+ * PA address - physical address combined of two cells in
+ * a following format:
+ * <ADDR MSB> <ADDR LSB>
+ * size - range size combined of two cells in
+ * a following format:
+ * <ADDR MSB> <ADDR LSB>
+ */
+ attributes = *cell_ptr;
+ attributes = (attributes >> SPACE_CODE_SHIFT) & SPACE_CODE_MASK;
+ if (attributes == SPACE_CODE_IO_SPACE) {
+ /* Internal PCIe does not support IO space, ignore. */
+ sc->ranges[tuple].phys_base = 0;
+ sc->ranges[tuple].size = 0;
+ cell_ptr +=
+ (pci_addr_cells + parent_addr_cells + size_cells);
+ continue;
+ }
+ cell_ptr += PROPS_CELL_SIZE;
+ sc->ranges[tuple].pci_base = OFW_CELL_TO_UINT64(cell_ptr);
+ cell_ptr += PCI_ADDR_CELL_SIZE;
+ sc->ranges[tuple].phys_base = OFW_CELL_TO_UINT64(cell_ptr);
+ cell_ptr += parent_addr_cells;
+ sc->ranges[tuple].size = OFW_CELL_TO_UINT64(cell_ptr);
+ cell_ptr += size_cells;
+
+ if (bootverbose) {
+ device_printf(dev,
+ "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx\n",
+ sc->ranges[tuple].pci_base,
+ sc->ranges[tuple].phys_base,
+ sc->ranges[tuple].size);
+ }
+
+ }
+ for (; tuple < RANGES_TUPLES_MAX; tuple++) {
+ /* zero-fill remaining tuples to mark empty elements in array */
+ sc->ranges[tuple].phys_base = 0;
+ sc->ranges[tuple].size = 0;
+ }
+
+ rv = 0;
+out:
+ free(ranges_buf, M_OFWPROP);
+ return (rv);
+}
+
+/* OFW bus interface */
+struct thunder_pcie_ofw_devinfo {
+ struct ofw_bus_devinfo di_dinfo;
+ struct resource_list di_rl;
+};
+
+static const struct ofw_bus_devinfo *
+thunder_pcie_ofw_get_devinfo(device_t bus __unused, device_t child)
+{
+ struct thunder_pcie_ofw_devinfo *di;
+
+ di = device_get_ivars(child);
+ return (&di->di_dinfo);
+}
+
+static struct resource *
+thunder_pcie_ofw_bus_alloc_res(device_t bus, device_t child, int type, int *rid,
+ rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+{
+ struct thunder_pcie_softc *sc;
+ struct thunder_pcie_ofw_devinfo *di;
+ struct resource_list_entry *rle;
+ int i;
+
+ /* For PCIe devices that do not have FDT nodes, use PCIB method */
+ if ((int)ofw_bus_get_node(child) <= 0) {
+ return (thunder_pcie_alloc_resource(bus, child, type, rid,
+ start, end, count, flags));
+ }
+
+ sc = device_get_softc(bus);
+
+ if ((start == 0UL) && (end == ~0UL)) {
+ if ((di = device_get_ivars(child)) == NULL)
+ return (NULL);
+ if (type == SYS_RES_IOPORT)
+ type = SYS_RES_MEMORY;
+
+ /* Find defaults for this rid */
+ rle = resource_list_find(&di->di_rl, type, *rid);
+ if (rle == NULL)
+ return (NULL);
+
+ start = rle->start;
+ end = rle->end;
+ count = rle->count;
+ }
+
+ if (type == SYS_RES_MEMORY) {
+ /* Remap through ranges property */
+ for (i = 0; i < RANGES_TUPLES_MAX; i++) {
+ if (start >= sc->ranges[i].phys_base && end <
+ sc->ranges[i].pci_base + sc->ranges[i].size) {
+ start -= sc->ranges[i].phys_base;
+ start += sc->ranges[i].pci_base;
+ end -= sc->ranges[i].phys_base;
+ end += sc->ranges[i].pci_base;
+ break;
+ }
+ }
+
+ if (i == RANGES_TUPLES_MAX) {
+ device_printf(bus, "Could not map resource "
+ "%#lx-%#lx\n", start, end);
+ return (NULL);
+ }
+ }
+
+ return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
+ count, flags));
+}
+
+static int
+thunder_pcie_ofw_bus_rel_res(device_t bus, device_t child, int type, int rid,
+ struct resource *res)
+{
+
+ /* For PCIe devices that do not have FDT nodes, use PCIB method */
+ if ((int)ofw_bus_get_node(child) <= 0) {
+ return (thunder_pcie_release_resource(bus,
+ child, type, rid, res));
+ }
+
+ return (bus_generic_release_resource(bus, child, type, rid, res));
+}
+
+/* Helper functions */
+
+static int
+thunder_pcie_ofw_bus_attach(device_t dev)
+{
+ struct thunder_pcie_ofw_devinfo *di;
+ device_t child;
+ phandle_t parent, node;
+ pcell_t addr_cells, size_cells;
+
+ parent = ofw_bus_get_node(dev);
+ if (parent > 0) {
+ get_addr_size_cells(parent, &addr_cells, &size_cells);
+ /* Iterate through all bus subordinates */
+ for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
+ /* Allocate and populate devinfo. */
+ di = malloc(sizeof(*di), M_THUNDER_PCIE, M_WAITOK | M_ZERO);
+ if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node) != 0) {
+ free(di, M_THUNDER_PCIE);
+ continue;
+ }
+
+ /* Initialize and populate resource list. */
+ resource_list_init(&di->di_rl);
+ ofw_bus_reg_to_rl(dev, node, addr_cells, size_cells,
+ &di->di_rl);
+ ofw_bus_intr_to_rl(dev, node, &di->di_rl, NULL);
+
+ /* Add newbus device for this FDT node */
+ child = device_add_child(dev, NULL, -1);
+ if (child == NULL) {
+ resource_list_free(&di->di_rl);
+ ofw_bus_gen_destroy_devinfo(&di->di_dinfo);
+ free(di, M_THUNDER_PCIE);
+ continue;
+ }
+
+ device_set_ivars(child, di);
+ }
+ }
+
+ return (0);
+}
diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h
index f8d19960139e..0c86462376fc 100644
--- a/sys/arm64/include/armreg.h
+++ b/sys/arm64/include/armreg.h
@@ -33,6 +33,8 @@
#ifndef _MACHINE_ARMREG_H_
#define _MACHINE_ARMREG_H_
+#define INSN_SIZE 4
+
#define READ_SPECIALREG(reg) \
({ uint64_t val; \
__asm __volatile("mrs %0, " __STRING(reg) : "=&r" (val)); \
@@ -99,6 +101,7 @@
#define EXCP_SP_ALIGN 0x26 /* SP slignment fault */
#define EXCP_TRAP_FP 0x2c /* Trapped FP exception */
#define EXCP_SERROR 0x2f /* SError interrupt */
+#define EXCP_SOFTSTP_EL0 0x32 /* Software Step, from lower EL */
#define EXCP_SOFTSTP_EL1 0x33 /* Software Step, from same EL */
#define EXCP_WATCHPT_EL1 0x35 /* Watchpoint, from same EL */
#define EXCP_BRK 0x3c /* Breakpoint */
diff --git a/sys/arm64/include/disassem.h b/sys/arm64/include/disassem.h
new file mode 100644
index 000000000000..1a555117a066
--- /dev/null
+++ b/sys/arm64/include/disassem.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2016 Cavium
+ * All rights reserved.
+ *
+ * This software was developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __DISASSEM_H_
+#define __DISASSEM_H_
+
+struct disasm_interface {
+ u_int (*di_readword)(vm_offset_t);
+ void (*di_printaddr)(vm_offset_t);
+ int (*di_printf)(const char *, ...) __printflike(1, 2);
+};
+
+vm_offset_t disasm(const struct disasm_interface *, vm_offset_t, int);
+
+#endif /* __DISASSEM_H_ */
diff --git a/sys/arm64/include/kdb.h b/sys/arm64/include/kdb.h
index e4f4f70a4a71..2f7306ef669b 100644
--- a/sys/arm64/include/kdb.h
+++ b/sys/arm64/include/kdb.h
@@ -43,6 +43,8 @@ void kdb_cpu_set_singlestep(void);
static __inline void
kdb_cpu_sync_icache(unsigned char *addr, size_t size)
{
+
+ cpu_icache_sync_range((vm_offset_t)addr, size);
}
static __inline void
diff --git a/sys/arm64/include/pcb.h b/sys/arm64/include/pcb.h
index 027b60544c38..55dd6e92eb3d 100644
--- a/sys/arm64/include/pcb.h
+++ b/sys/arm64/include/pcb.h
@@ -45,6 +45,10 @@ struct pcb {
/* Fault handler, the error value is passed in x0 */
vm_offset_t pcb_onfault;
+ u_int pcb_flags;
+#define PCB_SINGLE_STEP_SHIFT 0
+#define PCB_SINGLE_STEP (1 << PCB_SINGLE_STEP_SHIFT)
+
/* Place last to simplify the asm to access the rest if the struct */
__uint128_t pcb_vfp[32];
uint32_t pcb_fpcr;
diff --git a/sys/arm64/include/pmap.h b/sys/arm64/include/pmap.h
index e109de2816d8..0faf2e8fc9d9 100644
--- a/sys/arm64/include/pmap.h
+++ b/sys/arm64/include/pmap.h
@@ -121,7 +121,7 @@ extern struct pmap kernel_pmap_store;
#define PMAP_TRYLOCK(pmap) mtx_trylock(&(pmap)->pm_mtx)
#define PMAP_UNLOCK(pmap) mtx_unlock(&(pmap)->pm_mtx)
-#define PHYS_AVAIL_SIZE 10
+#define PHYS_AVAIL_SIZE 32
extern vm_paddr_t phys_avail[];
extern vm_paddr_t dump_avail[];
extern vm_offset_t virtual_avail;
diff --git a/sys/boot/efi/boot1/boot1.c b/sys/boot/efi/boot1/boot1.c
index c326c79d77ad..1161b0a1e58a 100644
--- a/sys/boot/efi/boot1/boot1.c
+++ b/sys/boot/efi/boot1/boot1.c
@@ -50,9 +50,6 @@ static const boot_module_t *boot_modules[] =
void putchar(int c);
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
-static void try_load(const boot_module_t* mod);
-static EFI_STATUS probe_handle(EFI_HANDLE h);
-
EFI_SYSTEM_TABLE *systab;
EFI_BOOT_SERVICES *bs;
static EFI_HANDLE *image;
@@ -85,20 +82,300 @@ Free(void *buf, const char *file __unused, int line __unused)
}
/*
- * This function only returns if it fails to load the kernel. If it
- * succeeds, it simply boots the kernel.
+ * nodes_match returns TRUE if the imgpath isn't NULL and the nodes match,
+ * FALSE otherwise.
*/
-void
-try_load(const boot_module_t *mod)
+static BOOLEAN
+nodes_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
+{
+ int len;
+
+ if (imgpath == NULL || imgpath->Type != devpath->Type ||
+ imgpath->SubType != devpath->SubType)
+ return (FALSE);
+
+ len = DevicePathNodeLength(imgpath);
+ if (len != DevicePathNodeLength(devpath))
+ return (FALSE);
+
+ return (memcmp(imgpath, devpath, (size_t)len) == 0);
+}
+
+/*
+ * device_paths_match returns TRUE if the imgpath isn't NULL and all nodes
+ * in imgpath and devpath match up to their respect occurances of a media
+ * node, FALSE otherwise.
+ */
+static BOOLEAN
+device_paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath)
+{
+
+ if (imgpath == NULL)
+ return (FALSE);
+
+ while (!IsDevicePathEnd(imgpath) && !IsDevicePathEnd(devpath)) {
+ if (IsDevicePathType(imgpath, MEDIA_DEVICE_PATH) &&
+ IsDevicePathType(devpath, MEDIA_DEVICE_PATH))
+ return (TRUE);
+
+ if (!nodes_match(imgpath, devpath))
+ return (FALSE);
+
+ imgpath = NextDevicePathNode(imgpath);
+ devpath = NextDevicePathNode(devpath);
+ }
+
+ return (FALSE);
+}
+
+/*
+ * devpath_last returns the last non-path end node in devpath.
+ */
+static EFI_DEVICE_PATH *
+devpath_last(EFI_DEVICE_PATH *devpath)
+{
+
+ while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
+ devpath = NextDevicePathNode(devpath);
+
+ return (devpath);
+}
+
+/*
+ * devpath_node_str is a basic output method for a devpath node which
+ * only understands a subset of the available sub types.
+ *
+ * If we switch to UEFI 2.x then we should update it to use:
+ * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
+ */
+static int
+devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
+{
+
+ switch (devpath->Type) {
+ case MESSAGING_DEVICE_PATH:
+ switch (devpath->SubType) {
+ case MSG_ATAPI_DP: {
+ ATAPI_DEVICE_PATH *atapi;
+
+ atapi = (ATAPI_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "ata(%s,%s,0x%x)",
+ (atapi->PrimarySecondary == 1) ? "Sec" : "Pri",
+ (atapi->SlaveMaster == 1) ? "Slave" : "Master",
+ atapi->Lun);
+ }
+ case MSG_USB_DP: {
+ USB_DEVICE_PATH *usb;
+
+ usb = (USB_DEVICE_PATH *)devpath;
+ return snprintf(buf, size, "usb(0x%02x,0x%02x)",
+ usb->ParentPortNumber, usb->InterfaceNumber);
+ }
+ case MSG_SCSI_DP: {
+ SCSI_DEVICE_PATH *scsi;
+
+ scsi = (SCSI_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "scsi(0x%02x,0x%02x)",
+ scsi->Pun, scsi->Lun);
+ }
+ case MSG_SATA_DP: {
+ SATA_DEVICE_PATH *sata;
+
+ sata = (SATA_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "sata(0x%x,0x%x,0x%x)",
+ sata->HBAPortNumber, sata->PortMultiplierPortNumber,
+ sata->Lun);
+ }
+ default:
+ return snprintf(buf, size, "msg(0x%02x)",
+ devpath->SubType);
+ }
+ break;
+ case HARDWARE_DEVICE_PATH:
+ switch (devpath->SubType) {
+ case HW_PCI_DP: {
+ PCI_DEVICE_PATH *pci;
+
+ pci = (PCI_DEVICE_PATH *)devpath;
+ return snprintf(buf, size, "pci(0x%02x,0x%02x)",
+ pci->Device, pci->Function);
+ }
+ default:
+ return snprintf(buf, size, "hw(0x%02x)",
+ devpath->SubType);
+ }
+ break;
+ case ACPI_DEVICE_PATH: {
+ ACPI_HID_DEVICE_PATH *acpi;
+
+ acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath;
+ if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+ switch (EISA_ID_TO_NUM(acpi->HID)) {
+ case 0x0a03:
+ return snprintf(buf, size, "pciroot(0x%x)",
+ acpi->UID);
+ case 0x0a08:
+ return snprintf(buf, size, "pcieroot(0x%x)",
+ acpi->UID);
+ case 0x0604:
+ return snprintf(buf, size, "floppy(0x%x)",
+ acpi->UID);
+ case 0x0301:
+ return snprintf(buf, size, "keyboard(0x%x)",
+ acpi->UID);
+ case 0x0501:
+ return snprintf(buf, size, "serial(0x%x)",
+ acpi->UID);
+ case 0x0401:
+ return snprintf(buf, size, "parallelport(0x%x)",
+ acpi->UID);
+ default:
+ return snprintf(buf, size, "acpi(pnp%04x,0x%x)",
+ EISA_ID_TO_NUM(acpi->HID), acpi->UID);
+ }
+ }
+
+ return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID,
+ acpi->UID);
+ }
+ case MEDIA_DEVICE_PATH:
+ switch (devpath->SubType) {
+ case MEDIA_CDROM_DP: {
+ CDROM_DEVICE_PATH *cdrom;
+
+ cdrom = (CDROM_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "cdrom(%x)",
+ cdrom->BootEntry);
+ }
+ case MEDIA_HARDDRIVE_DP: {
+ HARDDRIVE_DEVICE_PATH *hd;
+
+ hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
+ return snprintf(buf, size, "hd(%x)",
+ hd->PartitionNumber);
+ }
+ default:
+ return snprintf(buf, size, "media(0x%02x)",
+ devpath->SubType);
+ }
+ case BBS_DEVICE_PATH:
+ return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType);
+ case END_DEVICE_PATH_TYPE:
+ return (0);
+ }
+
+ return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type,
+ devpath->SubType);
+}
+
+/*
+ * devpath_strlcat appends a text description of devpath to buf but not more
+ * than size - 1 characters followed by NUL-terminator.
+ */
+int
+devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
+{
+ size_t len, used;
+ const char *sep;
+
+ sep = "";
+ used = 0;
+ while (!IsDevicePathEnd(devpath)) {
+ len = snprintf(buf, size - used, "%s", sep);
+ used += len;
+ if (used > size)
+ return (used);
+ buf += len;
+
+ len = devpath_node_str(buf, size - used, devpath);
+ used += len;
+ if (used > size)
+ return (used);
+ buf += len;
+ devpath = NextDevicePathNode(devpath);
+ sep = ":";
+ }
+
+ return (used);
+}
+
+/*
+ * devpath_str is convenience method which returns the text description of
+ * devpath using a static buffer, so it isn't thread safe!
+ */
+char *
+devpath_str(EFI_DEVICE_PATH *devpath)
+{
+ static char buf[256];
+
+ devpath_strlcat(buf, sizeof(buf), devpath);
+
+ return buf;
+}
+
+/*
+ * load_loader attempts to load the loader image data.
+ *
+ * It tries each module and its respective devices, identified by mod->probe,
+ * in order until a successful load occurs at which point it returns EFI_SUCCESS
+ * and EFI_NOT_FOUND otherwise.
+ *
+ * Only devices which have preferred matching the preferred parameter are tried.
+ */
+static EFI_STATUS
+load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp,
+ size_t *bufsize, BOOLEAN preferred)
{
- size_t bufsize, cmdsize;
- void *buf;
+ UINTN i;
+ dev_info_t *dev;
+ const boot_module_t *mod;
+
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] == NULL)
+ continue;
+ mod = boot_modules[i];
+ for (dev = mod->devices(); dev != NULL; dev = dev->next) {
+ if (dev->preferred != preferred)
+ continue;
+
+ if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) ==
+ EFI_SUCCESS) {
+ *devinfop = dev;
+ *modp = mod;
+ return (EFI_SUCCESS);
+ }
+ }
+ }
+
+ return (EFI_NOT_FOUND);
+}
+
+/*
+ * try_boot only returns if it fails to load the loader. If it succeeds
+ * it simply boots, otherwise it returns the status of last EFI call.
+ */
+static EFI_STATUS
+try_boot()
+{
+ size_t bufsize, loadersize, cmdsize;
+ void *buf, *loaderbuf;
char *cmd;
dev_info_t *dev;
+ const boot_module_t *mod;
EFI_HANDLE loaderhandle;
EFI_LOADED_IMAGE *loaded_image;
EFI_STATUS status;
+ status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
+ if (status != EFI_SUCCESS) {
+ status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
+ FALSE);
+ if (status != EFI_SUCCESS) {
+ printf("Failed to load '%s'\n", PATH_LOADER_EFI);
+ return (status);
+ }
+ }
+
/*
* Read in and parse the command line from /boot.config or /boot/config,
* if present. We'll pass it the next stage via a simple ASCII
@@ -111,67 +388,183 @@ try_load(const boot_module_t *mod)
*/
cmd = NULL;
cmdsize = 0;
- status = mod->load(PATH_DOTCONFIG, &dev, &buf, &bufsize);
+ status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize);
if (status == EFI_NOT_FOUND)
- status = mod->load(PATH_CONFIG, &dev, &buf, &bufsize);
+ status = mod->load(PATH_CONFIG, dev, &buf, &bufsize);
if (status == EFI_SUCCESS) {
cmdsize = bufsize + 1;
cmd = malloc(cmdsize);
- if (cmd == NULL) {
- free(buf);
- return;
- }
+ if (cmd == NULL)
+ goto errout;
memcpy(cmd, buf, bufsize);
cmd[bufsize] = '\0';
free(buf);
+ buf = NULL;
}
- status = mod->load(PATH_LOADER_EFI, &dev, &buf, &bufsize);
- if (status == EFI_NOT_FOUND)
- return;
-
- if (status != EFI_SUCCESS) {
- printf("%s failed to load %s (%lu)\n", mod->name,
- PATH_LOADER_EFI, EFI_ERROR_CODE(status));
- return;
- }
-
- if ((status = bs->LoadImage(TRUE, image, dev->devpath, buf, bufsize,
- &loaderhandle)) != EFI_SUCCESS) {
+ if ((status = bs->LoadImage(TRUE, image, devpath_last(dev->devpath),
+ loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) {
printf("Failed to load image provided by %s, size: %zu, (%lu)\n",
mod->name, bufsize, EFI_ERROR_CODE(status));
- return;
+ goto errout;
}
- if (cmd != NULL)
- printf(" command args: %s\n", cmd);
-
if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID,
(VOID**)&loaded_image)) != EFI_SUCCESS) {
printf("Failed to query LoadedImage provided by %s (%lu)\n",
mod->name, EFI_ERROR_CODE(status));
- return;
+ goto errout;
}
+ if (cmd != NULL)
+ printf(" command args: %s\n", cmd);
+
loaded_image->DeviceHandle = dev->devhandle;
loaded_image->LoadOptionsSize = cmdsize;
loaded_image->LoadOptions = cmd;
+ DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
+ DSTALL(1000000);
+ DPRINTF(".");
+ DSTALL(1000000);
+ DPRINTF(".");
+ DSTALL(1000000);
+ DPRINTF(".");
+ DSTALL(1000000);
+ DPRINTF(".");
+ DSTALL(1000000);
+ DPRINTF(".\n");
+
if ((status = bs->StartImage(loaderhandle, NULL, NULL)) !=
EFI_SUCCESS) {
printf("Failed to start image provided by %s (%lu)\n",
mod->name, EFI_ERROR_CODE(status));
- free(cmd);
loaded_image->LoadOptionsSize = 0;
loaded_image->LoadOptions = NULL;
- return;
}
+
+errout:
+ if (cmd != NULL)
+ free(cmd);
+ if (buf != NULL)
+ free(buf);
+ if (loaderbuf != NULL)
+ free(loaderbuf);
+
+ return (status);
+}
+
+/*
+ * probe_handle determines if the passed handle represents a logical partition
+ * if it does it uses each module in order to probe it and if successful it
+ * returns EFI_SUCCESS.
+ */
+static EFI_STATUS
+probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred)
+{
+ dev_info_t *devinfo;
+ EFI_BLOCK_IO *blkio;
+ EFI_DEVICE_PATH *devpath;
+ EFI_STATUS status;
+ UINTN i;
+
+ /* Figure out if we're dealing with an actual partition. */
+ status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
+ if (status == EFI_UNSUPPORTED)
+ return (status);
+
+ if (status != EFI_SUCCESS) {
+ DPRINTF("\nFailed to query DevicePath (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ DPRINTF("probing: %s\n", devpath_str(devpath));
+
+ status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
+ if (status == EFI_UNSUPPORTED)
+ return (status);
+
+ if (status != EFI_SUCCESS) {
+ DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ if (!blkio->Media->LogicalPartition)
+ return (EFI_UNSUPPORTED);
+
+ *preferred = device_paths_match(imgpath, devpath);
+
+ /* Run through each module, see if it can load this partition */
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] == NULL)
+ continue;
+
+ if ((status = bs->AllocatePool(EfiLoaderData,
+ sizeof(*devinfo), (void **)&devinfo)) !=
+ EFI_SUCCESS) {
+ DPRINTF("\nFailed to allocate devinfo (%lu)\n",
+ EFI_ERROR_CODE(status));
+ continue;
+ }
+ devinfo->dev = blkio;
+ devinfo->devpath = devpath;
+ devinfo->devhandle = h;
+ devinfo->devdata = NULL;
+ devinfo->preferred = *preferred;
+ devinfo->next = NULL;
+
+ status = boot_modules[i]->probe(devinfo);
+ if (status == EFI_SUCCESS)
+ return (EFI_SUCCESS);
+ (void)bs->FreePool(devinfo);
+ }
+
+ return (EFI_UNSUPPORTED);
+}
+
+/*
+ * probe_handle_status calls probe_handle and outputs the returned status
+ * of the call.
+ */
+static void
+probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath)
+{
+ EFI_STATUS status;
+ BOOLEAN preferred;
+
+ status = probe_handle(h, imgpath, &preferred);
+
+ DPRINTF("probe: ");
+ switch (status) {
+ case EFI_UNSUPPORTED:
+ printf(".");
+ DPRINTF(" not supported\n");
+ break;
+ case EFI_SUCCESS:
+ if (preferred) {
+ printf("%c", '*');
+ DPRINTF(" supported (preferred)\n");
+ } else {
+ printf("%c", '+');
+ DPRINTF(" supported\n");
+ }
+ break;
+ default:
+ printf("x");
+ DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status));
+ break;
+ }
+ DSTALL(500000);
}
EFI_STATUS
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
{
EFI_HANDLE *handles;
+ EFI_LOADED_IMAGE *img;
+ EFI_DEVICE_PATH *imgpath;
EFI_STATUS status;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
@@ -254,20 +647,22 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
/* Scan all partitions, probing with all modules. */
nhandles = hsize / sizeof(*handles);
printf(" Probing %zu block devices...", nhandles);
- for (i = 0; i < nhandles; i++) {
- status = probe_handle(handles[i]);
- switch (status) {
- case EFI_UNSUPPORTED:
- printf(".");
- break;
- case EFI_SUCCESS:
- printf("+");
- break;
- default:
- printf("x");
- break;
- }
+ DPRINTF("\n");
+
+ /* Determine the devpath of our image so we can prefer it. */
+ status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img);
+ imgpath = NULL;
+ if (status == EFI_SUCCESS) {
+ status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID,
+ (void **)&imgpath);
+ if (status != EFI_SUCCESS)
+ DPRINTF("Failed to get image DevicePath (%lu)\n",
+ EFI_ERROR_CODE(status));
+ DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath));
}
+
+ for (i = 0; i < nhandles; i++)
+ probe_handle_status(handles[i], imgpath);
printf(" done\n");
/* Status summary. */
@@ -278,78 +673,15 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
}
}
- /* Select a partition to boot by trying each module in order. */
- for (i = 0; i < NUM_BOOT_MODULES; i++)
- if (boot_modules[i] != NULL)
- try_load(boot_modules[i]);
+ try_boot();
/* If we get here, we're out of luck... */
panic("No bootable partitions found!");
}
-static EFI_STATUS
-probe_handle(EFI_HANDLE h)
-{
- dev_info_t *devinfo;
- EFI_BLOCK_IO *blkio;
- EFI_DEVICE_PATH *devpath;
- EFI_STATUS status;
- UINTN i;
-
- /* Figure out if we're dealing with an actual partition. */
- status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
- if (status == EFI_UNSUPPORTED)
- return (status);
-
- if (status != EFI_SUCCESS) {
- DPRINTF("\nFailed to query DevicePath (%lu)\n",
- EFI_ERROR_CODE(status));
- return (status);
- }
-
- while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
- devpath = NextDevicePathNode(devpath);
-
- status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
- if (status == EFI_UNSUPPORTED)
- return (status);
-
- if (status != EFI_SUCCESS) {
- DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
- EFI_ERROR_CODE(status));
- return (status);
- }
-
- if (!blkio->Media->LogicalPartition)
- return (EFI_UNSUPPORTED);
-
- /* Run through each module, see if it can load this partition */
- for (i = 0; i < NUM_BOOT_MODULES; i++) {
- if (boot_modules[i] == NULL)
- continue;
-
- if ((status = bs->AllocatePool(EfiLoaderData,
- sizeof(*devinfo), (void **)&devinfo)) !=
- EFI_SUCCESS) {
- DPRINTF("\nFailed to allocate devinfo (%lu)\n",
- EFI_ERROR_CODE(status));
- continue;
- }
- devinfo->dev = blkio;
- devinfo->devpath = devpath;
- devinfo->devhandle = h;
- devinfo->devdata = NULL;
- devinfo->next = NULL;
-
- status = boot_modules[i]->probe(devinfo);
- if (status == EFI_SUCCESS)
- return (EFI_SUCCESS);
- (void)bs->FreePool(devinfo);
- }
-
- return (EFI_UNSUPPORTED);
-}
-
+/*
+ * add_device adds a device to the passed devinfo list.
+ */
void
add_device(dev_info_t **devinfop, dev_info_t *devinfo)
{
diff --git a/sys/boot/efi/boot1/boot_module.h b/sys/boot/efi/boot1/boot_module.h
index 2c158f6dd821..296d5a67a10b 100644
--- a/sys/boot/efi/boot1/boot_module.h
+++ b/sys/boot/efi/boot1/boot_module.h
@@ -36,9 +36,11 @@
#include <eficonsctl.h>
#ifdef EFI_DEBUG
-#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
+#define DPRINTF(fmt, args...) printf(fmt, ##args)
+#define DSTALL(d) bs->Stall(d)
#else
#define DPRINTF(fmt, ...) {}
+#define DSTALL(d) {}
#endif
/* EFI device info */
@@ -48,6 +50,7 @@ typedef struct dev_info
EFI_DEVICE_PATH *devpath;
EFI_HANDLE *devhandle;
void *devdata;
+ BOOLEAN preferred;
struct dev_info *next;
} dev_info_t;
@@ -75,19 +78,21 @@ typedef struct boot_module_t
/*
* load should select the best out of a set of devices that probe
- * indicated were loadable and load it.
+ * indicated were loadable and load the specified file.
*
* Return codes:
* EFI_SUCCESS = The module can handle the device.
* EFI_NOT_FOUND = The module can not handle the device.
* Other = The module encountered an error.
*/
- EFI_STATUS (*load)(const char *loader_path, dev_info_t **devinfo,
+ EFI_STATUS (*load)(const char *filepath, dev_info_t *devinfo,
void **buf, size_t *bufsize);
/* status outputs information about the probed devices. */
void (*status)();
+ /* valid devices as found by probe. */
+ dev_info_t *(*devices)();
} boot_module_t;
/* Standard boot modules. */
@@ -107,4 +112,6 @@ extern int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
extern EFI_SYSTEM_TABLE *systab;
extern EFI_BOOT_SERVICES *bs;
+extern int devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath);
+extern char *devpath_str(EFI_DEVICE_PATH *devpath);
#endif
diff --git a/sys/boot/efi/boot1/ufs_module.c b/sys/boot/efi/boot1/ufs_module.c
index 07c7152f342c..63087ea22fa7 100644
--- a/sys/boot/efi/boot1/ufs_module.c
+++ b/sys/boot/efi/boot1/ufs_module.c
@@ -93,7 +93,7 @@ probe(dev_info_t* dev)
}
static EFI_STATUS
-try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize)
+load(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize)
{
ufs_ino_t ino;
EFI_STATUS status;
@@ -101,59 +101,46 @@ try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize)
ssize_t read;
void *buf;
- if (init_dev(dev) < 0)
+ DPRINTF("Loading '%s' from %s\n", filepath, devpath_str(dev->devpath));
+
+ if (init_dev(dev) < 0) {
+ DPRINTF("Failed to init device\n");
return (EFI_UNSUPPORTED);
+ }
- if ((ino = lookup(loader_path)) == 0)
+ if ((ino = lookup(filepath)) == 0) {
+ DPRINTF("Failed to lookup '%s' (file not found?)\n", filepath);
return (EFI_NOT_FOUND);
+ }
if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) {
- printf("Failed to read size of '%s' ino: %d\n", loader_path,
- ino);
+ printf("Failed to read size of '%s' ino: %d\n", filepath, ino);
return (EFI_INVALID_PARAMETER);
}
if ((status = bs->AllocatePool(EfiLoaderData, size, &buf)) !=
EFI_SUCCESS) {
- printf("Failed to allocate read buffer (%lu)\n",
- EFI_ERROR_CODE(status));
+ printf("Failed to allocate read buffer %zu for '%s' (%lu)\n",
+ size, filepath, EFI_ERROR_CODE(status));
return (status);
}
read = fsread(ino, buf, size);
if ((size_t)read != size) {
- printf("Failed to read '%s' (%zd != %zu)\n", loader_path, read,
+ printf("Failed to read '%s' (%zd != %zu)\n", filepath, read,
size);
(void)bs->FreePool(buf);
return (EFI_INVALID_PARAMETER);
}
+ DPRINTF("Load complete\n");
+
*bufp = buf;
*bufsize = size;
return (EFI_SUCCESS);
}
-static EFI_STATUS
-load(const char *loader_path, dev_info_t **devinfop, void **buf,
- size_t *bufsize)
-{
- dev_info_t *dev;
- EFI_STATUS status;
-
- for (dev = devices; dev != NULL; dev = dev->next) {
- status = try_load(dev, loader_path, buf, bufsize);
- if (status == EFI_SUCCESS) {
- *devinfop = dev;
- return (EFI_SUCCESS);
- } else if (status != EFI_NOT_FOUND) {
- return (status);
- }
- }
-
- return (EFI_NOT_FOUND);
-}
-
static void
status()
{
@@ -176,10 +163,18 @@ status()
}
}
+static dev_info_t *
+_devices()
+{
+
+ return (devices);
+}
+
const boot_module_t ufs_module =
{
.name = "UFS",
.probe = probe,
.load = load,
- .status = status
+ .status = status,
+ .devices = _devices
};
diff --git a/sys/boot/efi/boot1/zfs_module.c b/sys/boot/efi/boot1/zfs_module.c
index 96eec332f16a..4e2c5c4681c1 100644
--- a/sys/boot/efi/boot1/zfs_module.c
+++ b/sys/boot/efi/boot1/zfs_module.c
@@ -91,7 +91,7 @@ probe(dev_info_t *dev)
}
static EFI_STATUS
-try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufsize)
+load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize)
{
spa_t *spa;
struct zfsmount zfsmount;
@@ -102,32 +102,41 @@ try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufs
EFI_STATUS status;
spa = devinfo->devdata;
- if (zfs_spa_init(spa) != 0) {
- /* Init failed, don't report this loudly. */
+
+ DPRINTF("load: '%s' spa: '%s', devpath: %s\n", filepath, spa->spa_name,
+ devpath_str(devinfo->devpath));
+
+ if ((err = zfs_spa_init(spa)) != 0) {
+ DPRINTF("Failed to load pool '%s' (%d)\n", spa->spa_name, err);
return (EFI_NOT_FOUND);
}
- if (zfs_mount(spa, 0, &zfsmount) != 0) {
- /* Mount failed, don't report this loudly. */
+ if ((err = zfs_mount(spa, 0, &zfsmount)) != 0) {
+ DPRINTF("Failed to mount pool '%s' (%d)\n", spa->spa_name, err);
return (EFI_NOT_FOUND);
}
- if ((err = zfs_lookup(&zfsmount, loader_path, &dn)) != 0) {
- printf("Failed to lookup %s on pool %s (%d)\n", loader_path,
+ if ((err = zfs_lookup(&zfsmount, filepath, &dn)) != 0) {
+ if (err == ENOENT) {
+ DPRINTF("Failed to find '%s' on pool '%s' (%d)\n",
+ filepath, spa->spa_name, err);
+ return (EFI_NOT_FOUND);
+ }
+ printf("Failed to lookup '%s' on pool '%s' (%d)\n", filepath,
spa->spa_name, err);
return (EFI_INVALID_PARAMETER);
}
if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) {
- printf("Failed to lookup %s on pool %s (%d)\n", loader_path,
+ printf("Failed to stat '%s' on pool '%s' (%d)\n", filepath,
spa->spa_name, err);
return (EFI_INVALID_PARAMETER);
}
if ((status = bs->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf))
!= EFI_SUCCESS) {
- printf("Failed to allocate load buffer for pool %s (%lu)\n",
- spa->spa_name, EFI_ERROR_CODE(status));
+ printf("Failed to allocate load buffer %zu for pool '%s' for '%s' "
+ "(%lu)\n", st.st_size, spa->spa_name, filepath, EFI_ERROR_CODE(status));
return (EFI_INVALID_PARAMETER);
}
@@ -144,26 +153,6 @@ try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufs
return (EFI_SUCCESS);
}
-static EFI_STATUS
-load(const char *loader_path, dev_info_t **devinfop, void **bufp,
- size_t *bufsize)
-{
- dev_info_t *devinfo;
- EFI_STATUS status;
-
- for (devinfo = devices; devinfo != NULL; devinfo = devinfo->next) {
- status = try_load(devinfo, loader_path, bufp, bufsize);
- if (status == EFI_SUCCESS) {
- *devinfop = devinfo;
- return (EFI_SUCCESS);
- } else if (status != EFI_NOT_FOUND) {
- return (status);
- }
- }
-
- return (EFI_NOT_FOUND);
-}
-
static void
status()
{
@@ -189,11 +178,19 @@ init()
zfs_init();
}
+static dev_info_t *
+_devices()
+{
+
+ return (devices);
+}
+
const boot_module_t zfs_module =
{
.name = "ZFS",
.init = init,
.probe = probe,
.load = load,
- .status = status
+ .status = status,
+ .devices = _devices
};
diff --git a/sys/boot/efi/include/efidevp.h b/sys/boot/efi/include/efidevp.h
index f0f49efc3fff..dda79de7af13 100644
--- a/sys/boot/efi/include/efidevp.h
+++ b/sys/boot/efi/include/efidevp.h
@@ -40,9 +40,7 @@ typedef struct _EFI_DEVICE_PATH {
#define EFI_DP_TYPE_MASK 0x7F
#define EFI_DP_TYPE_UNPACKED 0x80
-//#define END_DEVICE_PATH_TYPE 0xff
#define END_DEVICE_PATH_TYPE 0x7f
-//#define END_DEVICE_PATH_TYPE_UNPACKED 0x7f
#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01
@@ -56,8 +54,8 @@ typedef struct _EFI_DEVICE_PATH {
#define DevicePathSubType(a) ( (a)->SubType )
#define DevicePathNodeLength(a) ( ((a)->Length[0]) | ((a)->Length[1] << 8) )
#define NextDevicePathNode(a) ( (EFI_DEVICE_PATH *) ( ((UINT8 *) (a)) + DevicePathNodeLength(a)))
-//#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE_UNPACKED )
-#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE )
+#define IsDevicePathType(a, t) ( DevicePathType(a) == t )
+#define IsDevicePathEndType(a) IsDevicePathType(a, END_DEVICE_PATH_TYPE)
#define IsDevicePathEndSubType(a) ( (a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE )
#define IsDevicePathEnd(a) ( IsDevicePathEndType(a) && IsDevicePathEndSubType(a) )
#define IsDevicePathUnpacked(a) ( (a)->Type & EFI_DP_TYPE_UNPACKED )
@@ -285,6 +283,13 @@ typedef struct _UART_DEVICE_PATH {
#define DEVICE_PATH_MESSAGING_VT_UTF8 \
{ 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88} }
+#define MSG_SATA_DP 0x12
+typedef struct _SATA_DEVICE_PATH {
+ EFI_DEVICE_PATH Header;
+ UINT16 HBAPortNumber;
+ UINT16 PortMultiplierPortNumber;
+ UINT16 Lun;
+} SATA_DEVICE_PATH;
#define MEDIA_DEVICE_PATH 0x04
diff --git a/sys/boot/efi/libefi/efinet.c b/sys/boot/efi/libefi/efinet.c
index f1e614331999..b7888aaed5fc 100644
--- a/sys/boot/efi/libefi/efinet.c
+++ b/sys/boot/efi/libefi/efinet.c
@@ -184,11 +184,16 @@ efinet_init(struct iodesc *desc, void *machdep_hint)
EFI_HANDLE h;
EFI_STATUS status;
+ if (nif->nif_driver->netif_ifs[nif->nif_unit].dif_unit < 0) {
+ printf("Invalid network interface %d\n", nif->nif_unit);
+ return;
+ }
+
h = nif->nif_driver->netif_ifs[nif->nif_unit].dif_private;
status = BS->HandleProtocol(h, &sn_guid, (VOID **)&nif->nif_devdata);
if (status != EFI_SUCCESS) {
- printf("net%d: cannot start interface (status=%ld)\n",
- nif->nif_unit, (long)status);
+ printf("net%d: cannot start interface (status=%lu)\n",
+ nif->nif_unit, EFI_ERROR_CODE(status));
return;
}
@@ -288,11 +293,30 @@ efinet_dev_init()
stats = calloc(nifs, sizeof(struct netif_stats));
for (i = 0; i < nifs; i++) {
+ EFI_SIMPLE_NETWORK *net;
+ EFI_HANDLE h;
+
dif = &efinetif.netif_ifs[i];
+ dif->dif_unit = -1;
+
+ h = efi_find_handle(&efinet_dev, i);
+
+ /*
+ * Open the network device in exclusive mode. Without this
+ * we will be racing with the UEFI network stack. It will
+ * pull packets off the network leading to lost packets.
+ */
+ status = BS->OpenProtocol(h, &sn_guid, (void **)&net,
+ IH, 0, EFI_OPEN_PROTOCOL_EXCLUSIVE);
+ if (status != EFI_SUCCESS) {
+ printf("Unable to open network interface %d for "
+ "exclusive access\n", i);
+ }
+
dif->dif_unit = i;
dif->dif_nsel = 1;
dif->dif_stats = &stats[i];
- dif->dif_private = efi_find_handle(&efinet_dev, i);
+ dif->dif_private = h;
}
return (0);
diff --git a/sys/boot/fdt/dts/riscv/spike.dts b/sys/boot/fdt/dts/riscv/spike.dts
new file mode 100644
index 000000000000..c5013340d538
--- /dev/null
+++ b/sys/boot/fdt/dts/riscv/spike.dts
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/dts-v1/;
+
+/ {
+ model = "UC Berkeley Spike Simulator RV64I";
+ compatible = "riscv,rv64i";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interrupt-cells = <1>;
+
+ aliases {
+ console0 = &console0;
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x8000000>; /* 128MB at 0x0 */
+ };
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ compatible = "simple-bus";
+ ranges;
+
+ pic0: pic@0 {
+ compatible = "riscv,pic";
+ interrupt-controller;
+ };
+
+ timer0: timer@0 {
+ compatible = "riscv,timer";
+ interrupts = < 1 >;
+ interrupt-parent = < &pic0 >;
+ clock-frequency = < 1000000 >;
+ };
+
+ htif0: htif@0 {
+ compatible = "riscv,htif";
+ interrupts = < 0 >;
+ interrupt-parent = < &pic0 >;
+
+ console0: console@0 {
+ compatible = "htif,console";
+ status = "okay";
+ };
+ };
+ };
+
+ chosen {
+ bootargs = "-v";
+ stdin = "console0";
+ stdout = "console0";
+ };
+};
diff --git a/sys/boot/ficl/riscv/sysdep.c b/sys/boot/ficl/riscv/sysdep.c
new file mode 100644
index 000000000000..ad38660843cd
--- /dev/null
+++ b/sys/boot/ficl/riscv/sysdep.c
@@ -0,0 +1,99 @@
+/*******************************************************************
+** s y s d e p . c
+** Forth Inspired Command Language
+** Author: John Sadler (john_sadler@alum.mit.edu)
+** Created: 16 Oct 1997
+** Implementations of FICL external interface functions...
+**
+*******************************************************************/
+
+/* $FreeBSD$ */
+
+#ifdef TESTMAIN
+#include <stdio.h>
+#include <stdlib.h>
+#else
+#include <stand.h>
+#endif
+#include "ficl.h"
+
+/*
+******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith
+*/
+
+#if PORTABLE_LONGMULDIV == 0
+DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y)
+{
+ DPUNS q;
+ u_int64_t qx;
+
+ qx = (u_int64_t)x * (u_int64_t) y;
+
+ q.hi = (u_int32_t)( qx >> 32 );
+ q.lo = (u_int32_t)( qx & 0xFFFFFFFFL);
+
+ return q;
+}
+
+UNSQR ficlLongDiv(DPUNS q, FICL_UNS y)
+{
+ UNSQR result;
+ u_int64_t qx, qh;
+
+ qh = q.hi;
+ qx = (qh << 32) | q.lo;
+
+ result.quot = qx / y;
+ result.rem = qx % y;
+
+ return result;
+}
+#endif
+
+void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline)
+{
+ IGNORE(pVM);
+
+ while(*msg != 0)
+ putchar(*(msg++));
+ if (fNewline)
+ putchar('\n');
+
+ return;
+}
+
+void *ficlMalloc (size_t size)
+{
+ return malloc(size);
+}
+
+void *ficlRealloc (void *p, size_t size)
+{
+ return realloc(p, size);
+}
+
+void ficlFree (void *p)
+{
+ free(p);
+}
+
+
+/*
+** Stub function for dictionary access control - does nothing
+** by default, user can redefine to guarantee exclusive dict
+** access to a single thread for updates. All dict update code
+** is guaranteed to be bracketed as follows:
+** ficlLockDictionary(TRUE);
+** <code that updates dictionary>
+** ficlLockDictionary(FALSE);
+**
+** Returns zero if successful, nonzero if unable to acquire lock
+** befor timeout (optional - could also block forever)
+*/
+#if FICL_MULTITHREAD
+int ficlLockDictionary(short fLock)
+{
+ IGNORE(fLock);
+ return 0;
+}
+#endif /* FICL_MULTITHREAD */
diff --git a/sys/boot/ficl/riscv/sysdep.h b/sys/boot/ficl/riscv/sysdep.h
new file mode 100644
index 000000000000..3726b9ef838f
--- /dev/null
+++ b/sys/boot/ficl/riscv/sysdep.h
@@ -0,0 +1,411 @@
+/*******************************************************************
+ s y s d e p . h
+** Forth Inspired Command Language
+** Author: John Sadler (john_sadler@alum.mit.edu)
+** Created: 16 Oct 1997
+** Ficl system dependent types and prototypes...
+**
+** Note: Ficl also depends on the use of "assert" when
+** FICL_ROBUST is enabled. This may require some consideration
+** in firmware systems since assert often
+** assumes stderr/stdout.
+** $Id: sysdep.h,v 1.6 2001-04-26 21:41:55-07 jsadler Exp jsadler $
+*******************************************************************/
+/*
+** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
+** All rights reserved.
+**
+** Get the latest Ficl release at http://ficl.sourceforge.net
+**
+** L I C E N S E and D I S C L A I M E R
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+**
+** I am interested in hearing from anyone who uses ficl. If you have
+** a problem, a success story, a defect, an enhancement request, or
+** if you would like to contribute to the ficl release, please send
+** contact me by email at the address above.
+**
+** $Id: sysdep.h,v 1.6 2001-04-26 21:41:55-07 jsadler Exp jsadler $
+** $FreeBSD$
+*/
+
+#if !defined (__SYSDEP_H__)
+#define __SYSDEP_H__
+
+#include <sys/types.h>
+
+#include <stddef.h> /* size_t, NULL */
+#include <setjmp.h>
+#include <assert.h>
+
+#if !defined IGNORE /* Macro to silence unused param warnings */
+#define IGNORE(x) (void)(x)
+#endif
+
+/*
+** TRUE and FALSE for C boolean operations, and
+** portable 32 bit types for CELLs
+**
+*/
+#if !defined TRUE
+#define TRUE 1
+#endif
+#if !defined FALSE
+#define FALSE 0
+#endif
+
+
+/*
+** System dependent data type declarations...
+*/
+#if !defined INT32
+#define INT32 int
+#endif
+
+#if !defined UNS32
+#define UNS32 unsigned int
+#endif
+
+#if !defined UNS16
+#define UNS16 unsigned short
+#endif
+
+#if !defined UNS8
+#define UNS8 unsigned char
+#endif
+
+#if !defined NULL
+#define NULL ((void *)0)
+#endif
+
+/*
+** FICL_UNS and FICL_INT must have the same size as a void* on
+** the target system. A CELL is a union of void*, FICL_UNS, and
+** FICL_INT.
+** (11/2000: same for FICL_FLOAT)
+*/
+#if !defined FICL_INT
+#define FICL_INT long
+#endif
+
+#if !defined FICL_UNS
+#define FICL_UNS unsigned long
+#endif
+
+#if !defined FICL_FLOAT
+#define FICL_FLOAT float
+#endif
+
+/*
+** Ficl presently supports values of 32 and 64 for BITS_PER_CELL
+*/
+#if !defined BITS_PER_CELL
+#define BITS_PER_CELL 64
+#endif
+
+#if ((BITS_PER_CELL != 32) && (BITS_PER_CELL != 64))
+ Error!
+#endif
+
+typedef struct
+{
+ FICL_UNS hi;
+ FICL_UNS lo;
+} DPUNS;
+
+typedef struct
+{
+ FICL_UNS quot;
+ FICL_UNS rem;
+} UNSQR;
+
+typedef struct
+{
+ FICL_INT hi;
+ FICL_INT lo;
+} DPINT;
+
+typedef struct
+{
+ FICL_INT quot;
+ FICL_INT rem;
+} INTQR;
+
+
+/*
+** B U I L D C O N T R O L S
+*/
+
+#if !defined (FICL_MINIMAL)
+#define FICL_MINIMAL 0
+#endif
+#if (FICL_MINIMAL)
+#define FICL_WANT_SOFTWORDS 0
+#define FICL_WANT_FLOAT 0
+#define FICL_WANT_USER 0
+#define FICL_WANT_LOCALS 0
+#define FICL_WANT_DEBUGGER 0
+#define FICL_WANT_OOP 0
+#define FICL_PLATFORM_EXTEND 0
+#define FICL_MULTITHREAD 0
+#define FICL_ROBUST 0
+#define FICL_EXTENDED_PREFIX 0
+#endif
+
+/*
+** FICL_PLATFORM_EXTEND
+** Includes words defined in ficlCompilePlatform
+*/
+#if !defined (FICL_PLATFORM_EXTEND)
+#define FICL_PLATFORM_EXTEND 1
+#endif
+
+/*
+** FICL_WANT_FLOAT
+** Includes a floating point stack for the VM, and words to do float operations.
+** Contributed by Guy Carver
+*/
+#if !defined (FICL_WANT_FLOAT)
+#define FICL_WANT_FLOAT 0
+#endif
+
+/*
+** FICL_WANT_DEBUGGER
+** Inludes a simple source level debugger
+*/
+#if !defined (FICL_WANT_DEBUGGER)
+#define FICL_WANT_DEBUGGER 1
+#endif
+
+/*
+** User variables: per-instance variables bound to the VM.
+** Kinda like thread-local storage. Could be implemented in a
+** VM private dictionary, but I've chosen the lower overhead
+** approach of an array of CELLs instead.
+*/
+#if !defined FICL_WANT_USER
+#define FICL_WANT_USER 1
+#endif
+
+#if !defined FICL_USER_CELLS
+#define FICL_USER_CELLS 16
+#endif
+
+/*
+** FICL_WANT_LOCALS controls the creation of the LOCALS wordset and
+** a private dictionary for local variable compilation.
+*/
+#if !defined FICL_WANT_LOCALS
+#define FICL_WANT_LOCALS 1
+#endif
+
+/* Max number of local variables per definition */
+#if !defined FICL_MAX_LOCALS
+#define FICL_MAX_LOCALS 16
+#endif
+
+/*
+** FICL_WANT_OOP
+** Inludes object oriented programming support (in softwords)
+** OOP support requires locals and user variables!
+*/
+#if !(FICL_WANT_LOCALS) || !(FICL_WANT_USER)
+#if !defined (FICL_WANT_OOP)
+#define FICL_WANT_OOP 0
+#endif
+#endif
+
+#if !defined (FICL_WANT_OOP)
+#define FICL_WANT_OOP 1
+#endif
+
+/*
+** FICL_WANT_SOFTWORDS
+** Controls inclusion of all softwords in softcore.c
+*/
+#if !defined (FICL_WANT_SOFTWORDS)
+#define FICL_WANT_SOFTWORDS 1
+#endif
+
+/*
+** FICL_MULTITHREAD enables dictionary mutual exclusion
+** wia the ficlLockDictionary system dependent function.
+** Note: this implementation is experimental and poorly
+** tested. Further, it's unnecessary unless you really
+** intend to have multiple SESSIONS (poor choice of name
+** on my part) - that is, threads that modify the dictionary
+** at the same time.
+*/
+#if !defined FICL_MULTITHREAD
+#define FICL_MULTITHREAD 0
+#endif
+
+/*
+** PORTABLE_LONGMULDIV causes ficlLongMul and ficlLongDiv to be
+** defined in C in sysdep.c. Use this if you cannot easily
+** generate an inline asm definition
+*/
+#if !defined (PORTABLE_LONGMULDIV)
+#define PORTABLE_LONGMULDIV 0
+#endif
+
+/*
+** INLINE_INNER_LOOP causes the inner interpreter to be inline code
+** instead of a function call. This is mainly because MS VC++ 5
+** chokes with an internal compiler error on the function version.
+** in release mode. Sheesh.
+*/
+#if !defined INLINE_INNER_LOOP
+#if defined _DEBUG
+#define INLINE_INNER_LOOP 0
+#else
+#define INLINE_INNER_LOOP 1
+#endif
+#endif
+
+/*
+** FICL_ROBUST enables bounds checking of stacks and the dictionary.
+** This will detect stack over and underflows and dictionary overflows.
+** Any exceptional condition will result in an assertion failure.
+** (As generated by the ANSI assert macro)
+** FICL_ROBUST == 1 --> stack checking in the outer interpreter
+** FICL_ROBUST == 2 also enables checking in many primitives
+*/
+
+#if !defined FICL_ROBUST
+#define FICL_ROBUST 2
+#endif
+
+/*
+** FICL_DEFAULT_STACK Specifies the default size (in CELLs) of
+** a new virtual machine's stacks, unless overridden at
+** create time.
+*/
+#if !defined FICL_DEFAULT_STACK
+#define FICL_DEFAULT_STACK 128
+#endif
+
+/*
+** FICL_DEFAULT_DICT specifies the number of CELLs to allocate
+** for the system dictionary by default. The value
+** can be overridden at startup time as well.
+** FICL_DEFAULT_ENV specifies the number of cells to allot
+** for the environment-query dictionary.
+*/
+#if !defined FICL_DEFAULT_DICT
+#define FICL_DEFAULT_DICT 12288
+#endif
+
+#if !defined FICL_DEFAULT_ENV
+#define FICL_DEFAULT_ENV 260
+#endif
+
+/*
+** FICL_DEFAULT_VOCS specifies the maximum number of wordlists in
+** the dictionary search order. See Forth DPANS sec 16.3.3
+** (file://dpans16.htm#16.3.3)
+*/
+#if !defined FICL_DEFAULT_VOCS
+#define FICL_DEFAULT_VOCS 16
+#endif
+
+/*
+** FICL_MAX_PARSE_STEPS controls the size of an array in the FICL_SYSTEM structure
+** that stores pointers to parser extension functions. I would never expect to have
+** more than 8 of these, so that's the default limit. Too many of these functions
+** will probably exact a nasty performance penalty.
+*/
+#if !defined FICL_MAX_PARSE_STEPS
+#define FICL_MAX_PARSE_STEPS 8
+#endif
+
+/*
+** FICL_EXTENDED_PREFIX enables a bunch of extra prefixes in prefix.c and prefix.fr (if
+** included as part of softcore.c)
+*/
+#if !defined FICL_EXTENDED_PREFIX
+#define FICL_EXTENDED_PREFIX 0
+#endif
+
+/*
+** FICL_ALIGN is the power of two to which the dictionary
+** pointer address must be aligned. This value is usually
+** either 1 or 2, depending on the memory architecture
+** of the target system; 2 is safe on any 16 or 32 bit
+** machine. 3 would be appropriate for a 64 bit machine.
+*/
+#if !defined FICL_ALIGN
+#define FICL_ALIGN 3
+#define FICL_ALIGN_ADD ((1 << FICL_ALIGN) - 1)
+#endif
+
+/*
+** System dependent routines --
+** edit the implementations in sysdep.c to be compatible
+** with your runtime environment...
+** ficlTextOut sends a NULL terminated string to the
+** default output device - used for system error messages
+** ficlMalloc and ficlFree have the same semantics as malloc and free
+** in standard C
+** ficlLongMul multiplies two UNS32s and returns a 64 bit unsigned
+** product
+** ficlLongDiv divides an UNS64 by an UNS32 and returns UNS32 quotient
+** and remainder
+*/
+struct vm;
+void ficlTextOut(struct vm *pVM, char *msg, int fNewline);
+void *ficlMalloc (size_t size);
+void ficlFree (void *p);
+void *ficlRealloc(void *p, size_t size);
+/*
+** Stub function for dictionary access control - does nothing
+** by default, user can redefine to guarantee exclusive dict
+** access to a single thread for updates. All dict update code
+** must be bracketed as follows:
+** ficlLockDictionary(TRUE);
+** <code that updates dictionary>
+** ficlLockDictionary(FALSE);
+**
+** Returns zero if successful, nonzero if unable to acquire lock
+** before timeout (optional - could also block forever)
+**
+** NOTE: this function must be implemented with lock counting
+** semantics: nested calls must behave properly.
+*/
+#if FICL_MULTITHREAD
+int ficlLockDictionary(short fLock);
+#else
+#define ficlLockDictionary(x) 0 /* ignore */
+#endif
+
+/*
+** 64 bit integer math support routines: multiply two UNS32s
+** to get a 64 bit product, & divide the product by an UNS32
+** to get an UNS32 quotient and remainder. Much easier in asm
+** on a 32 bit CPU than in C, which usually doesn't support
+** the double length result (but it should).
+*/
+DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y);
+UNSQR ficlLongDiv(DPUNS q, FICL_UNS y);
+
+#endif /*__SYSDEP_H__*/
diff --git a/sys/cam/ata/ata_all.c b/sys/cam/ata/ata_all.c
index d836e42d59d7..d5220e874c78 100644
--- a/sys/cam/ata/ata_all.c
+++ b/sys/cam/ata/ata_all.c
@@ -75,13 +75,18 @@ ata_op_string(struct ata_cmd *cmd)
if (cmd->control & 0x04)
return ("SOFT_RESET");
switch (cmd->command) {
- case 0x00: return ("NOP");
+ case 0x00:
+ switch (cmd->features) {
+ case 0x00: return ("NOP FLUSHQUEUE");
+ case 0x01: return ("NOP AUTOPOLL");
+ }
+ return ("NOP");
case 0x03: return ("CFA_REQUEST_EXTENDED_ERROR");
case 0x06:
switch (cmd->features) {
- case 0x01: return ("DSM TRIM");
- }
- return "DSM";
+ case 0x01: return ("DSM TRIM");
+ }
+ return "DSM";
case 0x08: return ("DEVICE_RESET");
case 0x20: return ("READ");
case 0x24: return ("READ48");
@@ -105,6 +110,12 @@ ata_op_string(struct ata_cmd *cmd)
case 0x3f: return ("WRITE_LOG_EXT");
case 0x40: return ("READ_VERIFY");
case 0x42: return ("READ_VERIFY48");
+ case 0x45:
+ switch (cmd->features) {
+ case 0x55: return ("WRITE_UNCORRECTABLE48 PSEUDO");
+ case 0xaa: return ("WRITE_UNCORRECTABLE48 FLAGGED");
+ }
+ return "WRITE_UNCORRECTABLE48";
case 0x51: return ("CONFIGURE_STREAM");
case 0x60: return ("READ_FPDMA_QUEUED");
case 0x61: return ("WRITE_FPDMA_QUEUED");
@@ -128,7 +139,18 @@ ata_op_string(struct ata_cmd *cmd)
case 0xa0: return ("PACKET");
case 0xa1: return ("ATAPI_IDENTIFY");
case 0xa2: return ("SERVICE");
- case 0xb0: return ("SMART");
+ case 0xb0:
+ switch(cmd->features) {
+ case 0xd0: return ("SMART READ ATTR VALUES");
+ case 0xd1: return ("SMART READ ATTR THRESHOLDS");
+ case 0xd3: return ("SMART SAVE ATTR VALUES");
+ case 0xd4: return ("SMART EXECUTE OFFLINE IMMEDIATE");
+ case 0xd5: return ("SMART READ LOG DATA");
+ case 0xd8: return ("SMART ENABLE OPERATION");
+ case 0xd9: return ("SMART DISABLE OPERATION");
+ case 0xda: return ("SMART RETURN STATUS");
+ }
+ return ("SMART");
case 0xb1: return ("DEVICE CONFIGURATION");
case 0xc0: return ("CFA_ERASE");
case 0xc4: return ("READ_MUL");
@@ -158,18 +180,22 @@ ata_op_string(struct ata_cmd *cmd)
case 0xed: return ("MEDIA_EJECT");
case 0xef:
switch (cmd->features) {
- case 0x03: return ("SETFEATURES SET TRANSFER MODE");
- case 0x02: return ("SETFEATURES ENABLE WCACHE");
- case 0x82: return ("SETFEATURES DISABLE WCACHE");
- case 0x06: return ("SETFEATURES ENABLE PUIS");
- case 0x86: return ("SETFEATURES DISABLE PUIS");
- case 0x07: return ("SETFEATURES SPIN-UP");
- case 0x10: return ("SETFEATURES ENABLE SATA FEATURE");
- case 0x90: return ("SETFEATURES DISABLE SATA FEATURE");
- case 0xaa: return ("SETFEATURES ENABLE RCACHE");
- case 0x55: return ("SETFEATURES DISABLE RCACHE");
- }
- return "SETFEATURES";
+ case 0x03: return ("SETFEATURES SET TRANSFER MODE");
+ case 0x02: return ("SETFEATURES ENABLE WCACHE");
+ case 0x82: return ("SETFEATURES DISABLE WCACHE");
+ case 0x06: return ("SETFEATURES ENABLE PUIS");
+ case 0x86: return ("SETFEATURES DISABLE PUIS");
+ case 0x07: return ("SETFEATURES SPIN-UP");
+ case 0x10: return ("SETFEATURES ENABLE SATA FEATURE");
+ case 0x90: return ("SETFEATURES DISABLE SATA FEATURE");
+ case 0xaa: return ("SETFEATURES ENABLE RCACHE");
+ case 0x55: return ("SETFEATURES DISABLE RCACHE");
+ case 0x5d: return ("SETFEATURES ENABLE RELIRQ");
+ case 0xdd: return ("SETFEATURES DISABLE RELIRQ");
+ case 0x5e: return ("SETFEATURES ENABLE SRVIRQ");
+ case 0xde: return ("SETFEATURES DISABLE SRVIRQ");
+ }
+ return "SETFEATURES";
case 0xf1: return ("SECURITY_SET_PASSWORD");
case 0xf2: return ("SECURITY_UNLOCK");
case 0xf3: return ("SECURITY_ERASE_PREPARE");
diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c
index c0c313e82bd8..b9612851d2a7 100644
--- a/sys/cam/scsi/scsi_pass.c
+++ b/sys/cam/scsi/scsi_pass.c
@@ -773,9 +773,6 @@ passclose(struct cdev *dev, int flag, int fmt, struct thread *td)
if (softc->open_count == 0) {
struct pass_io_req *io_req, *io_req2;
- int need_unlock;
-
- need_unlock = 0;
TAILQ_FOREACH_SAFE(io_req, &softc->done_queue, links, io_req2) {
TAILQ_REMOVE(&softc->done_queue, io_req, links);
diff --git a/sys/cam/scsi/scsi_sa.c b/sys/cam/scsi/scsi_sa.c
index 149d06228455..78d43d81c92f 100644
--- a/sys/cam/scsi/scsi_sa.c
+++ b/sys/cam/scsi/scsi_sa.c
@@ -4961,10 +4961,6 @@ sasetpos(struct cam_periph *periph, int hard, struct mtlocate *locate_info)
/*sense_len*/ SSD_FULL_SIZE,
/*timeout*/ SPACE_TIMEOUT);
} else {
- uint32_t blk_pointer;
-
- blk_pointer = locate_info->logical_id;
-
scsi_locate_10(&ccb->csio,
/*retries*/ 1,
/*cbfcnp*/ sadone,
diff --git a/sys/cddl/compat/opensolaris/sys/atomic.h b/sys/cddl/compat/opensolaris/sys/atomic.h
index 363d55893532..81f75da80772 100644
--- a/sys/cddl/compat/opensolaris/sys/atomic.h
+++ b/sys/cddl/compat/opensolaris/sys/atomic.h
@@ -51,7 +51,7 @@ extern uint8_t atomic_or_8_nv(volatile uint8_t *target, uint8_t value);
extern void membar_producer(void);
#if defined(__sparc64__) || defined(__powerpc__) || defined(__arm__) || \
- defined(__mips__) || defined(__aarch64__)
+ defined(__mips__) || defined(__aarch64__) || defined(__riscv__)
extern void atomic_or_8(volatile uint8_t *target, uint8_t value);
#else
static __inline void
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c
index 9293e9a97e27..200369216947 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c
@@ -1652,7 +1652,7 @@ sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr,
int spill_data_size = 0;
int spill_attr_count = 0;
int error;
- uint16_t length;
+ uint16_t length, reg_length;
int i, j, k, length_idx;
sa_hdr_phys_t *hdr;
sa_idx_tab_t *idx_tab;
@@ -1712,34 +1712,50 @@ sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr,
hdr = SA_GET_HDR(hdl, SA_BONUS);
idx_tab = SA_IDX_TAB_GET(hdl, SA_BONUS);
for (; k != 2; k++) {
- /* iterate over each attribute in layout */
+ /*
+ * Iterate over each attribute in layout. Fetch the
+ * size of variable-length attributes needing rewrite
+ * from sa_lengths[].
+ */
for (i = 0, length_idx = 0; i != count; i++) {
sa_attr_type_t attr;
attr = idx_tab->sa_layout->lot_attrs[i];
- if (attr == newattr) {
- /* duplicate attributes are not allowed */
- ASSERT(action == SA_REPLACE ||
- action == SA_REMOVE);
- /* must be variable-sized to be replaced here */
- if (action == SA_REPLACE) {
- ASSERT(SA_REGISTERED_LEN(sa, attr) == 0);
- SA_ADD_BULK_ATTR(attr_desc, j, attr,
- locator, datastart, buflen);
- }
+ reg_length = SA_REGISTERED_LEN(sa, attr);
+ if (reg_length == 0) {
+ length = hdr->sa_lengths[length_idx];
+ length_idx++;
} else {
- length = SA_REGISTERED_LEN(sa, attr);
- if (length == 0) {
- length = hdr->sa_lengths[length_idx];
- }
+ length = reg_length;
+ }
+ if (attr == newattr) {
+ /*
+ * There is nothing to do for SA_REMOVE,
+ * so it is just skipped.
+ */
+ if (action == SA_REMOVE)
+ continue;
+ /*
+ * Duplicate attributes are not allowed, so the
+ * action can not be SA_ADD here.
+ */
+ ASSERT3S(action, ==, SA_REPLACE);
+
+ /*
+ * Only a variable-sized attribute can be
+ * replaced here, and its size must be changing.
+ */
+ ASSERT3U(reg_length, ==, 0);
+ ASSERT3U(length, !=, buflen);
+ SA_ADD_BULK_ATTR(attr_desc, j, attr,
+ locator, datastart, buflen);
+ } else {
SA_ADD_BULK_ATTR(attr_desc, j, attr,
NULL, (void *)
(TOC_OFF(idx_tab->sa_idx_tab[attr]) +
(uintptr_t)old_data[k]), length);
}
- if (SA_REGISTERED_LEN(sa, attr) == 0)
- length_idx++;
}
if (k == 0 && hdl->sa_spill) {
hdr = SA_GET_HDR(hdl, SA_SPILL);
@@ -1750,10 +1766,8 @@ sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr,
}
}
if (action == SA_ADD) {
- length = SA_REGISTERED_LEN(sa, newattr);
- if (length == 0) {
- length = buflen;
- }
+ reg_length = SA_REGISTERED_LEN(sa, newattr);
+ IMPLY(reg_length != 0, reg_length == buflen);
SA_ADD_BULK_ATTR(attr_desc, j, newattr, locator,
datastart, buflen);
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
index 99d313b55faf..5eb9df13d611 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
@@ -134,6 +134,9 @@ SYSCTL_NODE(_vfs_zfs, OID_AUTO, vol, CTLFLAG_RW, 0, "ZFS VOLUME");
static int volmode = ZFS_VOLMODE_GEOM;
SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, mode, CTLFLAG_RWTUN, &volmode, 0,
"Expose as GEOM providers (1), device files (2) or neither");
+static boolean_t zpool_on_zvol = B_FALSE;
+SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, recursive, CTLFLAG_RWTUN, &zpool_on_zvol, 0,
+ "Allow zpools to use zvols as vdevs (DANGEROUS)");
#endif
typedef struct zvol_extent {
@@ -1114,7 +1117,9 @@ zvol_open(struct g_provider *pp, int flag, int count)
return (err);
}
#else /* !illumos */
- if (tsd_get(zfs_geom_probe_vdev_key) != NULL) {
+ boolean_t locked = B_FALSE;
+
+ if (!zpool_on_zvol && tsd_get(zfs_geom_probe_vdev_key) != NULL) {
/*
* if zfs_geom_probe_vdev_key is set, that means that zfs is
* attempting to probe geom providers while looking for a
@@ -1125,19 +1130,34 @@ zvol_open(struct g_provider *pp, int flag, int count)
*/
return (EOPNOTSUPP);
}
-
- mutex_enter(&zfsdev_state_lock);
+ /*
+ * Protect against recursively entering spa_namespace_lock
+ * when spa_open() is used for a pool on a (local) ZVOL(s).
+ * This is needed since we replaced upstream zfsdev_state_lock
+ * with spa_namespace_lock in the ZVOL code.
+ * We are using the same trick as spa_open().
+ * Note that calls in zvol_first_open which need to resolve
+ * pool name to a spa object will enter spa_open()
+ * recursively, but that function already has all the
+ * necessary protection.
+ */
+ if (!MUTEX_HELD(&zfsdev_state_lock)) {
+ mutex_enter(&zfsdev_state_lock);
+ locked = B_TRUE;
+ }
zv = pp->private;
if (zv == NULL) {
- mutex_exit(&zfsdev_state_lock);
+ if (locked)
+ mutex_exit(&zfsdev_state_lock);
return (SET_ERROR(ENXIO));
}
if (zv->zv_total_opens == 0) {
err = zvol_first_open(zv);
if (err) {
- mutex_exit(&zfsdev_state_lock);
+ if (locked)
+ mutex_exit(&zfsdev_state_lock);
return (err);
}
pp->mediasize = zv->zv_volsize;
@@ -1171,7 +1191,8 @@ zvol_open(struct g_provider *pp, int flag, int count)
mutex_exit(&zfsdev_state_lock);
#else
zv->zv_total_opens += count;
- mutex_exit(&zfsdev_state_lock);
+ if (locked)
+ mutex_exit(&zfsdev_state_lock);
#endif
return (err);
@@ -1181,7 +1202,8 @@ out:
#ifdef illumos
mutex_exit(&zfsdev_state_lock);
#else
- mutex_exit(&zfsdev_state_lock);
+ if (locked)
+ mutex_exit(&zfsdev_state_lock);
#endif
return (err);
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/isa_defs.h b/sys/cddl/contrib/opensolaris/uts/common/sys/isa_defs.h
index 281abd755919..e46330c4ec4a 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/isa_defs.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/isa_defs.h
@@ -388,6 +388,48 @@ extern "C" {
#define _DONT_USE_1275_GENERIC_NAMES
#define _HAVE_CPUID_INSN
+#elif defined(__riscv__)
+
+/*
+ * Define the appropriate "processor characteristics"
+ */
+#define _STACK_GROWS_DOWNWARD
+#define _LONG_LONG_LTOH
+#define _BIT_FIELDS_LTOH
+#define _IEEE_754
+#define _CHAR_IS_UNSIGNED
+#define _BOOL_ALIGNMENT 1
+#define _CHAR_ALIGNMENT 1
+#define _SHORT_ALIGNMENT 2
+#define _INT_ALIGNMENT 4
+#define _FLOAT_ALIGNMENT 4
+#define _FLOAT_COMPLEX_ALIGNMENT 4
+#define _LONG_ALIGNMENT 8
+#define _LONG_LONG_ALIGNMENT 8
+#define _DOUBLE_ALIGNMENT 8
+#define _DOUBLE_COMPLEX_ALIGNMENT 8
+#define _LONG_DOUBLE_ALIGNMENT 16
+#define _LONG_DOUBLE_COMPLEX_ALIGNMENT 16
+#define _POINTER_ALIGNMENT 8
+#define _MAX_ALIGNMENT 16
+#define _ALIGNMENT_REQUIRED 1
+
+#define _LONG_LONG_ALIGNMENT_32 _LONG_LONG_ALIGNMENT
+
+/*
+ * Define the appropriate "implementation choices"
+ */
+#if !defined(_LP64)
+#define _LP64
+#endif
+#define _SUNOS_VTOC_16
+#define _DMA_USES_PHYSADDR
+#define _FIRMWARE_NEEDS_FDISK
+#define _PSM_MODULES
+#define _RTC_CONFIG
+#define _DONT_USE_1275_GENERIC_NAMES
+#define _HAVE_CPUID_INSN
+
#elif defined(__arm__)
/*
diff --git a/sys/cddl/dev/fbt/arm/fbt_isa.c b/sys/cddl/dev/fbt/arm/fbt_isa.c
index 0e948dd90979..2e0e5a5eae10 100644
--- a/sys/cddl/dev/fbt/arm/fbt_isa.c
+++ b/sys/cddl/dev/fbt/arm/fbt_isa.c
@@ -83,7 +83,7 @@ fbt_patch_tracepoint(fbt_probe_t *fbt, fbt_patchval_t val)
{
*fbt->fbtp_patchpoint = val;
- cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, sizeof(val));
+ icache_sync((vm_offset_t)fbt->fbtp_patchpoint, sizeof(val));
}
int
diff --git a/sys/compat/cloudabi/cloudabi_proc.c b/sys/compat/cloudabi/cloudabi_proc.c
index d91733760ceb..8d0b6e76958a 100644
--- a/sys/compat/cloudabi/cloudabi_proc.c
+++ b/sys/compat/cloudabi/cloudabi_proc.c
@@ -75,12 +75,16 @@ int
cloudabi_sys_proc_fork(struct thread *td,
struct cloudabi_sys_proc_fork_args *uap)
{
+ struct fork_req fr;
struct filecaps fcaps = {};
- struct proc *p2;
int error, fd;
cap_rights_init(&fcaps.fc_rights, CAP_FSTAT, CAP_EVENT);
- error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2, &fd, 0, &fcaps);
+ bzero(&fr, sizeof(fr));
+ fr.fr_flags = RFFDG | RFPROC | RFPROCDESC;
+ fr.fr_pd_fd = &fd;
+ fr.fr_pd_fcaps = &fcaps;
+ error = fork1(td, &fr);
if (error != 0)
return (error);
/* Return the file descriptor to the parent process. */
diff --git a/sys/compat/linux/linux_fork.c b/sys/compat/linux/linux_fork.c
index d0f73adefd31..c12f198fe79b 100644
--- a/sys/compat/linux/linux_fork.c
+++ b/sys/compat/linux/linux_fork.c
@@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$");
int
linux_fork(struct thread *td, struct linux_fork_args *args)
{
+ struct fork_req fr;
int error;
struct proc *p2;
struct thread *td2;
@@ -73,8 +74,10 @@ linux_fork(struct thread *td, struct linux_fork_args *args)
printf(ARGS(fork, ""));
#endif
- if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2, NULL, 0,
- NULL)) != 0)
+ bzero(&fr, sizeof(fr));
+ fr.fr_flags = RFFDG | RFPROC | RFSTOPPED;
+ fr.fr_procp = &p2;
+ if ((error = fork1(td, &fr)) != 0)
return (error);
td2 = FIRST_THREAD_IN_PROC(p2);
@@ -97,6 +100,7 @@ linux_fork(struct thread *td, struct linux_fork_args *args)
int
linux_vfork(struct thread *td, struct linux_vfork_args *args)
{
+ struct fork_req fr;
int error;
struct proc *p2;
struct thread *td2;
@@ -106,8 +110,10 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args)
printf(ARGS(vfork, ""));
#endif
- if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFPPWAIT | RFSTOPPED,
- 0, &p2, NULL, 0, NULL)) != 0)
+ bzero(&fr, sizeof(fr));
+ fr.fr_flags = RFFDG | RFPROC | RFMEM | RFPPWAIT | RFSTOPPED;
+ fr.fr_procp = &p2;
+ if ((error = fork1(td, &fr)) != 0)
return (error);
td2 = FIRST_THREAD_IN_PROC(p2);
@@ -130,6 +136,7 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args)
static int
linux_clone_proc(struct thread *td, struct linux_clone_args *args)
{
+ struct fork_req fr;
int error, ff = RFPROC | RFSTOPPED;
struct proc *p2;
struct thread *td2;
@@ -170,7 +177,10 @@ linux_clone_proc(struct thread *td, struct linux_clone_args *args)
if (args->flags & LINUX_CLONE_VFORK)
ff |= RFPPWAIT;
- error = fork1(td, ff, 0, &p2, NULL, 0, NULL);
+ bzero(&fr, sizeof(fr));
+ fr.fr_flags = ff;
+ fr.fr_procp = &p2;
+ error = fork1(td, &fr);
if (error)
return (error);
diff --git a/sys/conf/Makefile.arm b/sys/conf/Makefile.arm
index af5f7da3ec76..a7df55b5fe3b 100644
--- a/sys/conf/Makefile.arm
+++ b/sys/conf/Makefile.arm
@@ -68,7 +68,6 @@ SYSTEM_LD_TAIL +=;sed s/" + SIZEOF_HEADERS"// ldscript.$M\
FILES_CPU_FUNC = \
$S/$M/$M/cpufunc_asm_arm9.S \
- $S/$M/$M/cpufunc_asm_arm10.S \
$S/$M/$M/cpufunc_asm_xscale.S $S/$M/$M/cpufunc_asm.S \
$S/$M/$M/cpufunc_asm_xscale_c3.S $S/$M/$M/cpufunc_asm_armv5_ec.S \
$S/$M/$M/cpufunc_asm_fa526.S $S/$M/$M/cpufunc_asm_sheeva.S \
diff --git a/sys/conf/Makefile.riscv b/sys/conf/Makefile.riscv
new file mode 100644
index 000000000000..27338b470413
--- /dev/null
+++ b/sys/conf/Makefile.riscv
@@ -0,0 +1,49 @@
+# Makefile.riscv -- with config changes.
+# Copyright 1990 W. Jolitz
+# from: @(#)Makefile.i386 7.1 5/10/91
+# from FreeBSD: src/sys/conf/Makefile.i386,v 1.255 2002/02/20 23:35:49
+# $FreeBSD$
+#
+# Makefile for FreeBSD
+#
+# RISCVTODO: copy pasted from aarch64, needs to be
+# constructed from a machine description:
+# config machineid
+# Most changes should be made in the machine description
+# /sys/riscv/conf/``machineid''
+# after which you should do
+# config machineid
+# Generic makefile changes should be made in
+# /sys/conf/Makefile.riscv
+# after which config should be rerun for all machines.
+#
+
+# Which version of config(8) is required.
+%VERSREQ= 600012
+
+.if !defined(S)
+S= ../../..
+.endif
+.include "$S/conf/kern.pre.mk"
+
+INCLUDES+= -I$S/contrib/libfdt
+
+.if !empty(DDB_ENABLED)
+CFLAGS += -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer
+.endif
+
+%BEFORE_DEPEND
+
+%OBJS
+
+%FILES.c
+
+%FILES.s
+
+%FILES.m
+
+%CLEAN
+
+%RULES
+
+.include "$S/conf/kern.post.mk"
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 7d06fe321703..67a1bb4e6866 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -1078,6 +1078,14 @@ options UFS_GJOURNAL
# Make space in the kernel for a root filesystem on a md device.
# Define to the number of kilobytes to reserve for the filesystem.
+# This is now optional.
+# If not defined, the root filesystem passed in as the MFS_IMAGE makeoption
+# will be automatically embedded in the kernel during linking. Its exact size
+# will be consumed within the kernel.
+# If defined, the old way of embedding the filesystem in the kernel will be
+# used. That is to say MD_ROOT_SIZE KB will be allocated in the kernel and
+# later, the filesystem image passed in as the MFS_IMAGE makeoption will be
+# dd'd into the reserved space if it fits.
options MD_ROOT_SIZE=10
# Make the md device a potential root device, either with preloaded
diff --git a/sys/conf/files.arm b/sys/conf/files.arm
index 33bdd94265cb..bc5d8a39fd6d 100644
--- a/sys/conf/files.arm
+++ b/sys/conf/files.arm
@@ -11,18 +11,17 @@ arm/arm/busdma_machdep-v6.c optional armv6
arm/arm/copystr.S standard
arm/arm/cpufunc.c standard
arm/arm/cpufunc_asm.S standard
-arm/arm/cpufunc_asm_arm9.S optional cpu_arm9
-arm/arm/cpufunc_asm_arm10.S optional cpu_arm9e
+arm/arm/cpufunc_asm_arm9.S optional cpu_arm9 | cpu_arm9e
arm/arm/cpufunc_asm_arm11.S optional cpu_arm1176
arm/arm/cpufunc_asm_arm11x6.S optional cpu_arm1176
-arm/arm/cpufunc_asm_armv4.S optional cpu_arm9 | cpu_arm9e | cpu_fa526 | cpu_xscale_80321 | cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_80219 | cpu_xscale_81342
+arm/arm/cpufunc_asm_armv4.S optional cpu_arm9 | cpu_arm9e | cpu_fa526 | cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_81342
arm/arm/cpufunc_asm_armv5_ec.S optional cpu_arm9e
arm/arm/cpufunc_asm_armv6.S optional cpu_arm1176
arm/arm/cpufunc_asm_armv7.S optional cpu_cortexa | cpu_krait | cpu_mv_pj4b
arm/arm/cpufunc_asm_fa526.S optional cpu_fa526
arm/arm/cpufunc_asm_pj4b.S optional cpu_mv_pj4b
arm/arm/cpufunc_asm_sheeva.S optional cpu_arm9e
-arm/arm/cpufunc_asm_xscale.S optional cpu_xscale_80321 | cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_80219 | cpu_xscale_81342
+arm/arm/cpufunc_asm_xscale.S optional cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_81342
arm/arm/cpufunc_asm_xscale_c3.S optional cpu_xscale_81342
arm/arm/cpuinfo.c standard
arm/arm/cpu_asm-v6.S optional armv6
@@ -64,8 +63,7 @@ arm/arm/pl310.c optional pl310
arm/arm/platform.c optional platform
arm/arm/platform_if.m optional platform
arm/arm/pmap.c optional !armv6
-arm/arm/pmap-v6.c optional armv6 !arm_new_pmap
-arm/arm/pmap-v6-new.c optional armv6 arm_new_pmap
+arm/arm/pmap-v6.c optional armv6
arm/arm/pmu.c optional pmu | fdt hwpmc
arm/arm/sc_machdep.c optional sc
arm/arm/setcpsr.S standard
@@ -75,6 +73,8 @@ arm/arm/stdatomic.c standard \
compile-with "${NORMAL_C:N-Wmissing-prototypes}"
arm/arm/support.S standard
arm/arm/swtch.S standard
+arm/arm/swtch-v4.S optional !armv6
+arm/arm/swtch-v6.S optional armv6
arm/arm/sys_machdep.c standard
arm/arm/syscall.c standard
arm/arm/trap.c optional !armv6
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index 6168d704ed18..bbc77c19d010 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -20,6 +20,7 @@ arm64/arm64/db_disasm.c optional ddb
arm64/arm64/db_interface.c optional ddb
arm64/arm64/db_trace.c optional ddb
arm64/arm64/debug_monitor.c optional kdb
+arm64/arm64/disassem.c optional ddb
arm64/arm64/dump_machdep.c standard
arm64/arm64/elf_machdep.c standard
arm64/arm64/exception.S standard
@@ -51,7 +52,8 @@ arm64/arm64/uma_machdep.c standard
arm64/arm64/unwind.c optional ddb | kdtrace_hooks | stack
arm64/arm64/vfp.c standard
arm64/arm64/vm_machdep.c standard
-arm64/cavium/thunder_pcie.c optional soc_cavm_thunderx pci fdt
+arm64/cavium/thunder_pcie.c optional soc_cavm_thunderx pci
+arm64/cavium/thunder_pcie_fdt.c optional soc_cavm_thunderx pci fdt
arm64/cavium/thunder_pcie_pem.c optional soc_cavm_thunderx pci
arm64/cavium/thunder_pcie_common.c optional soc_cavm_thunderx pci
arm64/cloudabi64/cloudabi64_sysvec.c optional compat_cloudabi64
@@ -70,6 +72,7 @@ dev/psci/psci_arm64.S optional psci
dev/uart/uart_cpu_fdt.c optional uart fdt
dev/uart/uart_dev_pl011.c optional uart pl011
dev/usb/controller/dwc_otg_hisi.c optional dwcotg soc_hisi_hi6220
+dev/vnic/mrml_bridge.c optional vnic fdt
dev/vnic/nic_main.c optional vnic pci
dev/vnic/nicvf_main.c optional vnic pci pci_iov
dev/vnic/nicvf_queues.c optional vnic pci pci_iov
diff --git a/sys/conf/files.riscv b/sys/conf/files.riscv
new file mode 100644
index 000000000000..a101b57cfe2f
--- /dev/null
+++ b/sys/conf/files.riscv
@@ -0,0 +1,44 @@
+# $FreeBSD$
+crypto/blowfish/bf_enc.c optional crypto | ipsec
+crypto/des/des_enc.c optional crypto | ipsec | netsmb
+kern/kern_clocksource.c standard
+kern/subr_dummy_vdso_tc.c standard
+libkern/bcmp.c standard
+libkern/ffs.c standard
+libkern/ffsl.c standard
+libkern/fls.c standard
+libkern/flsl.c standard
+libkern/flsll.c standard
+libkern/memmove.c standard
+libkern/memset.c standard
+riscv/htif/htif.c standard
+riscv/htif/htif_block.c standard
+riscv/htif/htif_console.c standard
+riscv/riscv/autoconf.c standard
+riscv/riscv/bcopy.c standard
+riscv/riscv/bus_machdep.c standard
+riscv/riscv/busdma_machdep.c standard
+riscv/riscv/clock.c standard
+riscv/riscv/copyinout.S standard
+riscv/riscv/copystr.c standard
+riscv/riscv/cpufunc_asm.S standard
+riscv/riscv/devmap.c standard
+riscv/riscv/dump_machdep.c standard
+riscv/riscv/elf_machdep.c standard
+riscv/riscv/intr_machdep.c standard
+riscv/riscv/in_cksum.c optional inet | inet6
+riscv/riscv/identcpu.c standard
+riscv/riscv/locore.S standard no-obj
+riscv/riscv/minidump_machdep.c standard
+riscv/riscv/machdep.c standard
+riscv/riscv/mem.c standard
+riscv/riscv/nexus.c standard
+riscv/riscv/pmap.c standard
+riscv/riscv/sys_machdep.c standard
+riscv/riscv/support.S standard
+riscv/riscv/swtch.S standard
+riscv/riscv/trap.c standard
+riscv/riscv/timer.c standard
+riscv/riscv/uio_machdep.c standard
+riscv/riscv/uma_machdep.c standard
+riscv/riscv/vm_machdep.c standard
diff --git a/sys/conf/kern.mk b/sys/conf/kern.mk
index 56ddbda4996e..fb72a9789482 100644
--- a/sys/conf/kern.mk
+++ b/sys/conf/kern.mk
@@ -104,6 +104,10 @@ CFLAGS += -mgeneral-regs-only
CFLAGS += -ffixed-x18
.endif
+.if ${MACHINE_CPUARCH} == "riscv"
+INLINE_LIMIT?= 8000
+.endif
+
#
# For sparc64 we want the medany code model so modules may be located
# anywhere in the 64-bit address space. We also tell GCC to use floating
diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk
index 56f7c507f1fb..5bcc56eba733 100644
--- a/sys/conf/kern.post.mk
+++ b/sys/conf/kern.post.mk
@@ -130,6 +130,9 @@ ${FULLKERNEL}: ${SYSTEM_DEP} vers.o
@rm -f ${.TARGET}
@echo linking ${.TARGET}
${SYSTEM_LD}
+.if !empty(MD_ROOT_SIZE_CONFIGURED) && defined(MFS_IMAGE)
+ @sh ${S}/tools/embed_mfs.sh ${.TARGET} ${MFS_IMAGE}
+.endif
.if ${MK_CTF} != "no"
@echo ${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ...
@${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ${SYSTEM_OBJS} vers.o
@@ -353,6 +356,7 @@ vnode_if_typedef.h:
${AWK} -f $S/tools/vnode_if.awk $S/kern/vnode_if.src -q
.if ${MFS_IMAGE:Uno} != "no"
+.if empty(MD_ROOT_SIZE_CONFIGURED)
# Generate an object file from the file system image to embed in the kernel
# via linking. Make sure the contents are in the mfs section and rename the
# start/end/size variables to __start_mfs, __stop_mfs, and mfs_size,
@@ -372,6 +376,7 @@ embedfs_${MFS_IMAGE:T:R}.o: ${MFS_IMAGE}
_binary_${MFS_IMAGE:C,[^[:alnum:]],_,g}_end=mfs_root_end \
${.TARGET}
.endif
+.endif
# XXX strictly, everything depends on Makefile because changes to ${PROF}
# only appear there, but we don't handle that.
diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk
index 7860701e8440..cf6ec1066f53 100644
--- a/sys/conf/kern.pre.mk
+++ b/sys/conf/kern.pre.mk
@@ -195,9 +195,13 @@ SYSTEM_DEP= Makefile ${SYSTEM_OBJS}
SYSTEM_OBJS= locore.o ${MDOBJS} ${OBJS}
SYSTEM_OBJS+= ${SYSTEM_CFILES:.c=.o}
SYSTEM_OBJS+= hack.So
+
+MD_ROOT_SIZE_CONFIGURED!= grep MD_ROOT_SIZE opt_md.h || true ; echo
.if ${MFS_IMAGE:Uno} != "no"
+.if empty(MD_ROOT_SIZE_CONFIGURED)
SYSTEM_OBJS+= embedfs_${MFS_IMAGE:T:R}.o
.endif
+.endif
SYSTEM_LD= @${LD} -Bdynamic -T ${LDSCRIPT} ${_LDFLAGS} --no-warn-mismatch \
--warn-common --export-dynamic --dynamic-linker /red/herring \
-o ${.TARGET} -X ${SYSTEM_OBJS} vers.o
@@ -230,8 +234,9 @@ MKMODULESENV+= __MPATH="${__MPATH}"
# Architecture and output format arguments for objdump to convert image to
# object file
-.if ${MFS_IMAGE:Uno} != "no"
+.if ${MFS_IMAGE:Uno} != "no"
+.if empty(MD_ROOT_SIZE_CONFIGURED)
.if !defined(EMBEDFS_FORMAT.${MACHINE_ARCH})
EMBEDFS_FORMAT.${MACHINE_ARCH}!= awk -F'"' '/OUTPUT_FORMAT/ {print $$2}' ${LDSCRIPT}
.if empty(EMBEDFS_FORMAT.${MACHINE_ARCH})
@@ -252,6 +257,8 @@ EMBEDFS_FORMAT.mips?= elf32-tradbigmips
EMBEDFS_FORMAT.mipsel?= elf32-tradlittlemips
EMBEDFS_FORMAT.mips64?= elf64-tradbigmips
EMBEDFS_FORMAT.mips64el?= elf64-tradlittlemips
+EMBEDFS_FORMAT.riscv?= elf64-littleriscv
+.endif
.endif
# Detect kernel config options that force stack frames to be turned on.
diff --git a/sys/conf/ldscript.riscv b/sys/conf/ldscript.riscv
new file mode 100644
index 000000000000..31fd5df9ce4e
--- /dev/null
+++ b/sys/conf/ldscript.riscv
@@ -0,0 +1,136 @@
+/* $FreeBSD$ */
+OUTPUT_ARCH(riscv)
+ENTRY(_start)
+
+SEARCH_DIR(/usr/lib);
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = kernbase + 0x100;
+ .text : AT(ADDR(.text) - kernbase)
+ {
+ *(.text)
+ *(.stub)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.gnu.linkonce.t*)
+ } =0x9090
+ _etext = .;
+ PROVIDE (etext = .);
+ .fini : { *(.fini) } =0x9090
+ .rodata : { *(.rodata) *(.gnu.linkonce.r*) }
+ .rodata1 : { *(.rodata1) }
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.text :
+ { *(.rel.text) *(.rel.gnu.linkonce.t*) }
+ .rela.text :
+ { *(.rela.text) *(.rela.gnu.linkonce.t*) }
+ .rel.data :
+ { *(.rel.data) *(.rel.gnu.linkonce.d*) }
+ .rela.data :
+ { *(.rela.data) *(.rela.gnu.linkonce.d*) }
+ .rel.rodata :
+ { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
+ .rela.rodata :
+ { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) } =0x9090
+ .plt : { *(.plt) }
+
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = ALIGN(0x1000) + (. & (0x1000 - 1)) ;
+ .data :
+ {
+ *(.data)
+ *(.gnu.linkonce.d*)
+ CONSTRUCTORS
+ }
+ .data1 : { *(.data1) }
+ . = ALIGN(32 / 8);
+ _start_ctors = .;
+ PROVIDE (start_ctors = .);
+ .ctors :
+ {
+ *(.ctors)
+ }
+ _stop_ctors = .;
+ PROVIDE (stop_ctors = .);
+ .dtors :
+ {
+ *(.dtors)
+ }
+ .got : { *(.got.plt) *(.got) }
+ .dynamic : { *(.dynamic) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ . = ALIGN(8);
+ .sdata : { *(.sdata) }
+ _edata = .;
+ PROVIDE (edata = .);
+ __bss_start = .;
+ .sbss : { *(.sbss) *(.scommon) }
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ . = ALIGN(8);
+ _end = . ;
+ PROVIDE (end = .);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* These must appear regardless of . */
+}
diff --git a/sys/conf/options b/sys/conf/options
index c7cd58181e8b..f1b2af473ceb 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -918,6 +918,7 @@ VNET_DEBUG opt_global.h
# Common Flash Interface (CFI) options
CFI_SUPPORT_STRATAFLASH opt_cfi.h
CFI_ARMEDANDDANGEROUS opt_cfi.h
+CFI_HARDWAREBYTESWAP opt_cfi.h
# Sound options
SND_DEBUG opt_snd.h
diff --git a/sys/conf/options.arm b/sys/conf/options.arm
index 8720ac24a168..7beae5bd6833 100644
--- a/sys/conf/options.arm
+++ b/sys/conf/options.arm
@@ -5,7 +5,6 @@ ARM_INTRNG opt_global.h
ARM_KERN_DIRECTMAP opt_vm.h
ARM_L2_PIPT opt_global.h
ARM_MANY_BOARD opt_global.h
-ARM_NEW_PMAP opt_global.h
NKPT2PG opt_pmap.h
ARM_WANT_TP_ADDRESS opt_global.h
COUNTS_PER_SEC opt_timer.h
@@ -16,8 +15,6 @@ CPU_CORTEXA opt_global.h
CPU_KRAIT opt_global.h
CPU_FA526 opt_global.h
CPU_MV_PJ4B opt_global.h
-CPU_XSCALE_80219 opt_global.h
-CPU_XSCALE_80321 opt_global.h
CPU_XSCALE_81342 opt_global.h
CPU_XSCALE_IXP425 opt_global.h
CPU_XSCALE_IXP435 opt_global.h
diff --git a/sys/conf/options.mips b/sys/conf/options.mips
index 47cff06ff7c2..e85f5b1327e2 100644
--- a/sys/conf/options.mips
+++ b/sys/conf/options.mips
@@ -29,9 +29,13 @@
# $FreeBSD$
CPU_MIPS4KC opt_global.h
-CPU_MIPS24KC opt_global.h
-CPU_MIPS74KC opt_global.h
-CPU_MIPS1004KC opt_global.h
+CPU_MIPS24K opt_global.h
+CPU_MIPS34K opt_global.h
+CPU_MIPS74K opt_global.h
+CPU_MIPS1004K opt_global.h
+CPU_MIPS1074K opt_global.h
+CPU_INTERAPTIV opt_global.h
+CPU_PROAPTIV opt_global.h
CPU_MIPS32 opt_global.h
CPU_MIPS64 opt_global.h
CPU_SENTRY5 opt_global.h
diff --git a/sys/conf/options.riscv b/sys/conf/options.riscv
new file mode 100644
index 000000000000..c263bd860875
--- /dev/null
+++ b/sys/conf/options.riscv
@@ -0,0 +1,4 @@
+# $FreeBSD$
+
+RISCV opt_global.h
+VFP opt_global.h
diff --git a/sys/contrib/ipfilter/netinet/ip_compat.h b/sys/contrib/ipfilter/netinet/ip_compat.h
index 8aece74b53cc..bcb47e93464d 100644
--- a/sys/contrib/ipfilter/netinet/ip_compat.h
+++ b/sys/contrib/ipfilter/netinet/ip_compat.h
@@ -147,6 +147,7 @@ struct ether_addr {
# include <sys/selinfo.h>
# include <sys/lock.h>
+# include <sys/malloc.h>
# include <sys/mutex.h>
# define KRWLOCK_FILL_SZ 56
# define KMUTEX_FILL_SZ 56
diff --git a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
index 30ec46c11b9d..8a5a90d74073 100644
--- a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
+++ b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c
@@ -36,6 +36,7 @@ static const char rcsid[] = "@(#)$Id$";
#if defined(__FreeBSD_version) && (__FreeBSD_version >= 800000)
#include <sys/jail.h>
#endif
+# include <sys/malloc.h>
# include <sys/mbuf.h>
# include <sys/sockopt.h>
#if !defined(__hpux)
diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
index 753e8e510631..e325f6ed777a 100644
--- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
+++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
@@ -48,6 +48,7 @@
#include <vm/vm_phys.h>
#include <machine/bus.h>
+#include <machine/cpu.h>
#include <arm/broadcom/bcm2835/bcm2835_mbox.h>
#include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
@@ -411,6 +412,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
int run, addridx, actual_pages;
int err;
vm_paddr_t pagelist_phys;
+ vm_paddr_t pa;
offset = (vm_offset_t)buf & (PAGE_SIZE - 1);
num_pages = (count + offset + PAGE_SIZE - 1) / PAGE_SIZE;
@@ -533,7 +535,8 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
(fragments - g_fragments_base)/g_fragment_size;
}
- cpu_dcache_wbinv_range((vm_offset_t)buf, count);
+ pa = pmap_extract(PCPU_GET(curpmap), (vm_offset_t)buf);
+ dcache_wbinv_poc((vm_offset_t)buf, pa, count);
bus_dmamap_sync(bi->pagelist_dma_tag, bi->pagelist_dma_map, BUS_DMASYNC_PREWRITE);
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 118e38e30a19..8cefa9e09cd1 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -496,7 +496,18 @@ ata_cmd2str(struct ata_request *request)
}
} else {
switch (request->u.ata.command) {
- case 0x00: return ("NOP");
+ case 0x00:
+ switch (request->u.ata.feature) {
+ case 0x00: return ("NOP FLUSHQUEUE");
+ case 0x01: return ("NOP AUTOPOLL");
+ }
+ return ("NOP");
+ case 0x03: return ("CFA_REQUEST_EXTENDED_ERROR");
+ case 0x06:
+ switch (request->u.ata.feature) {
+ case 0x01: return ("DSM TRIM");
+ }
+ return "DSM";
case 0x08: return ("DEVICE_RESET");
case 0x20: return ("READ");
case 0x24: return ("READ48");
@@ -504,18 +515,65 @@ ata_cmd2str(struct ata_request *request)
case 0x26: return ("READ_DMA_QUEUED48");
case 0x27: return ("READ_NATIVE_MAX_ADDRESS48");
case 0x29: return ("READ_MUL48");
+ case 0x2a: return ("READ_STREAM_DMA48");
+ case 0x2b: return ("READ_STREAM48");
+ case 0x2f: return ("READ_LOG_EXT");
case 0x30: return ("WRITE");
case 0x34: return ("WRITE48");
case 0x35: return ("WRITE_DMA48");
case 0x36: return ("WRITE_DMA_QUEUED48");
case 0x37: return ("SET_MAX_ADDRESS48");
case 0x39: return ("WRITE_MUL48");
+ case 0x3a: return ("WRITE_STREAM_DMA48");
+ case 0x3b: return ("WRITE_STREAM48");
+ case 0x3d: return ("WRITE_DMA_FUA48");
+ case 0x3e: return ("WRITE_DMA_QUEUED_FUA48");
+ case 0x3f: return ("WRITE_LOG_EXT");
+ case 0x40: return ("READ_VERIFY");
+ case 0x42: return ("READ_VERIFY48");
+ case 0x45:
+ switch (request->u.ata.feature) {
+ case 0x55: return ("WRITE_UNCORRECTABLE48 PSEUDO");
+ case 0xaa: return ("WRITE_UNCORRECTABLE48 FLAGGED");
+ }
+ return "WRITE_UNCORRECTABLE48";
+ case 0x51: return ("CONFIGURE_STREAM");
+ case 0x60: return ("READ_FPDMA_QUEUED");
+ case 0x61: return ("WRITE_FPDMA_QUEUED");
+ case 0x63: return ("NCQ_NON_DATA");
+ case 0x64: return ("SEND_FPDMA_QUEUED");
+ case 0x65: return ("RECEIVE_FPDMA_QUEUED");
+ case 0x67:
+ if (request->u.ata.feature == 0xec)
+ return ("SEP_ATTN IDENTIFY");
+ switch (request->u.ata.lba) {
+ case 0x00: return ("SEP_ATTN READ BUFFER");
+ case 0x02: return ("SEP_ATTN RECEIVE DIAGNOSTIC RESULTS");
+ case 0x80: return ("SEP_ATTN WRITE BUFFER");
+ case 0x82: return ("SEP_ATTN SEND DIAGNOSTIC");
+ }
+ return ("SEP_ATTN");
case 0x70: return ("SEEK");
- case 0xa0: return ("PACKET_CMD");
+ case 0x87: return ("CFA_TRANSLATE_SECTOR");
+ case 0x90: return ("EXECUTE_DEVICE_DIAGNOSTIC");
+ case 0x92: return ("DOWNLOAD_MICROCODE");
+ case 0xa0: return ("PACKET");
case 0xa1: return ("ATAPI_IDENTIFY");
case 0xa2: return ("SERVICE");
- case 0xb0: return ("SMART");
- case 0xc0: return ("CFA ERASE");
+ case 0xb0:
+ switch(request->u.ata.feature) {
+ case 0xd0: return ("SMART READ ATTR VALUES");
+ case 0xd1: return ("SMART READ ATTR THRESHOLDS");
+ case 0xd3: return ("SMART SAVE ATTR VALUES");
+ case 0xd4: return ("SMART EXECUTE OFFLINE IMMEDIATE");
+ case 0xd5: return ("SMART READ LOG DATA");
+ case 0xd8: return ("SMART ENABLE OPERATION");
+ case 0xd9: return ("SMART DISABLE OPERATION");
+ case 0xda: return ("SMART RETURN STATUS");
+ }
+ return ("SMART");
+ case 0xb1: return ("DEVICE CONFIGURATION");
+ case 0xc0: return ("CFA_ERASE");
case 0xc4: return ("READ_MUL");
case 0xc5: return ("WRITE_MUL");
case 0xc6: return ("SET_MULTI");
@@ -523,22 +581,48 @@ ata_cmd2str(struct ata_request *request)
case 0xc8: return ("READ_DMA");
case 0xca: return ("WRITE_DMA");
case 0xcc: return ("WRITE_DMA_QUEUED");
+ case 0xcd: return ("CFA_WRITE_MULTIPLE_WITHOUT_ERASE");
+ case 0xce: return ("WRITE_MUL_FUA48");
+ case 0xd1: return ("CHECK_MEDIA_CARD_TYPE");
+ case 0xda: return ("GET_MEDIA_STATUS");
+ case 0xde: return ("MEDIA_LOCK");
+ case 0xdf: return ("MEDIA_UNLOCK");
+ case 0xe0: return ("STANDBY_IMMEDIATE");
+ case 0xe1: return ("IDLE_IMMEDIATE");
+ case 0xe2: return ("STANDBY");
+ case 0xe3: return ("IDLE");
+ case 0xe4: return ("READ_BUFFER/PM");
+ case 0xe5: return ("CHECK_POWER_MODE");
case 0xe6: return ("SLEEP");
case 0xe7: return ("FLUSHCACHE");
+ case 0xe8: return ("WRITE_PM");
case 0xea: return ("FLUSHCACHE48");
case 0xec: return ("ATA_IDENTIFY");
+ case 0xed: return ("MEDIA_EJECT");
case 0xef:
switch (request->u.ata.feature) {
case 0x03: return ("SETFEATURES SET TRANSFER MODE");
case 0x02: return ("SETFEATURES ENABLE WCACHE");
case 0x82: return ("SETFEATURES DISABLE WCACHE");
+ case 0x06: return ("SETFEATURES ENABLE PUIS");
+ case 0x86: return ("SETFEATURES DISABLE PUIS");
+ case 0x07: return ("SETFEATURES SPIN-UP");
+ case 0x10: return ("SETFEATURES ENABLE SATA FEATURE");
+ case 0x90: return ("SETFEATURES DISABLE SATA FEATURE");
case 0xaa: return ("SETFEATURES ENABLE RCACHE");
case 0x55: return ("SETFEATURES DISABLE RCACHE");
+ case 0x5d: return ("SETFEATURES ENABLE RELIRQ");
+ case 0xdd: return ("SETFEATURES DISABLE RELIRQ");
+ case 0x5e: return ("SETFEATURES ENABLE SRVIRQ");
+ case 0xde: return ("SETFEATURES DISABLE SRVIRQ");
}
- sprintf(buffer, "SETFEATURES 0x%02x",
- request->u.ata.feature);
- return (buffer);
- case 0xf5: return ("SECURITY_FREE_LOCK");
+ return "SETFEATURES";
+ case 0xf1: return ("SECURITY_SET_PASSWORD");
+ case 0xf2: return ("SECURITY_UNLOCK");
+ case 0xf3: return ("SECURITY_ERASE_PREPARE");
+ case 0xf4: return ("SECURITY_ERASE_UNIT");
+ case 0xf5: return ("SECURITY_FREEZE_LOCK");
+ case 0xf6: return ("SECURITY_DISABLE_PASSWORD");
case 0xf8: return ("READ_NATIVE_MAX_ADDRESS");
case 0xf9: return ("SET_MAX_ADDRESS");
}
diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c
index 93996e27beb8..e2228e6e3c59 100644
--- a/sys/dev/bwn/if_bwn.c
+++ b/sys/dev/bwn/if_bwn.c
@@ -36,8 +36,9 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/module.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
#include <sys/endian.h>
#include <sys/errno.h>
#include <sys/firmware.h>
diff --git a/sys/dev/cfi/cfi_core.c b/sys/dev/cfi/cfi_core.c
index 5150b779f0e5..d292e1a4188b 100644
--- a/sys/dev/cfi/cfi_core.c
+++ b/sys/dev/cfi/cfi_core.c
@@ -99,11 +99,17 @@ cfi_read(struct cfi_softc *sc, u_int ofs)
break;
case 2:
sval = bus_space_read_2(sc->sc_tag, sc->sc_handle, ofs);
+#ifdef CFI_HARDWAREBYTESWAP
+ val = sval;
+#else
val = le16toh(sval);
+#endif
break;
case 4:
val = bus_space_read_4(sc->sc_tag, sc->sc_handle, ofs);
+#ifndef CFI_HARDWAREBYTESWAP
val = le32toh(val);
+#endif
break;
default:
val = ~0;
@@ -122,10 +128,19 @@ cfi_write(struct cfi_softc *sc, u_int ofs, u_int val)
bus_space_write_1(sc->sc_tag, sc->sc_handle, ofs, val);
break;
case 2:
+#ifdef CFI_HARDWAREBYTESWAP
+ bus_space_write_2(sc->sc_tag, sc->sc_handle, ofs, val);
+#else
bus_space_write_2(sc->sc_tag, sc->sc_handle, ofs, htole16(val));
+
+#endif
break;
case 4:
+#ifdef CFI_HARDWAREBYTESWAP
+ bus_space_write_4(sc->sc_tag, sc->sc_handle, ofs, val);
+#else
bus_space_write_4(sc->sc_tag, sc->sc_handle, ofs, htole32(val));
+#endif
break;
}
}
diff --git a/sys/dev/cxgb/cxgb_sge.c b/sys/dev/cxgb/cxgb_sge.c
index d70a94877fcd..2cfad262673b 100644
--- a/sys/dev/cxgb/cxgb_sge.c
+++ b/sys/dev/cxgb/cxgb_sge.c
@@ -738,7 +738,7 @@ refill_fl(adapter_t *sc, struct sge_fl *q, int n)
cl, q->buf_size, refill_fl_cb, &cb_arg, 0);
if (err != 0 || cb_arg.error) {
- if (q->zone == zone_pack)
+ if (q->zone != zone_pack)
uma_zfree(q->zone, cl);
m_free(m);
goto done;
diff --git a/sys/dev/e1000/e1000_80003es2lan.c b/sys/dev/e1000/e1000_80003es2lan.c
index b948bb4e3198..e7c42d5386eb 100644
--- a/sys/dev/e1000/e1000_80003es2lan.c
+++ b/sys/dev/e1000/e1000_80003es2lan.c
@@ -851,11 +851,17 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
e1000_release_phy_80003es2lan(hw);
/* Disable IBIST slave mode (far-end loopback) */
- e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
- &kum_reg_data);
- kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
- e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
- kum_reg_data);
+ ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
+ E1000_KMRNCTRLSTA_INBAND_PARAM, &kum_reg_data);
+ if (!ret_val) {
+ kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
+ ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
+ E1000_KMRNCTRLSTA_INBAND_PARAM,
+ kum_reg_data);
+ if (ret_val)
+ DEBUGOUT("Error disabling far-end loopback\n");
+ } else
+ DEBUGOUT("Error disabling far-end loopback\n");
ret_val = e1000_get_auto_rd_done_generic(hw);
if (ret_val)
@@ -911,11 +917,18 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
return ret_val;
/* Disable IBIST slave mode (far-end loopback) */
- e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
- &kum_reg_data);
- kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
- e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
- kum_reg_data);
+ ret_val =
+ e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+ &kum_reg_data);
+ if (!ret_val) {
+ kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
+ ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
+ E1000_KMRNCTRLSTA_INBAND_PARAM,
+ kum_reg_data);
+ if (ret_val)
+ DEBUGOUT("Error disabling far-end loopback\n");
+ } else
+ DEBUGOUT("Error disabling far-end loopback\n");
/* Set the transmit descriptor write-back policy */
reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0));
diff --git a/sys/dev/e1000/e1000_82540.c b/sys/dev/e1000/e1000_82540.c
index 68f92c619afe..2d03b8ff8e3f 100644
--- a/sys/dev/e1000/e1000_82540.c
+++ b/sys/dev/e1000/e1000_82540.c
@@ -66,7 +66,7 @@ static s32 e1000_read_mac_addr_82540(struct e1000_hw *hw);
static s32 e1000_init_phy_params_82540(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
phy->addr = 1;
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
@@ -329,7 +329,7 @@ static s32 e1000_init_hw_82540(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
u32 txdctl, ctrl_ext;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 i;
DEBUGFUNC("e1000_init_hw_82540");
@@ -411,7 +411,7 @@ static s32 e1000_init_hw_82540(struct e1000_hw *hw)
static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw)
{
u32 ctrl;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 data;
DEBUGFUNC("e1000_setup_copper_link_82540");
@@ -498,7 +498,7 @@ out:
**/
static s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 nvm_data;
DEBUGFUNC("e1000_adjust_serdes_amplitude_82540");
@@ -528,7 +528,7 @@ out:
**/
static s32 e1000_set_vco_speed_82540(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 default_page = 0;
u16 phy_data;
diff --git a/sys/dev/e1000/e1000_82541.c b/sys/dev/e1000/e1000_82541.c
index 59615556fa32..55d51087b7b3 100644
--- a/sys/dev/e1000/e1000_82541.c
+++ b/sys/dev/e1000/e1000_82541.c
@@ -85,7 +85,7 @@ static const u16 e1000_igp_cable_length_table[] = {
static s32 e1000_init_phy_params_82541(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_init_phy_params_82541");
@@ -295,7 +295,7 @@ void e1000_init_function_pointers_82541(struct e1000_hw *hw)
**/
static s32 e1000_reset_hw_82541(struct e1000_hw *hw)
{
- u32 ledctl, ctrl, icr, manc;
+ u32 ledctl, ctrl, manc;
DEBUGFUNC("e1000_reset_hw_82541");
@@ -317,6 +317,7 @@ static s32 e1000_reset_hw_82541(struct e1000_hw *hw)
/* Must reset the Phy before resetting the MAC */
if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_PHY_RST));
+ E1000_WRITE_FLUSH(hw);
msec_delay(5);
}
@@ -359,7 +360,7 @@ static s32 e1000_reset_hw_82541(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
/* Clear any pending interrupt events. */
- icr = E1000_READ_REG(hw, E1000_ICR);
+ E1000_READ_REG(hw, E1000_ICR);
return E1000_SUCCESS;
}
diff --git a/sys/dev/e1000/e1000_82542.c b/sys/dev/e1000/e1000_82542.c
index b2d676eca8c5..4cca9b2b2c61 100644
--- a/sys/dev/e1000/e1000_82542.c
+++ b/sys/dev/e1000/e1000_82542.c
@@ -317,7 +317,7 @@ static s32 e1000_init_hw_82542(struct e1000_hw *hw)
static s32 e1000_setup_link_82542(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_setup_link_82542");
@@ -565,7 +565,7 @@ static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw)
*
* Reads the device MAC address from the EEPROM and stores the value.
**/
-static s32 e1000_read_mac_addr_82542(struct e1000_hw *hw)
+s32 e1000_read_mac_addr_82542(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
u16 offset, nvm_data, i;
diff --git a/sys/dev/e1000/e1000_82543.c b/sys/dev/e1000/e1000_82543.c
index b9a53bd6081c..474387d2cb75 100644
--- a/sys/dev/e1000/e1000_82543.c
+++ b/sys/dev/e1000/e1000_82543.c
@@ -900,7 +900,7 @@ static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw)
**/
static s32 e1000_reset_hw_82543(struct e1000_hw *hw)
{
- u32 ctrl, icr;
+ u32 ctrl;
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_reset_hw_82543");
@@ -942,7 +942,7 @@ static s32 e1000_reset_hw_82543(struct e1000_hw *hw)
/* Masking off and clearing any pending interrupts */
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
- icr = E1000_READ_REG(hw, E1000_ICR);
+ E1000_READ_REG(hw, E1000_ICR);
return ret_val;
}
diff --git a/sys/dev/e1000/e1000_82571.h b/sys/dev/e1000/e1000_82571.h
index 1d7718eda12c..8e5ca56ae88c 100644
--- a/sys/dev/e1000/e1000_82571.h
+++ b/sys/dev/e1000/e1000_82571.h
@@ -50,9 +50,10 @@
#define E1000_EIAC_82574 0x000DC /* Ext. Interrupt Auto Clear - RW */
#define E1000_EIAC_MASK_82574 0x01F00000
-#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */
+#define E1000_IVAR_INT_ALLOC_VALID 0x8
-#define E1000_RXCFGL 0x0B634 /* TimeSync Rx EtherType & Msg Type Reg - RW */
+/* Manageability Operation Mode mask */
+#define E1000_NVM_INIT_CTRL2_MNGM 0x6000
#define E1000_BASE1000T_STATUS 10
#define E1000_IDLE_ERROR_COUNT_MASK 0xFF
diff --git a/sys/dev/e1000/e1000_82575.c b/sys/dev/e1000/e1000_82575.c
index 10653f8824c8..38770a327b16 100644
--- a/sys/dev/e1000/e1000_82575.c
+++ b/sys/dev/e1000/e1000_82575.c
@@ -278,6 +278,11 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
if (ret_val)
goto out;
}
+ if (phy->id == M88E1543_E_PHY_ID) {
+ ret_val = e1000_initialize_M88E1543_phy(hw);
+ if (ret_val)
+ goto out;
+ }
break;
case IGP03E1000_E_PHY_ID:
case IGP04E1000_E_PHY_ID:
@@ -1235,7 +1240,7 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw)
DEBUGFUNC("e1000_check_for_link_media_swap");
- /* Check the copper medium. */
+ /* Check for copper. */
ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
if (ret_val)
return ret_val;
@@ -1247,7 +1252,7 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw)
if (data & E1000_M88E1112_STATUS_LINK)
port = E1000_MEDIA_PORT_COPPER;
- /* Check the other medium. */
+ /* Check for other. */
ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1);
if (ret_val)
return ret_val;
@@ -1256,11 +1261,6 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /* reset page to 0 */
- ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
- if (ret_val)
- return ret_val;
-
if (data & E1000_M88E1112_STATUS_LINK)
port = E1000_MEDIA_PORT_OTHER;
@@ -1268,8 +1268,20 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw)
if (port && (hw->dev_spec._82575.media_port != port)) {
hw->dev_spec._82575.media_port = port;
hw->dev_spec._82575.media_changed = TRUE;
+ }
+
+ if (port == E1000_MEDIA_PORT_COPPER) {
+ /* reset page to 0 */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
+ if (ret_val)
+ return ret_val;
+ e1000_check_for_link_82575(hw);
} else {
- ret_val = e1000_check_for_link_82575(hw);
+ e1000_check_for_link_82575(hw);
+ /* reset page to 0 */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
+ if (ret_val)
+ return ret_val;
}
return E1000_SUCCESS;
@@ -2136,7 +2148,13 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw)
u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
int i, ms_wait;
- DEBUGFUNC("e1000_rx_fifo_workaround_82575");
+ DEBUGFUNC("e1000_rx_fifo_flush_82575");
+
+ /* disable IPv6 options as per hardware errata */
+ rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+ rfctl |= E1000_RFCTL_IPV6_EX_DIS;
+ E1000_WRITE_REG(hw, E1000_RFCTL, rfctl);
+
if (hw->mac.type != e1000_82575 ||
!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN))
return;
@@ -2164,7 +2182,6 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw)
* incoming packets are rejected. Set enable and wait 2ms so that
* any packet that was coming in as RCTL.EN was set is flushed
*/
- rfctl = E1000_READ_REG(hw, E1000_RFCTL);
E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF);
rlpml = E1000_READ_REG(hw, E1000_RLPML);
@@ -2806,7 +2823,7 @@ s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data)
* e1000_initialize_M88E1512_phy - Initialize M88E1512 PHY
* @hw: pointer to the HW structure
*
- * Initialize Marverl 1512 to work correctly with Avoton.
+ * Initialize Marvell 1512 to work correctly with Avoton.
**/
s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw)
{
@@ -2892,13 +2909,114 @@ out:
}
/**
+ * e1000_initialize_M88E1543_phy - Initialize M88E1543 PHY
+ * @hw: pointer to the HW structure
+ *
+ * Initialize Marvell 1543 to work correctly with Avoton.
+ **/
+s32 e1000_initialize_M88E1543_phy(struct e1000_hw *hw)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val = E1000_SUCCESS;
+
+ DEBUGFUNC("e1000_initialize_M88E1543_phy");
+
+ /* Check if this is correct PHY. */
+ if (phy->id != M88E1543_E_PHY_ID)
+ goto out;
+
+ /* Switch to PHY page 0xFF. */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xDC0C);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159);
+ if (ret_val)
+ goto out;
+
+ /* Switch to PHY page 0xFB. */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0xC00D);
+ if (ret_val)
+ goto out;
+
+ /* Switch to PHY page 0x12. */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12);
+ if (ret_val)
+ goto out;
+
+ /* Change mode to SGMII-to-Copper */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001);
+ if (ret_val)
+ goto out;
+
+ /* Switch to PHY page 1. */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x1);
+ if (ret_val)
+ goto out;
+
+ /* Change mode to 1000BASE-X/SGMII and autoneg enable; reset */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_FIBER_CTRL, 0x9140);
+ if (ret_val)
+ goto out;
+
+ /* Return the PHY to page 0. */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.commit(hw);
+ if (ret_val) {
+ DEBUGOUT("Error committing the PHY changes\n");
+ return ret_val;
+ }
+
+ msec_delay(1000);
+out:
+ return ret_val;
+}
+
+/**
* e1000_set_eee_i350 - Enable/disable EEE support
* @hw: pointer to the HW structure
+ * @adv1g: boolean flag enabling 1G EEE advertisement
+ * @adv100m: boolean flag enabling 100M EEE advertisement
*
* Enable/disable EEE based on setting in dev_spec structure.
*
**/
-s32 e1000_set_eee_i350(struct e1000_hw *hw)
+s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M)
{
u32 ipcnfg, eeer;
@@ -2914,7 +3032,16 @@ s32 e1000_set_eee_i350(struct e1000_hw *hw)
if (!(hw->dev_spec._82575.eee_disable)) {
u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU);
- ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
+ if (adv100M)
+ ipcnfg |= E1000_IPCNFG_EEE_100M_AN;
+ else
+ ipcnfg &= ~E1000_IPCNFG_EEE_100M_AN;
+
+ if (adv1G)
+ ipcnfg |= E1000_IPCNFG_EEE_1G_AN;
+ else
+ ipcnfg &= ~E1000_IPCNFG_EEE_1G_AN;
+
eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
E1000_EEER_LPI_FC);
@@ -2938,11 +3065,13 @@ out:
/**
* e1000_set_eee_i354 - Enable/disable EEE support
* @hw: pointer to the HW structure
+ * @adv1g: boolean flag enabling 1G EEE advertisement
+ * @adv100m: boolean flag enabling 100M EEE advertisement
*
* Enable/disable EEE legacy mode based on setting in dev_spec structure.
*
**/
-s32 e1000_set_eee_i354(struct e1000_hw *hw)
+s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M)
{
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val = E1000_SUCCESS;
@@ -2984,8 +3113,16 @@ s32 e1000_set_eee_i354(struct e1000_hw *hw)
if (ret_val)
goto out;
- phy_data |= E1000_EEE_ADV_100_SUPPORTED |
- E1000_EEE_ADV_1000_SUPPORTED;
+ if (adv100M)
+ phy_data |= E1000_EEE_ADV_100_SUPPORTED;
+ else
+ phy_data &= ~E1000_EEE_ADV_100_SUPPORTED;
+
+ if (adv1G)
+ phy_data |= E1000_EEE_ADV_1000_SUPPORTED;
+ else
+ phy_data &= ~E1000_EEE_ADV_1000_SUPPORTED;
+
ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
E1000_EEE_ADV_DEV_I354,
phy_data);
diff --git a/sys/dev/e1000/e1000_82575.h b/sys/dev/e1000/e1000_82575.h
index 503fdce305d6..45fe132e4a40 100644
--- a/sys/dev/e1000/e1000_82575.h
+++ b/sys/dev/e1000/e1000_82575.h
@@ -495,10 +495,11 @@ void e1000_rlpml_set_vf(struct e1000_hw *, u16);
s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type type);
u16 e1000_rxpbs_adjust_82580(u32 data);
s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data);
-s32 e1000_set_eee_i350(struct e1000_hw *);
-s32 e1000_set_eee_i354(struct e1000_hw *);
+s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M);
+s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M);
s32 e1000_get_eee_status_i354(struct e1000_hw *, bool *);
s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw);
+s32 e1000_initialize_M88E1543_phy(struct e1000_hw *hw);
/* I2C SDA and SCL timing parameters for standard mode */
#define E1000_I2C_T_HD_STA 4
diff --git a/sys/dev/e1000/e1000_api.c b/sys/dev/e1000/e1000_api.c
index 5db22db16f0d..28379cc572d3 100644
--- a/sys/dev/e1000/e1000_api.c
+++ b/sys/dev/e1000/e1000_api.c
@@ -299,6 +299,13 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_PCH_I218_V3:
mac->type = e1000_pch_lpt;
break;
+ case E1000_DEV_ID_PCH_SPT_I219_LM:
+ case E1000_DEV_ID_PCH_SPT_I219_V:
+ case E1000_DEV_ID_PCH_SPT_I219_LM2:
+ case E1000_DEV_ID_PCH_SPT_I219_V2:
+ case E1000_DEV_ID_PCH_LBG_I219_LM3:
+ mac->type = e1000_pch_spt;
+ break;
case E1000_DEV_ID_82575EB_COPPER:
case E1000_DEV_ID_82575EB_FIBER_SERDES:
case E1000_DEV_ID_82575GB_QUAD_COPPER:
@@ -449,6 +456,7 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
case e1000_pchlan:
case e1000_pch2lan:
case e1000_pch_lpt:
+ case e1000_pch_spt:
e1000_init_function_pointers_ich8lan(hw);
break;
case e1000_82575:
diff --git a/sys/dev/e1000/e1000_defines.h b/sys/dev/e1000/e1000_defines.h
index 9472ca4c4d4d..e33fe0fb7982 100644
--- a/sys/dev/e1000/e1000_defines.h
+++ b/sys/dev/e1000/e1000_defines.h
@@ -197,6 +197,8 @@
#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */
#define E1000_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */
+#define E1000_RCTL_RDMTS_HEX 0x00010000
+#define E1000_RCTL_RDMTS1_HEX E1000_RCTL_RDMTS_HEX
#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */
#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */
#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */
@@ -753,6 +755,12 @@
#define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */
#define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */
+/* HH Time Sync */
+#define E1000_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0x0000F000 /* max delay */
+#define E1000_TSYNCTXCTL_SYNC_COMP_ERR 0x20000000 /* sync err */
+#define E1000_TSYNCTXCTL_SYNC_COMP 0x40000000 /* sync complete */
+#define E1000_TSYNCTXCTL_START_SYNC 0x80000000 /* initiate sync */
+
#define E1000_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */
#define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */
#define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00
@@ -849,6 +857,7 @@
#define E1000_M88E1543_PAGE_ADDR 0x16 /* Page Offset Register */
#define E1000_M88E1543_EEE_CTRL_1 0x0
#define E1000_M88E1543_EEE_CTRL_1_MS 0x0001 /* EEE Master/Slave */
+#define E1000_M88E1543_FIBER_CTRL 0x0 /* Fiber Control Register */
#define E1000_EEE_ADV_DEV_I354 7
#define E1000_EEE_ADV_ADDR_I354 60
#define E1000_EEE_ADV_100_SUPPORTED (1 << 1) /* 100BaseTx EEE Supported */
@@ -1020,9 +1029,7 @@
/* NVM Addressing bits based on type 0=small, 1=large */
#define E1000_EECD_ADDR_BITS 0x00000400
#define E1000_EECD_TYPE 0x00002000 /* NVM Type (1-SPI, 0-Microwire) */
-#ifndef E1000_NVM_GRANT_ATTEMPTS
#define E1000_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */
-#endif
#define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */
#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */
#define E1000_EECD_SIZE_EX_SHIFT 11
diff --git a/sys/dev/e1000/e1000_hw.h b/sys/dev/e1000/e1000_hw.h
index 8ae4b202fd1e..1792e14ef38a 100644
--- a/sys/dev/e1000/e1000_hw.h
+++ b/sys/dev/e1000/e1000_hw.h
@@ -137,6 +137,11 @@ struct e1000_hw;
#define E1000_DEV_ID_PCH_I218_V2 0x15A1
#define E1000_DEV_ID_PCH_I218_LM3 0x15A2 /* Wildcat Point PCH */
#define E1000_DEV_ID_PCH_I218_V3 0x15A3 /* Wildcat Point PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_LM 0x156F /* Sunrise Point PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_V 0x1570 /* Sunrise Point PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_LM2 0x15B7 /* Sunrise Point-H PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_V2 0x15B8 /* Sunrise Point-H PCH */
+#define E1000_DEV_ID_PCH_LBG_I219_LM3 0x15B9 /* LEWISBURG PCH */
#define E1000_DEV_ID_82576 0x10C9
#define E1000_DEV_ID_82576_FIBER 0x10E6
#define E1000_DEV_ID_82576_SERDES 0x10E7
@@ -222,6 +227,7 @@ enum e1000_mac_type {
e1000_pchlan,
e1000_pch2lan,
e1000_pch_lpt,
+ e1000_pch_spt,
e1000_82575,
e1000_82576,
e1000_82580,
@@ -805,7 +811,7 @@ struct e1000_mac_info {
enum e1000_serdes_link_state serdes_link_state;
bool serdes_has_link;
bool tx_pkt_filtering;
- u32 max_frame_size;
+ u32 max_frame_size;
};
struct e1000_phy_info {
diff --git a/sys/dev/e1000/e1000_i210.c b/sys/dev/e1000/e1000_i210.c
index 563f11a1d27e..cd8d7c7e1f56 100644
--- a/sys/dev/e1000/e1000_i210.c
+++ b/sys/dev/e1000/e1000_i210.c
@@ -883,6 +883,35 @@ static s32 e1000_pll_workaround_i210(struct e1000_hw *hw)
}
/**
+ * e1000_get_cfg_done_i210 - Read config done bit
+ * @hw: pointer to the HW structure
+ *
+ * Read the management control register for the config done bit for
+ * completion status. NOTE: silicon which is EEPROM-less will fail trying
+ * to read the config done bit, so an error is *ONLY* logged and returns
+ * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon
+ * would not be able to be reset or change link.
+ **/
+static s32 e1000_get_cfg_done_i210(struct e1000_hw *hw)
+{
+ s32 timeout = PHY_CFG_TIMEOUT;
+ u32 mask = E1000_NVM_CFG_DONE_PORT_0;
+
+ DEBUGFUNC("e1000_get_cfg_done_i210");
+
+ while (timeout) {
+ if (E1000_READ_REG(hw, E1000_EEMNGCTL_I210) & mask)
+ break;
+ msec_delay(1);
+ timeout--;
+ }
+ if (!timeout)
+ DEBUGOUT("MNG configuration cycle has not completed.\n");
+
+ return E1000_SUCCESS;
+}
+
+/**
* e1000_init_hw_i210 - Init hw for I210/I211
* @hw: pointer to the HW structure
*
@@ -899,6 +928,7 @@ s32 e1000_init_hw_i210(struct e1000_hw *hw)
if (ret_val != E1000_SUCCESS)
return ret_val;
}
+ hw->phy.ops.get_cfg_done = e1000_get_cfg_done_i210;
ret_val = e1000_init_hw_82575(hw);
return ret_val;
}
diff --git a/sys/dev/e1000/e1000_ich8lan.c b/sys/dev/e1000/e1000_ich8lan.c
index 75fcade3703b..9b9a090422e9 100644
--- a/sys/dev/e1000/e1000_ich8lan.c
+++ b/sys/dev/e1000/e1000_ich8lan.c
@@ -92,10 +92,13 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw,
bool active);
static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data);
+static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data);
static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw);
static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw);
+static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw);
static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw,
u16 *data);
static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw);
@@ -123,6 +126,14 @@ static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw,
u32 offset, u8 *data);
static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
u8 size, u16 *data);
+static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
+ u32 *data);
+static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw,
+ u32 offset, u32 *data);
+static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw,
+ u32 offset, u32 data);
+static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw,
+ u32 offset, u32 dword);
static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw,
u32 offset, u16 *data);
static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
@@ -232,16 +243,21 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
if (ret_val)
return FALSE;
out:
- if (hw->mac.type == e1000_pch_lpt) {
- /* Unforce SMBus mode in PHY */
- hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL, &phy_reg);
- phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
- hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL, phy_reg);
+ if ((hw->mac.type == e1000_pch_lpt) ||
+ (hw->mac.type == e1000_pch_spt)) {
+ /* Only unforce SMBus if ME is not active */
+ if (!(E1000_READ_REG(hw, E1000_FWSM) &
+ E1000_ICH_FWSM_FW_VALID)) {
+ /* Unforce SMBus mode in PHY */
+ hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL, &phy_reg);
+ phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
+ hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL, phy_reg);
- /* Unforce SMBus mode in MAC */
- mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
- mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
- E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
+ /* Unforce SMBus mode in MAC */
+ mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
+ mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
+ }
}
return TRUE;
@@ -328,6 +344,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
*/
switch (hw->mac.type) {
case e1000_pch_lpt:
+ case e1000_pch_spt:
if (e1000_phy_is_accessible_pchlan(hw))
break;
@@ -475,6 +492,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
/* fall-through */
case e1000_pch2lan:
case e1000_pch_lpt:
+ case e1000_pch_spt:
/* In case the PHY needs to be in mdio slow mode,
* set slow mode and try to get the PHY id again.
*/
@@ -617,36 +635,57 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
u32 gfpreg, sector_base_addr, sector_end_addr;
u16 i;
+ u32 nvm_size;
DEBUGFUNC("e1000_init_nvm_params_ich8lan");
- /* Can't read flash registers if the register set isn't mapped. */
nvm->type = e1000_nvm_flash_sw;
- if (!hw->flash_address) {
- DEBUGOUT("ERROR: Flash registers not mapped\n");
- return -E1000_ERR_CONFIG;
- }
- gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG);
+ if (hw->mac.type == e1000_pch_spt) {
+ /* in SPT, gfpreg doesn't exist. NVM size is taken from the
+ * STRAP register. This is because in SPT the GbE Flash region
+ * is no longer accessed through the flash registers. Instead,
+ * the mechanism has changed, and the Flash region access
+ * registers are now implemented in GbE memory space.
+ */
+ nvm->flash_base_addr = 0;
+ nvm_size =
+ (((E1000_READ_REG(hw, E1000_STRAP) >> 1) & 0x1F) + 1)
+ * NVM_SIZE_MULTIPLIER;
+ nvm->flash_bank_size = nvm_size / 2;
+ /* Adjust to word count */
+ nvm->flash_bank_size /= sizeof(u16);
+ /* Set the base address for flash register access */
+ hw->flash_address = hw->hw_addr + E1000_FLASH_BASE_ADDR;
+ } else {
+ /* Can't read flash registers if register set isn't mapped. */
+ if (!hw->flash_address) {
+ DEBUGOUT("ERROR: Flash registers not mapped\n");
+ return -E1000_ERR_CONFIG;
+ }
- /* sector_X_addr is a "sector"-aligned address (4096 bytes)
- * Add 1 to sector_end_addr since this sector is included in
- * the overall size.
- */
- sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
- sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1;
+ gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG);
- /* flash_base_addr is byte-aligned */
- nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT;
+ /* sector_X_addr is a "sector"-aligned address (4096 bytes)
+ * Add 1 to sector_end_addr since this sector is included in
+ * the overall size.
+ */
+ sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
+ sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1;
- /* find total size of the NVM, then cut in half since the total
- * size represents two separate NVM banks.
- */
- nvm->flash_bank_size = ((sector_end_addr - sector_base_addr)
- << FLASH_SECTOR_ADDR_SHIFT);
- nvm->flash_bank_size /= 2;
- /* Adjust to word count */
- nvm->flash_bank_size /= sizeof(u16);
+ /* flash_base_addr is byte-aligned */
+ nvm->flash_base_addr = sector_base_addr
+ << FLASH_SECTOR_ADDR_SHIFT;
+
+ /* find total size of the NVM, then cut in half since the total
+ * size represents two separate NVM banks.
+ */
+ nvm->flash_bank_size = ((sector_end_addr - sector_base_addr)
+ << FLASH_SECTOR_ADDR_SHIFT);
+ nvm->flash_bank_size /= 2;
+ /* Adjust to word count */
+ nvm->flash_bank_size /= sizeof(u16);
+ }
nvm->word_size = E1000_SHADOW_RAM_WORDS;
@@ -662,8 +701,13 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
/* Function Pointers */
nvm->ops.acquire = e1000_acquire_nvm_ich8lan;
nvm->ops.release = e1000_release_nvm_ich8lan;
- nvm->ops.read = e1000_read_nvm_ich8lan;
- nvm->ops.update = e1000_update_nvm_checksum_ich8lan;
+ if (hw->mac.type == e1000_pch_spt) {
+ nvm->ops.read = e1000_read_nvm_spt;
+ nvm->ops.update = e1000_update_nvm_checksum_spt;
+ } else {
+ nvm->ops.read = e1000_read_nvm_ich8lan;
+ nvm->ops.update = e1000_update_nvm_checksum_ich8lan;
+ }
nvm->ops.valid_led_default = e1000_valid_led_default_ich8lan;
nvm->ops.validate = e1000_validate_nvm_checksum_ich8lan;
nvm->ops.write = e1000_write_nvm_ich8lan;
@@ -681,9 +725,6 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
-#if defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT)
- u16 pci_cfg;
-#endif /* QV_RELEASE || !defined(NO_PCH_LPT_B0_SUPPORT) */
DEBUGFUNC("e1000_init_mac_params_ich8lan");
@@ -752,15 +793,12 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
mac->ops.rar_set = e1000_rar_set_pch2lan;
/* fall-through */
case e1000_pch_lpt:
+ case e1000_pch_spt:
/* multicast address update for pch2 */
mac->ops.update_mc_addr_list =
e1000_update_mc_addr_list_pch2lan;
+ /* fall-through */
case e1000_pchlan:
-#if defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT)
- /* save PCH revision_id */
- e1000_read_pci_cfg(hw, E1000_PCI_REVISION_ID_REG, &pci_cfg);
- hw->revision_id = (u8)(pci_cfg &= 0x000F);
-#endif /* QV_RELEASE || !defined(NO_PCH_LPT_B0_SUPPORT) */
/* check management mode */
mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
/* ID LED init */
@@ -777,7 +815,8 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
break;
}
- if (mac->type == e1000_pch_lpt) {
+ if ((mac->type == e1000_pch_lpt) ||
+ (mac->type == e1000_pch_spt)) {
mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES;
mac->ops.rar_set = e1000_rar_set_pch_lpt;
mac->ops.setup_physical_interface = e1000_setup_copper_link_pch_lpt;
@@ -1007,8 +1046,9 @@ release:
/* clear FEXTNVM6 bit 8 on link down or 10/100 */
fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK;
- if (!link || ((status & E1000_STATUS_SPEED_100) &&
- (status & E1000_STATUS_FD)))
+ if ((hw->phy.revision > 5) || !link ||
+ ((status & E1000_STATUS_SPEED_100) &&
+ (status & E1000_STATUS_FD)))
goto update_fextnvm6;
ret_val = hw->phy.ops.read_reg(hw, I217_INBAND_CTRL, &reg);
@@ -1221,6 +1261,7 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
u32 mac_reg;
s32 ret_val = E1000_SUCCESS;
u16 phy_reg;
+ u16 oem_reg = 0;
if ((hw->mac.type < e1000_pch_lpt) ||
(hw->device_id == E1000_DEV_ID_PCH_LPT_I217_LM) ||
@@ -1276,6 +1317,25 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
+ /* Si workaround for ULP entry flow on i127/rev6 h/w. Enable
+ * LPLU and disable Gig speed when entering ULP
+ */
+ if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6)) {
+ ret_val = e1000_read_phy_reg_hv_locked(hw, HV_OEM_BITS,
+ &oem_reg);
+ if (ret_val)
+ goto release;
+
+ phy_reg = oem_reg;
+ phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS;
+
+ ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
+ phy_reg);
+
+ if (ret_val)
+ goto release;
+ }
+
/* Set Inband ULP Exit, Reset to SMBus mode and
* Disable SMBus Release on PERST# in PHY
*/
@@ -1287,10 +1347,15 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
if (to_sx) {
if (E1000_READ_REG(hw, E1000_WUFC) & E1000_WUFC_LNKC)
phy_reg |= I218_ULP_CONFIG1_WOL_HOST;
+ else
+ phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST;
phy_reg |= I218_ULP_CONFIG1_STICKY_ULP;
+ phy_reg &= ~I218_ULP_CONFIG1_INBAND_EXIT;
} else {
phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT;
+ phy_reg &= ~I218_ULP_CONFIG1_STICKY_ULP;
+ phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST;
}
e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
@@ -1302,6 +1367,15 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
/* Commit ULP changes in PHY by starting auto ULP configuration */
phy_reg |= I218_ULP_CONFIG1_START;
e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
+
+ if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6) &&
+ to_sx && (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) {
+ ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
+ oem_reg);
+ if (ret_val)
+ goto release;
+ }
+
release:
hw->phy.ops.release(hw);
out:
@@ -1352,10 +1426,10 @@ s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force)
E1000_WRITE_REG(hw, E1000_H2ME, mac_reg);
}
- /* Poll up to 100msec for ME to clear ULP_CFG_DONE */
+ /* Poll up to 300msec for ME to clear ULP_CFG_DONE. */
while (E1000_READ_REG(hw, E1000_FWSM) &
E1000_FWSM_ULP_CFG_DONE) {
- if (i++ == 10) {
+ if (i++ == 30) {
ret_val = -E1000_ERR_PHY;
goto out;
}
@@ -1429,6 +1503,8 @@ s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force)
I218_ULP_CONFIG1_RESET_TO_SMBUS |
I218_ULP_CONFIG1_WOL_HOST |
I218_ULP_CONFIG1_INBAND_EXIT |
+ I218_ULP_CONFIG1_EN_ULP_LANPHYPC |
+ I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST |
I218_ULP_CONFIG1_DISABLE_SMB_PERST);
e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
@@ -1467,7 +1543,8 @@ out:
static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
- s32 ret_val;
+ s32 ret_val, tipg_reg = 0;
+ u16 emi_addr, emi_val = 0;
bool link;
u16 phy_reg;
@@ -1500,35 +1577,119 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
* the IPG and reduce Rx latency in the PHY.
*/
if (((hw->mac.type == e1000_pch2lan) ||
- (hw->mac.type == e1000_pch_lpt)) && link) {
- u32 reg;
- reg = E1000_READ_REG(hw, E1000_STATUS);
- if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) {
- u16 emi_addr;
+ (hw->mac.type == e1000_pch_lpt) ||
+ (hw->mac.type == e1000_pch_spt)) && link) {
+ u16 speed, duplex;
- reg = E1000_READ_REG(hw, E1000_TIPG);
- reg &= ~E1000_TIPG_IPGT_MASK;
- reg |= 0xFF;
- E1000_WRITE_REG(hw, E1000_TIPG, reg);
+ e1000_get_speed_and_duplex_copper_generic(hw, &speed, &duplex);
+ tipg_reg = E1000_READ_REG(hw, E1000_TIPG);
+ tipg_reg &= ~E1000_TIPG_IPGT_MASK;
+ if (duplex == HALF_DUPLEX && speed == SPEED_10) {
+ tipg_reg |= 0xFF;
/* Reduce Rx latency in analog PHY */
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- return ret_val;
+ emi_val = 0;
+ } else if (hw->mac.type == e1000_pch_spt &&
+ duplex == FULL_DUPLEX && speed != SPEED_1000) {
+ tipg_reg |= 0xC;
+ emi_val = 1;
+ } else {
+ /* Roll back the default values */
+ tipg_reg |= 0x08;
+ emi_val = 1;
+ }
+
+ E1000_WRITE_REG(hw, E1000_TIPG, tipg_reg);
- if (hw->mac.type == e1000_pch2lan)
- emi_addr = I82579_RX_CONFIG;
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ if (hw->mac.type == e1000_pch2lan)
+ emi_addr = I82579_RX_CONFIG;
+ else
+ emi_addr = I217_RX_CONFIG;
+ ret_val = e1000_write_emi_reg_locked(hw, emi_addr, emi_val);
+
+ if (hw->mac.type == e1000_pch_lpt ||
+ hw->mac.type == e1000_pch_spt) {
+ u16 phy_reg;
+
+ hw->phy.ops.read_reg_locked(hw, I217_PLL_CLOCK_GATE_REG,
+ &phy_reg);
+ phy_reg &= ~I217_PLL_CLOCK_GATE_MASK;
+ if (speed == SPEED_100 || speed == SPEED_10)
+ phy_reg |= 0x3E8;
else
- emi_addr = I217_RX_CONFIG;
- ret_val = e1000_write_emi_reg_locked(hw, emi_addr, 0);
+ phy_reg |= 0xFA;
+ hw->phy.ops.write_reg_locked(hw,
+ I217_PLL_CLOCK_GATE_REG,
+ phy_reg);
+ }
+ hw->phy.ops.release(hw);
- hw->phy.ops.release(hw);
+ if (ret_val)
+ return ret_val;
- if (ret_val)
- return ret_val;
+ if (hw->mac.type == e1000_pch_spt) {
+ u16 data;
+ u16 ptr_gap;
+
+ if (speed == SPEED_1000) {
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = hw->phy.ops.read_reg_locked(hw,
+ PHY_REG(776, 20),
+ &data);
+ if (ret_val) {
+ hw->phy.ops.release(hw);
+ return ret_val;
+ }
+
+ ptr_gap = (data & (0x3FF << 2)) >> 2;
+ if (ptr_gap < 0x18) {
+ data &= ~(0x3FF << 2);
+ data |= (0x18 << 2);
+ ret_val =
+ hw->phy.ops.write_reg_locked(hw,
+ PHY_REG(776, 20), data);
+ }
+ hw->phy.ops.release(hw);
+ if (ret_val)
+ return ret_val;
+ } else {
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = hw->phy.ops.write_reg_locked(hw,
+ PHY_REG(776, 20),
+ 0xC023);
+ hw->phy.ops.release(hw);
+ if (ret_val)
+ return ret_val;
+
+ }
}
}
+ /* I217 Packet Loss issue:
+ * ensure that FEXTNVM4 Beacon Duration is set correctly
+ * on power up.
+ * Set the Beacon Duration for I217 to 8 usec
+ */
+ if ((hw->mac.type == e1000_pch_lpt) ||
+ (hw->mac.type == e1000_pch_spt)) {
+ u32 mac_reg;
+
+ mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM4);
+ mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
+ mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
+ E1000_WRITE_REG(hw, E1000_FEXTNVM4, mac_reg);
+ }
+
/* Work-around I218 hang issue */
if ((hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
(hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
@@ -1538,7 +1699,8 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
if (ret_val)
return ret_val;
}
- if (hw->mac.type == e1000_pch_lpt) {
+ if ((hw->mac.type == e1000_pch_lpt) ||
+ (hw->mac.type == e1000_pch_spt)) {
/* Set platform power management values for
* Latency Tolerance Reporting (LTR)
* Optimized Buffer Flush/Fill (OBFF)
@@ -1551,6 +1713,19 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
/* Clear link partner's EEE ability */
hw->dev_spec.ich8lan.eee_lp_ability = 0;
+ /* FEXTNVM6 K1-off workaround */
+ if (hw->mac.type == e1000_pch_spt) {
+ u32 pcieanacfg = E1000_READ_REG(hw, E1000_PCIEANACFG);
+ u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
+
+ if (pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE)
+ fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE;
+ else
+ fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE;
+
+ E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6);
+ }
+
if (!link)
return E1000_SUCCESS; /* No link detected */
@@ -1644,6 +1819,7 @@ void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw)
case e1000_pchlan:
case e1000_pch2lan:
case e1000_pch_lpt:
+ case e1000_pch_spt:
hw->phy.ops.init_params = e1000_init_phy_params_pchlan;
break;
default:
@@ -2026,7 +2202,7 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
continue;
}
blocked = FALSE;
- } while (blocked && (i++ < 10));
+ } while (blocked && (i++ < 30));
return blocked ? E1000_BLK_PHY_RESET : E1000_SUCCESS;
}
@@ -2107,6 +2283,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
case e1000_pchlan:
case e1000_pch2lan:
case e1000_pch_lpt:
+ case e1000_pch_spt:
sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
break;
default:
@@ -3216,12 +3393,47 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
struct e1000_nvm_info *nvm = &hw->nvm;
u32 bank1_offset = nvm->flash_bank_size * sizeof(u16);
u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1;
+ u32 nvm_dword = 0;
u8 sig_byte = 0;
s32 ret_val;
DEBUGFUNC("e1000_valid_nvm_bank_detect_ich8lan");
switch (hw->mac.type) {
+ case e1000_pch_spt:
+ bank1_offset = nvm->flash_bank_size;
+ act_offset = E1000_ICH_NVM_SIG_WORD;
+
+ /* set bank to 0 in case flash read fails */
+ *bank = 0;
+
+ /* Check bank 0 */
+ ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset,
+ &nvm_dword);
+ if (ret_val)
+ return ret_val;
+ sig_byte = (u8)((nvm_dword & 0xFF00) >> 8);
+ if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
+ E1000_ICH_NVM_SIG_VALUE) {
+ *bank = 0;
+ return E1000_SUCCESS;
+ }
+
+ /* Check bank 1 */
+ ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset +
+ bank1_offset,
+ &nvm_dword);
+ if (ret_val)
+ return ret_val;
+ sig_byte = (u8)((nvm_dword & 0xFF00) >> 8);
+ if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
+ E1000_ICH_NVM_SIG_VALUE) {
+ *bank = 1;
+ return E1000_SUCCESS;
+ }
+
+ DEBUGOUT("ERROR: No valid NVM bank present\n");
+ return -E1000_ERR_NVM;
case e1000_ich8lan:
case e1000_ich9lan:
eecd = E1000_READ_REG(hw, E1000_EECD);
@@ -3269,6 +3481,99 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
}
/**
+ * e1000_read_nvm_spt - NVM access for SPT
+ * @hw: pointer to the HW structure
+ * @offset: The offset (in bytes) of the word(s) to read.
+ * @words: Size of data to read in words.
+ * @data: pointer to the word(s) to read at offset.
+ *
+ * Reads a word(s) from the NVM
+ **/
+static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
+{
+ struct e1000_nvm_info *nvm = &hw->nvm;
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
+ u32 act_offset;
+ s32 ret_val = E1000_SUCCESS;
+ u32 bank = 0;
+ u32 dword = 0;
+ u16 offset_to_read;
+ u16 i;
+
+ DEBUGFUNC("e1000_read_nvm_spt");
+
+ if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
+ (words == 0)) {
+ DEBUGOUT("nvm parameter(s) out of bounds\n");
+ ret_val = -E1000_ERR_NVM;
+ goto out;
+ }
+
+ nvm->ops.acquire(hw);
+
+ ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
+ if (ret_val != E1000_SUCCESS) {
+ DEBUGOUT("Could not detect valid bank, assuming bank 0\n");
+ bank = 0;
+ }
+
+ act_offset = (bank) ? nvm->flash_bank_size : 0;
+ act_offset += offset;
+
+ ret_val = E1000_SUCCESS;
+
+ for (i = 0; i < words; i += 2) {
+ if (words - i == 1) {
+ if (dev_spec->shadow_ram[offset+i].modified) {
+ data[i] = dev_spec->shadow_ram[offset+i].value;
+ } else {
+ offset_to_read = act_offset + i -
+ ((act_offset + i) % 2);
+ ret_val =
+ e1000_read_flash_dword_ich8lan(hw,
+ offset_to_read,
+ &dword);
+ if (ret_val)
+ break;
+ if ((act_offset + i) % 2 == 0)
+ data[i] = (u16)(dword & 0xFFFF);
+ else
+ data[i] = (u16)((dword >> 16) & 0xFFFF);
+ }
+ } else {
+ offset_to_read = act_offset + i;
+ if (!(dev_spec->shadow_ram[offset+i].modified) ||
+ !(dev_spec->shadow_ram[offset+i+1].modified)) {
+ ret_val =
+ e1000_read_flash_dword_ich8lan(hw,
+ offset_to_read,
+ &dword);
+ if (ret_val)
+ break;
+ }
+ if (dev_spec->shadow_ram[offset+i].modified)
+ data[i] = dev_spec->shadow_ram[offset+i].value;
+ else
+ data[i] = (u16) (dword & 0xFFFF);
+ if (dev_spec->shadow_ram[offset+i].modified)
+ data[i+1] =
+ dev_spec->shadow_ram[offset+i+1].value;
+ else
+ data[i+1] = (u16) (dword >> 16 & 0xFFFF);
+ }
+ }
+
+ nvm->ops.release(hw);
+
+out:
+ if (ret_val)
+ DEBUGOUT1("NVM read error: %d\n", ret_val);
+
+ return ret_val;
+}
+
+/**
* e1000_read_nvm_ich8lan - Read word(s) from the NVM
* @hw: pointer to the HW structure
* @offset: The offset (in bytes) of the word(s) to read.
@@ -3355,7 +3660,11 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
/* Clear FCERR and DAEL in hw status by writing 1 */
hsfsts.hsf_status.flcerr = 1;
hsfsts.hsf_status.dael = 1;
- E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
+ if (hw->mac.type == e1000_pch_spt)
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ hsfsts.regval & 0xFFFF);
+ else
+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
/* Either we should have a hardware SPI cycle in progress
* bit to check against, in order to start a new cycle or
@@ -3371,7 +3680,12 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
* Begin by setting Flash Cycle Done.
*/
hsfsts.hsf_status.flcdone = 1;
- E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
+ if (hw->mac.type == e1000_pch_spt)
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ hsfsts.regval & 0xFFFF);
+ else
+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
+ hsfsts.regval);
ret_val = E1000_SUCCESS;
} else {
s32 i;
@@ -3393,8 +3707,12 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
* now set the Flash Cycle Done.
*/
hsfsts.hsf_status.flcdone = 1;
- E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
- hsfsts.regval);
+ if (hw->mac.type == e1000_pch_spt)
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ hsfsts.regval & 0xFFFF);
+ else
+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
+ hsfsts.regval);
} else {
DEBUGOUT("Flash controller busy, cannot get access\n");
}
@@ -3419,10 +3737,17 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
DEBUGFUNC("e1000_flash_cycle_ich8lan");
/* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
- hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
+ if (hw->mac.type == e1000_pch_spt)
+ hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
+ else
+ hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
hsflctl.hsf_ctrl.flcgo = 1;
- E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
+ if (hw->mac.type == e1000_pch_spt)
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ hsflctl.regval << 16);
+ else
+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
/* wait till FDONE bit is set to 1 */
do {
@@ -3439,6 +3764,29 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
}
/**
+ * e1000_read_flash_dword_ich8lan - Read dword from flash
+ * @hw: pointer to the HW structure
+ * @offset: offset to data location
+ * @data: pointer to the location for storing the data
+ *
+ * Reads the flash dword at offset into data. Offset is converted
+ * to bytes before read.
+ **/
+static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, u32 offset,
+ u32 *data)
+{
+ DEBUGFUNC("e1000_read_flash_dword_ich8lan");
+
+ if (!data)
+ return -E1000_ERR_NVM;
+
+ /* Must convert word offset into bytes. */
+ offset <<= 1;
+
+ return e1000_read_flash_data32_ich8lan(hw, offset, data);
+}
+
+/**
* e1000_read_flash_word_ich8lan - Read word from flash
* @hw: pointer to the HW structure
* @offset: offset to data location
@@ -3475,7 +3823,13 @@ static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
s32 ret_val;
u16 word = 0;
- ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
+ /* In SPT, only 32 bits access is supported,
+ * so this function should not be called.
+ */
+ if (hw->mac.type == e1000_pch_spt)
+ return -E1000_ERR_NVM;
+ else
+ ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
if (ret_val)
return ret_val;
@@ -3561,6 +3915,83 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
return ret_val;
}
+/**
+ * e1000_read_flash_data32_ich8lan - Read dword from NVM
+ * @hw: pointer to the HW structure
+ * @offset: The offset (in bytes) of the dword to read.
+ * @data: Pointer to the dword to store the value read.
+ *
+ * Reads a byte or word from the NVM using the flash access registers.
+ **/
+static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
+ u32 *data)
+{
+ union ich8_hws_flash_status hsfsts;
+ union ich8_hws_flash_ctrl hsflctl;
+ u32 flash_linear_addr;
+ s32 ret_val = -E1000_ERR_NVM;
+ u8 count = 0;
+
+ DEBUGFUNC("e1000_read_flash_data_ich8lan");
+
+ if (offset > ICH_FLASH_LINEAR_ADDR_MASK ||
+ hw->mac.type != e1000_pch_spt)
+ return -E1000_ERR_NVM;
+ flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
+ hw->nvm.flash_base_addr);
+
+ do {
+ usec_delay(1);
+ /* Steps */
+ ret_val = e1000_flash_cycle_init_ich8lan(hw);
+ if (ret_val != E1000_SUCCESS)
+ break;
+ /* In SPT, This register is in Lan memory space, not flash.
+ * Therefore, only 32 bit access is supported
+ */
+ hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
+
+ /* 0b/1b corresponds to 1 or 2 byte size, respectively. */
+ hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1;
+ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ;
+ /* In SPT, This register is in Lan memory space, not flash.
+ * Therefore, only 32 bit access is supported
+ */
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ (u32)hsflctl.regval << 16);
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
+
+ ret_val = e1000_flash_cycle_ich8lan(hw,
+ ICH_FLASH_READ_COMMAND_TIMEOUT);
+
+ /* Check if FCERR is set to 1, if set to 1, clear it
+ * and try the whole sequence a few more times, else
+ * read in (shift in) the Flash Data0, the order is
+ * least significant byte first msb to lsb
+ */
+ if (ret_val == E1000_SUCCESS) {
+ *data = E1000_READ_FLASH_REG(hw, ICH_FLASH_FDATA0);
+ break;
+ } else {
+ /* If we've gotten here, then things are probably
+ * completely hosed, but if the error condition is
+ * detected, it won't hurt to give it another try...
+ * ICH_FLASH_CYCLE_REPEAT_COUNT times.
+ */
+ hsfsts.regval = E1000_READ_FLASH_REG16(hw,
+ ICH_FLASH_HSFSTS);
+ if (hsfsts.hsf_status.flcerr) {
+ /* Repeat for some time before giving up. */
+ continue;
+ } else if (!hsfsts.hsf_status.flcdone) {
+ DEBUGOUT("Timeout error - flash cycle did not complete.\n");
+ break;
+ }
+ }
+ } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
+
+ return ret_val;
+}
/**
* e1000_write_nvm_ich8lan - Write word(s) to the NVM
@@ -3599,6 +4030,175 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
}
/**
+ * e1000_update_nvm_checksum_spt - Update the checksum for NVM
+ * @hw: pointer to the HW structure
+ *
+ * The NVM checksum is updated by calling the generic update_nvm_checksum,
+ * which writes the checksum to the shadow ram. The changes in the shadow
+ * ram are then committed to the EEPROM by processing each bank at a time
+ * checking for the modified bit and writing only the pending changes.
+ * After a successful commit, the shadow ram is cleared and is ready for
+ * future writes.
+ **/
+static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw)
+{
+ struct e1000_nvm_info *nvm = &hw->nvm;
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
+ u32 i, act_offset, new_bank_offset, old_bank_offset, bank;
+ s32 ret_val;
+ u32 dword = 0;
+
+ DEBUGFUNC("e1000_update_nvm_checksum_spt");
+
+ ret_val = e1000_update_nvm_checksum_generic(hw);
+ if (ret_val)
+ goto out;
+
+ if (nvm->type != e1000_nvm_flash_sw)
+ goto out;
+
+ nvm->ops.acquire(hw);
+
+ /* We're writing to the opposite bank so if we're on bank 1,
+ * write to bank 0 etc. We also need to erase the segment that
+ * is going to be written
+ */
+ ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
+ if (ret_val != E1000_SUCCESS) {
+ DEBUGOUT("Could not detect valid bank, assuming bank 0\n");
+ bank = 0;
+ }
+
+ if (bank == 0) {
+ new_bank_offset = nvm->flash_bank_size;
+ old_bank_offset = 0;
+ ret_val = e1000_erase_flash_bank_ich8lan(hw, 1);
+ if (ret_val)
+ goto release;
+ } else {
+ old_bank_offset = nvm->flash_bank_size;
+ new_bank_offset = 0;
+ ret_val = e1000_erase_flash_bank_ich8lan(hw, 0);
+ if (ret_val)
+ goto release;
+ }
+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i += 2) {
+ /* Determine whether to write the value stored
+ * in the other NVM bank or a modified value stored
+ * in the shadow RAM
+ */
+ ret_val = e1000_read_flash_dword_ich8lan(hw,
+ i + old_bank_offset,
+ &dword);
+
+ if (dev_spec->shadow_ram[i].modified) {
+ dword &= 0xffff0000;
+ dword |= (dev_spec->shadow_ram[i].value & 0xffff);
+ }
+ if (dev_spec->shadow_ram[i + 1].modified) {
+ dword &= 0x0000ffff;
+ dword |= ((dev_spec->shadow_ram[i + 1].value & 0xffff)
+ << 16);
+ }
+ if (ret_val)
+ break;
+
+ /* If the word is 0x13, then make sure the signature bits
+ * (15:14) are 11b until the commit has completed.
+ * This will allow us to write 10b which indicates the
+ * signature is valid. We want to do this after the write
+ * has completed so that we don't mark the segment valid
+ * while the write is still in progress
+ */
+ if (i == E1000_ICH_NVM_SIG_WORD - 1)
+ dword |= E1000_ICH_NVM_SIG_MASK << 16;
+
+ /* Convert offset to bytes. */
+ act_offset = (i + new_bank_offset) << 1;
+
+ usec_delay(100);
+
+ /* Write the data to the new bank. Offset in words*/
+ act_offset = i + new_bank_offset;
+ ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset,
+ dword);
+ if (ret_val)
+ break;
+ }
+
+ /* Don't bother writing the segment valid bits if sector
+ * programming failed.
+ */
+ if (ret_val) {
+ DEBUGOUT("Flash commit failed.\n");
+ goto release;
+ }
+
+ /* Finally validate the new segment by setting bit 15:14
+ * to 10b in word 0x13 , this can be done without an
+ * erase as well since these bits are 11 to start with
+ * and we need to change bit 14 to 0b
+ */
+ act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
+
+ /*offset in words but we read dword*/
+ --act_offset;
+ ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword);
+
+ if (ret_val)
+ goto release;
+
+ dword &= 0xBFFFFFFF;
+ ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword);
+
+ if (ret_val)
+ goto release;
+
+ /* And invalidate the previously valid segment by setting
+ * its signature word (0x13) high_byte to 0b. This can be
+ * done without an erase because flash erase sets all bits
+ * to 1's. We can write 1's to 0's without an erase
+ */
+ act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;
+
+ /* offset in words but we read dword*/
+ act_offset = old_bank_offset + E1000_ICH_NVM_SIG_WORD - 1;
+ ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword);
+
+ if (ret_val)
+ goto release;
+
+ dword &= 0x00FFFFFF;
+ ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword);
+
+ if (ret_val)
+ goto release;
+
+ /* Great! Everything worked, we can now clear the cached entries. */
+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
+ dev_spec->shadow_ram[i].modified = FALSE;
+ dev_spec->shadow_ram[i].value = 0xFFFF;
+ }
+
+release:
+ nvm->ops.release(hw);
+
+ /* Reload the EEPROM, or else modifications will not appear
+ * until after the next adapter reset.
+ */
+ if (!ret_val) {
+ nvm->ops.reload(hw);
+ msec_delay(10);
+ }
+
+out:
+ if (ret_val)
+ DEBUGOUT1("NVM update error: %d\n", ret_val);
+
+ return ret_val;
+}
+
+/**
* e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM
* @hw: pointer to the HW structure
*
@@ -3775,6 +4375,7 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
*/
switch (hw->mac.type) {
case e1000_pch_lpt:
+ case e1000_pch_spt:
word = NVM_COMPAT;
valid_csum_mask = NVM_COMPAT_VALID_CSUM;
break;
@@ -3822,8 +4423,13 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
DEBUGFUNC("e1000_write_ich8_data");
- if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
- return -E1000_ERR_NVM;
+ if (hw->mac.type == e1000_pch_spt) {
+ if (size != 4 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
+ return -E1000_ERR_NVM;
+ } else {
+ if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
+ return -E1000_ERR_NVM;
+ }
flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
hw->nvm.flash_base_addr);
@@ -3834,12 +4440,29 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
ret_val = e1000_flash_cycle_init_ich8lan(hw);
if (ret_val != E1000_SUCCESS)
break;
- hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
+ /* In SPT, This register is in Lan memory space, not
+ * flash. Therefore, only 32 bit access is supported
+ */
+ if (hw->mac.type == e1000_pch_spt)
+ hsflctl.regval =
+ E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
+ else
+ hsflctl.regval =
+ E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
hsflctl.hsf_ctrl.fldbcount = size - 1;
hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
- E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
+ /* In SPT, This register is in Lan memory space,
+ * not flash. Therefore, only 32 bit access is
+ * supported
+ */
+ if (hw->mac.type == e1000_pch_spt)
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ hsflctl.regval << 16);
+ else
+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
+ hsflctl.regval);
E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
@@ -3877,6 +4500,94 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
return ret_val;
}
+/**
+* e1000_write_flash_data32_ich8lan - Writes 4 bytes to the NVM
+* @hw: pointer to the HW structure
+* @offset: The offset (in bytes) of the dwords to read.
+* @data: The 4 bytes to write to the NVM.
+*
+* Writes one/two/four bytes to the NVM using the flash access registers.
+**/
+static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
+ u32 data)
+{
+ union ich8_hws_flash_status hsfsts;
+ union ich8_hws_flash_ctrl hsflctl;
+ u32 flash_linear_addr;
+ s32 ret_val;
+ u8 count = 0;
+
+ DEBUGFUNC("e1000_write_flash_data32_ich8lan");
+
+ if (hw->mac.type == e1000_pch_spt) {
+ if (offset > ICH_FLASH_LINEAR_ADDR_MASK)
+ return -E1000_ERR_NVM;
+ }
+ flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
+ hw->nvm.flash_base_addr);
+ do {
+ usec_delay(1);
+ /* Steps */
+ ret_val = e1000_flash_cycle_init_ich8lan(hw);
+ if (ret_val != E1000_SUCCESS)
+ break;
+
+ /* In SPT, This register is in Lan memory space, not
+ * flash. Therefore, only 32 bit access is supported
+ */
+ if (hw->mac.type == e1000_pch_spt)
+ hsflctl.regval = E1000_READ_FLASH_REG(hw,
+ ICH_FLASH_HSFSTS)
+ >> 16;
+ else
+ hsflctl.regval = E1000_READ_FLASH_REG16(hw,
+ ICH_FLASH_HSFCTL);
+
+ hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1;
+ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
+
+ /* In SPT, This register is in Lan memory space,
+ * not flash. Therefore, only 32 bit access is
+ * supported
+ */
+ if (hw->mac.type == e1000_pch_spt)
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ hsflctl.regval << 16);
+ else
+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
+ hsflctl.regval);
+
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
+
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, data);
+
+ /* check if FCERR is set to 1 , if set to 1, clear it
+ * and try the whole sequence a few more times else done
+ */
+ ret_val = e1000_flash_cycle_ich8lan(hw,
+ ICH_FLASH_WRITE_COMMAND_TIMEOUT);
+
+ if (ret_val == E1000_SUCCESS)
+ break;
+
+ /* If we're here, then things are most likely
+ * completely hosed, but if the error condition
+ * is detected, it won't hurt to give it another
+ * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
+ */
+ hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
+
+ if (hsfsts.hsf_status.flcerr)
+ /* Repeat for some time before giving up. */
+ continue;
+ if (!hsfsts.hsf_status.flcdone) {
+ DEBUGOUT("Timeout error - flash cycle did not complete.\n");
+ break;
+ }
+ } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
+
+ return ret_val;
+}
/**
* e1000_write_flash_byte_ich8lan - Write a single byte to NVM
@@ -3896,7 +4607,42 @@ static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
return e1000_write_flash_data_ich8lan(hw, offset, 1, word);
}
+/**
+* e1000_retry_write_flash_dword_ich8lan - Writes a dword to NVM
+* @hw: pointer to the HW structure
+* @offset: The offset of the word to write.
+* @dword: The dword to write to the NVM.
+*
+* Writes a single dword to the NVM using the flash access registers.
+* Goes through a retry algorithm before giving up.
+**/
+static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw,
+ u32 offset, u32 dword)
+{
+ s32 ret_val;
+ u16 program_retries;
+
+ DEBUGFUNC("e1000_retry_write_flash_dword_ich8lan");
+
+ /* Must convert word offset into bytes. */
+ offset <<= 1;
+
+ ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword);
+ if (!ret_val)
+ return ret_val;
+ for (program_retries = 0; program_retries < 100; program_retries++) {
+ DEBUGOUT2("Retrying Byte %8.8X at offset %u\n", dword, offset);
+ usec_delay(100);
+ ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword);
+ if (ret_val == E1000_SUCCESS)
+ break;
+ }
+ if (program_retries == 100)
+ return -E1000_ERR_NVM;
+
+ return E1000_SUCCESS;
+}
/**
* e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM
@@ -4006,12 +4752,22 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
/* Write a value 11 (block Erase) in Flash
* Cycle field in hw flash control
*/
- hsflctl.regval =
- E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
+ if (hw->mac.type == e1000_pch_spt)
+ hsflctl.regval =
+ E1000_READ_FLASH_REG(hw,
+ ICH_FLASH_HSFSTS)>>16;
+ else
+ hsflctl.regval =
+ E1000_READ_FLASH_REG16(hw,
+ ICH_FLASH_HSFCTL);
hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
- E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
- hsflctl.regval);
+ if (hw->mac.type == e1000_pch_spt)
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ hsflctl.regval << 16);
+ else
+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
+ hsflctl.regval);
/* Write the last 24 bits of an index within the
* block into Flash Linear address field in Flash
@@ -4444,7 +5200,8 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_RFCTL, reg);
/* Enable ECC on Lynxpoint */
- if (hw->mac.type == e1000_pch_lpt) {
+ if ((hw->mac.type == e1000_pch_lpt) ||
+ (hw->mac.type == e1000_pch_spt)) {
reg = E1000_READ_REG(hw, E1000_PBECCSTS);
reg |= E1000_PBECCSTS_ECC_ENABLE;
E1000_WRITE_REG(hw, E1000_PBECCSTS, reg);
@@ -4876,7 +5633,8 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
(device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
(device_id == E1000_DEV_ID_PCH_I218_LM3) ||
- (device_id == E1000_DEV_ID_PCH_I218_V3)) {
+ (device_id == E1000_DEV_ID_PCH_I218_V3) ||
+ (hw->mac.type == e1000_pch_spt)) {
u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
E1000_WRITE_REG(hw, E1000_FEXTNVM6,
@@ -4992,18 +5750,18 @@ out:
* the PHY.
* On i217, setup Intel Rapid Start Technology.
**/
-void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
+u32 e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
{
s32 ret_val;
DEBUGFUNC("e1000_resume_workarounds_pchlan");
if (hw->mac.type < e1000_pch2lan)
- return;
+ return E1000_SUCCESS;
ret_val = e1000_init_phy_workarounds_pchlan(hw);
if (ret_val) {
DEBUGOUT1("Failed to init PHY flow ret_val=%d\n", ret_val);
- return;
+ return ret_val;
}
/* For i217 Intel Rapid Start Technology support when the system
@@ -5017,7 +5775,7 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
ret_val = hw->phy.ops.acquire(hw);
if (ret_val) {
DEBUGOUT("Failed to setup iRST\n");
- return;
+ return ret_val;
}
/* Clear Auto Enable LPI after link up */
@@ -5051,7 +5809,9 @@ release:
if (ret_val)
DEBUGOUT1("Error %d in resume workarounds\n", ret_val);
hw->phy.ops.release(hw);
+ return ret_val;
}
+ return E1000_SUCCESS;
}
/**
diff --git a/sys/dev/e1000/e1000_ich8lan.h b/sys/dev/e1000/e1000_ich8lan.h
index 9cb79c0b0c99..edc1dd14ccc9 100644
--- a/sys/dev/e1000/e1000_ich8lan.h
+++ b/sys/dev/e1000/e1000_ich8lan.h
@@ -107,9 +107,23 @@
#define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100
#define E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION 0x00000200
-
+#define E1000_FEXTNVM6_K1_OFF_ENABLE 0x80000000
+/* bit for disabling packet buffer read */
+#define E1000_FEXTNVM7_DISABLE_PB_READ 0x00040000
+#define E1000_FEXTNVM7_SIDE_CLK_UNGATE 0x00000004
#define E1000_FEXTNVM7_DISABLE_SMB_PERST 0x00000020
-
+#define E1000_FEXTNVM9_IOSFSB_CLKGATE_DIS 0x00000800
+#define E1000_FEXTNVM9_IOSFSB_CLKREQ_DIS 0x00001000
+#define E1000_FEXTNVM11_DISABLE_PB_READ 0x00000200
+#define E1000_FEXTNVM11_DISABLE_MULR_FIX 0x00002000
+
+/* bit24: RXDCTL thresholds granularity: 0 - cache lines, 1 - descriptors */
+#define E1000_RXDCTL_THRESH_UNIT_DESC 0x01000000
+
+#define NVM_SIZE_MULTIPLIER 4096 /*multiplier for NVMS field*/
+#define E1000_FLASH_BASE_ADDR 0xE000 /*offset of NVM access regs*/
+#define E1000_CTRL_EXT_NVMVS 0x3 /*NVM valid sector */
+#define E1000_TARC0_CB_MULTIQ_3_REQ (1 << 28 | 1 << 29)
#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL
#define E1000_ICH_RAR_ENTRIES 7
@@ -171,6 +185,8 @@
#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */
#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */
+#define K1_ENTRY_LATENCY 0
+#define K1_MIN_TIME 1
/* SMBus Control Phy Register */
#define CV_SMB_CTRL PHY_REG(769, 23)
@@ -184,6 +200,10 @@
#define I218_ULP_CONFIG1_INBAND_EXIT 0x0020 /* Inband on ULP exit */
#define I218_ULP_CONFIG1_WOL_HOST 0x0040 /* WoL Host on ULP exit */
#define I218_ULP_CONFIG1_RESET_TO_SMBUS 0x0100 /* Reset to SMBus mode */
+/* enable ULP even if when phy powered down via lanphypc */
+#define I218_ULP_CONFIG1_EN_ULP_LANPHYPC 0x0400
+/* disable clear of sticky ULP on PERST */
+#define I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST 0x0800
#define I218_ULP_CONFIG1_DISABLE_SMB_PERST 0x1000 /* Disable on PERST# */
/* SMBus Address Phy Register */
@@ -222,6 +242,9 @@
#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100
#define HV_PM_CTRL_K1_ENABLE 0x4000
+#define I217_PLL_CLOCK_GATE_REG PHY_REG(772, 28)
+#define I217_PLL_CLOCK_GATE_MASK 0x07FF
+
#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */
/* Inband Control */
@@ -302,15 +325,12 @@
#define E1000_SVCR_OFF_TIMER_SHIFT 16
#define E1000_SVT_OFF_HWM_MASK 0x0000001F
-#if defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT)
-#define E1000_PCI_REVISION_ID_REG 0x08
-#endif /* defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT) */
void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
bool state);
void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw);
-void e1000_resume_workarounds_pchlan(struct e1000_hw *hw);
+u32 e1000_resume_workarounds_pchlan(struct e1000_hw *hw);
s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw);
s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);
diff --git a/sys/dev/e1000/e1000_mac.h b/sys/dev/e1000/e1000_mac.h
index 1daed9bc9472..ef9789bbb537 100644
--- a/sys/dev/e1000/e1000_mac.h
+++ b/sys/dev/e1000/e1000_mac.h
@@ -36,9 +36,7 @@
#define _E1000_MAC_H_
void e1000_init_mac_ops_generic(struct e1000_hw *hw);
-#ifndef E1000_REMOVED
#define E1000_REMOVED(a) (0)
-#endif /* E1000_REMOVED */
void e1000_null_mac_generic(struct e1000_hw *hw);
s32 e1000_null_ops_generic(struct e1000_hw *hw);
s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d);
diff --git a/sys/dev/e1000/e1000_mbx.c b/sys/dev/e1000/e1000_mbx.c
index d9fb9acdce17..1de19a4df77c 100644
--- a/sys/dev/e1000/e1000_mbx.c
+++ b/sys/dev/e1000/e1000_mbx.c
@@ -426,15 +426,21 @@ static s32 e1000_check_for_rst_vf(struct e1000_hw *hw,
static s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw)
{
s32 ret_val = -E1000_ERR_MBX;
+ int count = 10;
DEBUGFUNC("e1000_obtain_mbx_lock_vf");
- /* Take ownership of the buffer */
- E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
+ do {
+ /* Take ownership of the buffer */
+ E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
- /* reserve mailbox for vf use */
- if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU)
- ret_val = E1000_SUCCESS;
+ /* reserve mailbox for vf use */
+ if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU) {
+ ret_val = E1000_SUCCESS;
+ break;
+ }
+ usec_delay(1000);
+ } while (count-- > 0);
return ret_val;
}
@@ -639,18 +645,26 @@ static s32 e1000_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
{
s32 ret_val = -E1000_ERR_MBX;
u32 p2v_mailbox;
+ int count = 10;
DEBUGFUNC("e1000_obtain_mbx_lock_pf");
- /* Take ownership of the buffer */
- E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU);
+ do {
+ /* Take ownership of the buffer */
+ E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number),
+ E1000_P2VMAILBOX_PFU);
- /* reserve mailbox for vf use */
- p2v_mailbox = E1000_READ_REG(hw, E1000_P2VMAILBOX(vf_number));
- if (p2v_mailbox & E1000_P2VMAILBOX_PFU)
- ret_val = E1000_SUCCESS;
+ /* reserve mailbox for pf use */
+ p2v_mailbox = E1000_READ_REG(hw, E1000_P2VMAILBOX(vf_number));
+ if (p2v_mailbox & E1000_P2VMAILBOX_PFU) {
+ ret_val = E1000_SUCCESS;
+ break;
+ }
+ usec_delay(1000);
+ } while (count-- > 0);
return ret_val;
+
}
/**
diff --git a/sys/dev/e1000/e1000_nvm.h b/sys/dev/e1000/e1000_nvm.h
index 31f2180a0b6b..64a4083eb209 100644
--- a/sys/dev/e1000/e1000_nvm.h
+++ b/sys/dev/e1000/e1000_nvm.h
@@ -35,12 +35,10 @@
#ifndef _E1000_NVM_H_
#define _E1000_NVM_H_
-#if !defined(NO_READ_PBA_RAW) || !defined(NO_WRITE_PBA_RAW)
struct e1000_pba {
u16 word[2];
u16 *pba_block;
};
-#endif
void e1000_init_nvm_ops_generic(struct e1000_hw *hw);
diff --git a/sys/dev/e1000/e1000_osdep.h b/sys/dev/e1000/e1000_osdep.h
index fc46f48df6cc..c0bf4182ec62 100644
--- a/sys/dev/e1000/e1000_osdep.h
+++ b/sys/dev/e1000/e1000_osdep.h
@@ -60,24 +60,24 @@
#define ASSERT(x) if(!(x)) panic("EM: x")
#define usec_delay(x) DELAY(x)
-#define usec_delay_irq(x) DELAY(x)
+#define usec_delay_irq(x) usec_delay(x)
#define msec_delay(x) DELAY(1000*(x))
#define msec_delay_irq(x) DELAY(1000*(x))
-#define DEBUGFUNC(F) DEBUGOUT(F);
-#define DEBUGOUT(S) do {} while (0)
-#define DEBUGOUT1(S,A) do {} while (0)
-#define DEBUGOUT2(S,A,B) do {} while (0)
-#define DEBUGOUT3(S,A,B,C) do {} while (0)
-#define DEBUGOUT7(S,A,B,C,D,E,F,G) do {} while (0)
+/* Enable/disable debugging statements in shared code */
+#define DBG 0
+
+#define DEBUGOUT(...) \
+ do { if (DBG) printf(__VA_ARGS__); } while (0)
+#define DEBUGOUT1(...) DEBUGOUT(__VA_ARGS__)
+#define DEBUGOUT2(...) DEBUGOUT(__VA_ARGS__)
+#define DEBUGOUT3(...) DEBUGOUT(__VA_ARGS__)
+#define DEBUGOUT7(...) DEBUGOUT(__VA_ARGS__)
+#define DEBUGFUNC(F) DEBUGOUT(F "\n")
#define STATIC static
#define FALSE 0
#define TRUE 1
-#ifndef __bool_true_false_are_defined
-#define false FALSE
-#define true TRUE
-#endif
#define CMD_MEM_WRT_INVALIDATE 0x0010 /* BIT_4 */
#define PCI_COMMAND_REGISTER PCIR_COMMAND
@@ -99,9 +99,6 @@ typedef int64_t s64;
typedef int32_t s32;
typedef int16_t s16;
typedef int8_t s8;
-#ifndef __bool_true_false_are_defined
-typedef boolean_t bool;
-#endif
#define __le16 u16
#define __le32 u32
diff --git a/sys/dev/e1000/e1000_phy.c b/sys/dev/e1000/e1000_phy.c
index 0c8ccd2ba627..b2bec3e5fe6b 100644
--- a/sys/dev/e1000/e1000_phy.c
+++ b/sys/dev/e1000/e1000_phy.c
@@ -1827,9 +1827,9 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
phy_data);
if (ret_val)
return ret_val;
- }
- DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data);
+ DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data);
+ }
ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
if (ret_val)
@@ -3429,14 +3429,12 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
u16 *data, bool read, bool page_set)
{
s32 ret_val;
- u16 reg, page;
+ u16 reg = BM_PHY_REG_NUM(offset);
+ u16 page = BM_PHY_REG_PAGE(offset);
u16 phy_reg = 0;
DEBUGFUNC("e1000_access_phy_wakeup_reg_bm");
- reg = BM_PHY_REG_NUM(offset);
- page = BM_PHY_REG_PAGE(offset);
-
/* Gig must be disabled for MDIO accesses to Host Wakeup reg page */
if ((hw->mac.type == e1000_pchlan) &&
(!(E1000_READ_REG(hw, E1000_PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
diff --git a/sys/dev/e1000/e1000_regs.h b/sys/dev/e1000/e1000_regs.h
index 7c81a8988243..37d701722da1 100644
--- a/sys/dev/e1000/e1000_regs.h
+++ b/sys/dev/e1000/e1000_regs.h
@@ -65,6 +65,9 @@
#define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */
#define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */
#define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */
+#define E1000_FEXTNVM9 0x5BB4 /* Future Extended NVM 9 - RW */
+#define E1000_FEXTNVM11 0x5BBC /* Future Extended NVM 11 - RW */
+#define E1000_PCIEANACFG 0x00F18 /* PCIE Analog Config */
#define E1000_FCT 0x00030 /* Flow Control Type - RW */
#define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
#define E1000_VET 0x00038 /* VLAN Ether Type - RW */
@@ -107,7 +110,9 @@
#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
#define E1000_PBS 0x01008 /* Packet Buffer Size */
#define E1000_PBECCSTS 0x0100C /* Packet Buffer ECC Status - RW */
+#define E1000_IOSFPC 0x00F28 /* TX corrupted data */
#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
+#define E1000_EEMNGCTL_I210 0x01010 /* i210 MNG EEprom Mode Control */
#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */
#define E1000_EEARBC_I210 0x12024 /* EEPROM Auto Read Bus Control */
#define E1000_FLASHT 0x01028 /* FLASH Timer Register */
@@ -588,6 +593,10 @@
#define E1000_TIMADJL 0x0B60C /* Time sync time adjustment offset Low - RW */
#define E1000_TIMADJH 0x0B610 /* Time sync time adjustment offset High - RW */
#define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */
+#define E1000_SYSSTMPL 0x0B648 /* HH Timesync system stamp low register */
+#define E1000_SYSSTMPH 0x0B64C /* HH Timesync system stamp hi register */
+#define E1000_PLTSTMPL 0x0B640 /* HH Timesync platform stamp low register */
+#define E1000_PLTSTMPH 0x0B644 /* HH Timesync platform stamp hi register */
#define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */
#define E1000_TSICR 0x0B66C /* Interrupt Cause Register */
#define E1000_TSIM 0x0B674 /* Interrupt Mask Register */
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index c1a9ce8717df..1f6746c5cdae 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -96,14 +96,9 @@
#include "if_em.h"
/*********************************************************************
- * Set this to one to display debug statistics
- *********************************************************************/
-int em_display_debug_stats = 0;
-
-/*********************************************************************
* Driver version:
*********************************************************************/
-char em_driver_version[] = "7.4.2";
+char em_driver_version[] = "7.6.1-k";
/*********************************************************************
* PCI Device ID Table
@@ -191,6 +186,13 @@ static em_vendor_info_t em_vendor_info_array[] =
{ 0x8086, E1000_DEV_ID_PCH_I218_V2, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_PCH_I218_LM3, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_PCH_I218_V3, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM2,
+ PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V2, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_PCH_LBG_I219_LM3,
+ PCI_ANY_ID, PCI_ANY_ID, 0},
/* required last entry */
{ 0, 0, 0, 0, 0}
};
@@ -238,6 +240,7 @@ static void em_free_pci_resources(struct adapter *);
static void em_local_timer(void *);
static void em_reset(struct adapter *);
static int em_setup_interface(device_t, struct adapter *);
+static void em_flush_desc_rings(struct adapter *);
static void em_setup_transmit_structures(struct adapter *);
static void em_initialize_transmit_unit(struct adapter *);
@@ -577,10 +580,25 @@ em_attach(device_t dev)
adapter->osdep.flash_bus_space_handle =
rman_get_bushandle(adapter->flash);
}
+ /*
+ ** In the new SPT device flash is not a
+ ** seperate BAR, rather it is also in BAR0,
+ ** so use the same tag and an offset handle for the
+ ** FLASH read/write macros in the shared code.
+ */
+ else if (hw->mac.type == e1000_pch_spt) {
+ adapter->osdep.flash_bus_space_tag =
+ adapter->osdep.mem_bus_space_tag;
+ adapter->osdep.flash_bus_space_handle =
+ adapter->osdep.mem_bus_space_handle
+ + E1000_FLASH_BASE_ADDR;
+ }
/* Do Shared Code initialization */
- if (e1000_setup_init_funcs(hw, TRUE)) {
- device_printf(dev, "Setup of Shared code failed\n");
+ error = e1000_setup_init_funcs(hw, TRUE);
+ if (error) {
+ device_printf(dev, "Setup of Shared code failed, error %d\n",
+ error);
error = ENXIO;
goto err_pci;
}
@@ -1170,6 +1188,7 @@ em_ioctl(if_t ifp, u_long command, caddr_t data)
case e1000_ich10lan:
case e1000_pch2lan:
case e1000_pch_lpt:
+ case e1000_pch_spt:
case e1000_82574:
case e1000_82583:
case e1000_80003es2lan: /* 9K Jumbo Frame size */
@@ -1371,8 +1390,15 @@ em_init_locked(struct adapter *adapter)
if_clearhwassist(ifp);
if (if_getcapenable(ifp) & IFCAP_TXCSUM)
if_sethwassistbits(ifp, CSUM_TCP | CSUM_UDP, 0);
- if (if_getcapenable(ifp) & IFCAP_TSO4)
- if_sethwassistbits(ifp, CSUM_TSO, 0);
+ /*
+ ** There have proven to be problems with TSO when not
+ ** at full gigabit speed, so disable the assist automatically
+ ** when at lower speeds. -jfv
+ */
+ if (if_getcapenable(ifp) & IFCAP_TSO4) {
+ if (adapter->link_speed == SPEED_1000)
+ if_sethwassistbits(ifp, CSUM_TSO, 0);
+ }
/* Configure for OS presence */
em_init_manageability(adapter);
@@ -2352,6 +2378,8 @@ em_update_link_status(struct adapter *adapter)
switch (hw->phy.media_type) {
case e1000_media_type_copper:
if (hw->mac.get_link_status) {
+ if (hw->mac.type == e1000_pch_spt)
+ msec_delay(50);
/* Do the work to read phy */
e1000_check_for_link(hw);
link_check = !hw->mac.get_link_status;
@@ -2443,6 +2471,10 @@ em_stop(void *arg)
EM_TX_UNLOCK(txr);
}
+ /* I219 needs some special flushing to avoid hangs */
+ if (adapter->hw.mac.type == e1000_pch_spt)
+ em_flush_desc_rings(adapter);
+
e1000_reset_hw(&adapter->hw);
E1000_WRITE_REG(&adapter->hw, E1000_WUC, 0);
@@ -2862,6 +2894,116 @@ msi:
}
+/*
+** The 3 following flush routines are used as a workaround in the
+** I219 client parts and only for them.
+**
+** em_flush_tx_ring - remove all descriptors from the tx_ring
+**
+** We want to clear all pending descriptors from the TX ring.
+** zeroing happens when the HW reads the regs. We assign the ring itself as
+** the data of the next descriptor. We don't care about the data we are about
+** to reset the HW.
+*/
+static void
+em_flush_tx_ring(struct adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ struct tx_ring *txr = adapter->tx_rings;
+ struct e1000_tx_desc *txd;
+ u32 tctl, txd_lower = E1000_TXD_CMD_IFCS;
+ u16 size = 512;
+
+ tctl = E1000_READ_REG(hw, E1000_TCTL);
+ E1000_WRITE_REG(hw, E1000_TCTL, tctl | E1000_TCTL_EN);
+
+ txd = &txr->tx_base[txr->next_avail_desc++];
+ if (txr->next_avail_desc == adapter->num_tx_desc)
+ txr->next_avail_desc = 0;
+
+ /* Just use the ring as a dummy buffer addr */
+ txd->buffer_addr = txr->txdma.dma_paddr;
+ txd->lower.data = htole32(txd_lower | size);
+ txd->upper.data = 0;
+
+ /* flush descriptors to memory before notifying the HW */
+ wmb();
+
+ E1000_WRITE_REG(hw, E1000_TDT(0), txr->next_avail_desc);
+ mb();
+ usec_delay(250);
+}
+
+/*
+** em_flush_rx_ring - remove all descriptors from the rx_ring
+**
+** Mark all descriptors in the RX ring as consumed and disable the rx ring
+*/
+static void
+em_flush_rx_ring(struct adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 rctl, rxdctl;
+
+ rctl = E1000_READ_REG(hw, E1000_RCTL);
+ E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
+ E1000_WRITE_FLUSH(hw);
+ usec_delay(150);
+
+ rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0));
+ /* zero the lower 14 bits (prefetch and host thresholds) */
+ rxdctl &= 0xffffc000;
+ /*
+ * update thresholds: prefetch threshold to 31, host threshold to 1
+ * and make sure the granularity is "descriptors" and not "cache lines"
+ */
+ rxdctl |= (0x1F | (1 << 8) | E1000_RXDCTL_THRESH_UNIT_DESC);
+ E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl);
+
+ /* momentarily enable the RX ring for the changes to take effect */
+ E1000_WRITE_REG(hw, E1000_RCTL, rctl | E1000_RCTL_EN);
+ E1000_WRITE_FLUSH(hw);
+ usec_delay(150);
+ E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
+}
+
+/*
+** em_flush_desc_rings - remove all descriptors from the descriptor rings
+**
+** In i219, the descriptor rings must be emptied before resetting the HW
+** or before changing the device state to D3 during runtime (runtime PM).
+**
+** Failure to do this will cause the HW to enter a unit hang state which can
+** only be released by PCI reset on the device
+**
+*/
+static void
+em_flush_desc_rings(struct adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ device_t dev = adapter->dev;
+ u16 hang_state;
+ u32 fext_nvm11, tdlen;
+
+ /* First, disable MULR fix in FEXTNVM11 */
+ fext_nvm11 = E1000_READ_REG(hw, E1000_FEXTNVM11);
+ fext_nvm11 |= E1000_FEXTNVM11_DISABLE_MULR_FIX;
+ E1000_WRITE_REG(hw, E1000_FEXTNVM11, fext_nvm11);
+
+ /* do nothing if we're not in faulty state, or if the queue is empty */
+ tdlen = E1000_READ_REG(hw, E1000_TDLEN(0));
+ hang_state = pci_read_config(dev, PCICFG_DESC_RING_STATUS, 2);
+ if (!(hang_state & FLUSH_DESC_REQUIRED) || !tdlen)
+ return;
+ em_flush_tx_ring(adapter);
+
+ /* recheck, maybe the fault is caused by the rx ring */
+ hang_state = pci_read_config(dev, PCICFG_DESC_RING_STATUS, 2);
+ if (hang_state & FLUSH_DESC_REQUIRED)
+ em_flush_rx_ring(adapter);
+}
+
+
/*********************************************************************
*
* Initialize the hardware to a configuration
@@ -2923,6 +3065,7 @@ em_reset(struct adapter *adapter)
case e1000_pchlan:
case e1000_pch2lan:
case e1000_pch_lpt:
+ case e1000_pch_spt:
pba = E1000_PBA_26K;
break;
default:
@@ -2981,6 +3124,7 @@ em_reset(struct adapter *adapter)
break;
case e1000_pch2lan:
case e1000_pch_lpt:
+ case e1000_pch_spt:
hw->fc.high_water = 0x5C20;
hw->fc.low_water = 0x5048;
hw->fc.pause_time = 0x0650;
@@ -3005,6 +3149,10 @@ em_reset(struct adapter *adapter)
break;
}
+ /* I219 needs some special flushing to avoid hangs */
+ if (hw->mac.type == e1000_pch_spt)
+ em_flush_desc_rings(adapter);
+
/* Issue a global reset */
e1000_reset_hw(hw);
E1000_WRITE_REG(hw, E1000_WUC, 0);
@@ -3601,6 +3749,15 @@ em_initialize_transmit_unit(struct adapter *adapter)
/* This write will effectively turn on the transmit unit. */
E1000_WRITE_REG(&adapter->hw, E1000_TCTL, tctl);
+ if (hw->mac.type == e1000_pch_spt) {
+ u32 reg;
+ reg = E1000_READ_REG(hw, E1000_IOSFPC);
+ reg |= E1000_RCTL_RDMTS_HEX;
+ E1000_WRITE_REG(hw, E1000_IOSFPC, reg);
+ reg = E1000_READ_REG(hw, E1000_TARC(0));
+ reg |= E1000_TARC0_CB_MULTIQ_3_REQ;
+ E1000_WRITE_REG(hw, E1000_TARC(0), reg);
+ }
}
diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h
index 362df49442a7..3b280b33401c 100644
--- a/sys/dev/e1000/if_em.h
+++ b/sys/dev/e1000/if_em.h
@@ -218,6 +218,9 @@
#define EM_TX_HUNG 0x80000000
#define EM_TX_MAXTRIES 10
+#define PCICFG_DESC_RING_STATUS 0xe4
+#define FLUSH_DESC_REQUIRED 0x100
+
/*
* TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
* multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index 5be7836cb8f8..c84dfc2be007 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -47,7 +47,7 @@
/*********************************************************************
* Driver version:
*********************************************************************/
-char igb_driver_version[] = "2.5.2";
+char igb_driver_version[] = "2.5.3-k";
/*********************************************************************
@@ -551,9 +551,9 @@ igb_attach(device_t dev)
"Disable Energy Efficient Ethernet");
if (adapter->hw.phy.media_type == e1000_media_type_copper) {
if (adapter->hw.mac.type == e1000_i354)
- e1000_set_eee_i354(&adapter->hw);
+ e1000_set_eee_i354(&adapter->hw, TRUE, TRUE);
else
- e1000_set_eee_i350(&adapter->hw);
+ e1000_set_eee_i350(&adapter->hw, TRUE, TRUE);
}
}
@@ -1277,6 +1277,9 @@ igb_init_locked(struct adapter *adapter)
if (ifp->if_capenable & IFCAP_TSO)
ifp->if_hwassist |= CSUM_TSO;
+ /* Clear bad data from Rx FIFOs */
+ e1000_rx_fifo_flush_82575(&adapter->hw);
+
/* Configure for OS presence */
igb_init_manageability(adapter);
@@ -1304,7 +1307,6 @@ igb_init_locked(struct adapter *adapter)
return;
}
igb_initialize_receive_units(adapter);
- e1000_rx_fifo_flush_82575(&adapter->hw);
/* Enable VLAN support */
if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
@@ -1341,9 +1343,9 @@ igb_init_locked(struct adapter *adapter)
/* Set Energy Efficient Ethernet */
if (adapter->hw.phy.media_type == e1000_media_type_copper) {
if (adapter->hw.mac.type == e1000_i354)
- e1000_set_eee_i354(&adapter->hw);
+ e1000_set_eee_i354(&adapter->hw, TRUE, TRUE);
else
- e1000_set_eee_i350(&adapter->hw);
+ e1000_set_eee_i350(&adapter->hw, TRUE, TRUE);
}
}
diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c
index 00e785d91c35..95d80f690643 100644
--- a/sys/dev/ed/if_ed.c
+++ b/sys/dev/ed/if_ed.c
@@ -43,8 +43,9 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sockio.h>
-#include <sys/mbuf.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
diff --git a/sys/dev/ep/if_ep.c b/sys/dev/ep/if_ep.c
index cd7afb530a46..9f6848a1de58 100644
--- a/sys/dev/ep/if_ep.c
+++ b/sys/dev/ep/if_ep.c
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
diff --git a/sys/dev/fe/if_fe.c b/sys/dev/fe/if_fe.c
index 4598b59fcb97..1be74f9d2c8b 100644
--- a/sys/dev/fe/if_fe.c
+++ b/sys/dev/fe/if_fe.c
@@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/sockio.h>
diff --git a/sys/dev/filemon/filemon.c b/sys/dev/filemon/filemon.c
index 0ec83465dbed..352f68241ede 100644
--- a/sys/dev/filemon/filemon.c
+++ b/sys/dev/filemon/filemon.c
@@ -89,7 +89,7 @@ struct filemon {
TAILQ_ENTRY(filemon) link; /* Link into the in-use list. */
struct sx lock; /* Lock mutex for this filemon. */
struct file *fp; /* Output file pointer. */
- pid_t pid; /* The process ID being monitored. */
+ struct proc *p; /* The process being monitored. */
char fname1[MAXPATHLEN]; /* Temporary filename buffer. */
char fname2[MAXPATHLEN]; /* Temporary filename buffer. */
char msgbufr[1024]; /* Output message buffer. */
@@ -137,7 +137,7 @@ filemon_dtr(void *data)
fp = filemon->fp;
filemon->fp = NULL;
- filemon->pid = -1;
+ filemon->p = NULL;
/* Add to the free list. */
TAILQ_INSERT_TAIL(&filemons_free, filemon, link);
@@ -188,7 +188,7 @@ filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused,
error = pget(*((pid_t *)data), PGET_CANDEBUG | PGET_NOTWEXIT,
&p);
if (error == 0) {
- filemon->pid = p->p_pid;
+ filemon->p = p;
PROC_UNLOCK(p);
}
break;
@@ -223,8 +223,6 @@ filemon_open(struct cdev *dev, int oflags __unused, int devtype __unused,
sx_init(&filemon->lock, "filemon");
}
- filemon->pid = curproc->p_pid;
-
devfs_set_cdevpriv(filemon, filemon_dtr);
/* Get exclusive write access. */
diff --git a/sys/dev/filemon/filemon_wrapper.c b/sys/dev/filemon/filemon_wrapper.c
index 9beb573966bc..1b9877a68592 100644
--- a/sys/dev/filemon/filemon_wrapper.c
+++ b/sys/dev/filemon/filemon_wrapper.c
@@ -29,7 +29,10 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/imgact.h>
+#include <sys/eventhandler.h>
#include <sys/sx.h>
+#include <sys/vnode.h>
#include "opt_compat.h"
@@ -43,21 +46,21 @@ __FBSDID("$FreeBSD$");
(2011-09-10) so this code is broken for
9-CURRENT September 10th-16th. */
#define sys_chdir chdir
-#define sys_execve execve
-#define sys_fork fork
#define sys_link link
#define sys_open open
#define sys_rename rename
#define sys_stat stat
#define sys_symlink symlink
#define sys_unlink unlink
-#define sys_vfork vfork
-#define sys_sys_exit sys_exit
#ifdef FILEMON_HAS_LINKAT
#define sys_linkat linkat
#endif
#endif /* __FreeBSD_version */
+static eventhandler_tag filemon_exec_tag;
+static eventhandler_tag filemon_exit_tag;
+static eventhandler_tag filemon_fork_tag;
+
static void
filemon_output(struct filemon *filemon, char *msg, size_t len)
{
@@ -95,7 +98,7 @@ filemon_pid_check(struct proc *p)
sx_slock(&proctree_lock);
while (p != initproc) {
TAILQ_FOREACH(filemon, &filemons_inuse, link) {
- if (p->p_pid == filemon->pid) {
+ if (p == filemon->p) {
sx_sunlock(&proctree_lock);
filemon_filemon_lock(filemon);
filemon_unlock_read();
@@ -136,84 +139,32 @@ filemon_wrapper_chdir(struct thread *td, struct chdir_args *uap)
return (ret);
}
-static int
-filemon_wrapper_execve(struct thread *td, struct execve_args *uap)
+static void
+filemon_event_process_exec(void *arg __unused, struct proc *p,
+ struct image_params *imgp)
{
- char fname[MAXPATHLEN];
- int ret;
- size_t done;
- size_t len;
struct filemon *filemon;
-
- copyinstr(uap->fname, fname, sizeof(fname), &done);
-
- if ((ret = sys_execve(td, uap)) == 0) {
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
- len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "E %d %s\n",
- curproc->p_pid, fname);
-
- filemon_output(filemon, filemon->msgbufr, len);
-
- /* Unlock the found filemon structure. */
- filemon_filemon_unlock(filemon);
- }
- }
-
- return (ret);
-}
-
-#if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
-static int
-filemon_wrapper_freebsd32_execve(struct thread *td,
- struct freebsd32_execve_args *uap)
-{
- char fname[MAXPATHLEN];
- int ret;
- size_t done;
+ char *fullpath, *freepath;
size_t len;
- struct filemon *filemon;
-
- copyinstr(uap->fname, fname, sizeof(fname), &done);
- if ((ret = freebsd32_execve(td, uap)) == 0) {
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
- len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "E %d %s\n",
- curproc->p_pid, fname);
+ if ((filemon = filemon_pid_check(p)) != NULL) {
+ fullpath = "<unknown>";
+ freepath = NULL;
- filemon_output(filemon, filemon->msgbufr, len);
+ vn_fullpath(FIRST_THREAD_IN_PROC(p), imgp->vp, &fullpath,
+ &freepath);
- /* Unlock the found filemon structure. */
- filemon_filemon_unlock(filemon);
- }
- }
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "E %d %s\n",
+ p->p_pid, fullpath);
- return (ret);
-}
-#endif
-
-static int
-filemon_wrapper_fork(struct thread *td, struct fork_args *uap)
-{
- int ret;
- size_t len;
- struct filemon *filemon;
-
- if ((ret = sys_fork(td, uap)) == 0) {
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
- len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "F %d %ld\n",
- curproc->p_pid, (long)curthread->td_retval[0]);
+ filemon_output(filemon, filemon->msgbufr, len);
- filemon_output(filemon, filemon->msgbufr, len);
+ /* Unlock the found filemon structure. */
+ filemon_filemon_unlock(filemon);
- /* Unlock the found filemon structure. */
- filemon_filemon_unlock(filemon);
- }
+ free(freepath, M_TEMP);
}
-
- return (ret);
}
static int
@@ -485,7 +436,7 @@ filemon_wrapper_freebsd32_stat(struct thread *td,
#endif
static void
-filemon_wrapper_sys_exit(struct thread *td, struct sys_exit_args *uap)
+filemon_event_process_exit(void *arg __unused, struct proc *p)
{
size_t len;
struct filemon *filemon;
@@ -494,28 +445,26 @@ filemon_wrapper_sys_exit(struct thread *td, struct sys_exit_args *uap)
/* Get timestamp before locking. */
getmicrotime(&now);
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
+ if ((filemon = filemon_pid_check(p)) != NULL) {
len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr),
- "X %d %d\n", curproc->p_pid, uap->rval);
+ "X %d %d %d\n", p->p_pid, p->p_xexit, p->p_xsig);
filemon_output(filemon, filemon->msgbufr, len);
/* Check if the monitored process is about to exit. */
- if (filemon->pid == curproc->p_pid) {
+ if (filemon->p == p) {
len = snprintf(filemon->msgbufr,
sizeof(filemon->msgbufr),
"# Stop %ju.%06ju\n# Bye bye\n",
(uintmax_t)now.tv_sec, (uintmax_t)now.tv_usec);
filemon_output(filemon, filemon->msgbufr, len);
- filemon->pid = -1;
+ filemon->p = NULL;
}
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- sys_sys_exit(td, uap);
}
static int
@@ -545,27 +494,23 @@ filemon_wrapper_unlink(struct thread *td, struct unlink_args *uap)
return (ret);
}
-static int
-filemon_wrapper_vfork(struct thread *td, struct vfork_args *uap)
+static void
+filemon_event_process_fork(void *arg __unused, struct proc *p1,
+ struct proc *p2, int flags __unused)
{
- int ret;
size_t len;
struct filemon *filemon;
- if ((ret = sys_vfork(td, uap)) == 0) {
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
- len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "F %d %ld\n",
- curproc->p_pid, (long)curthread->td_retval[0]);
+ if ((filemon = filemon_pid_check(p1)) != NULL) {
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "F %d %d\n",
+ p1->p_pid, p2->p_pid);
- filemon_output(filemon, filemon->msgbufr, len);
+ filemon_output(filemon, filemon->msgbufr, len);
- /* Unlock the found filemon structure. */
- filemon_filemon_unlock(filemon);
- }
+ /* Unlock the found filemon structure. */
+ filemon_filemon_unlock(filemon);
}
-
- return (ret);
}
static void
@@ -578,15 +523,11 @@ filemon_wrapper_install(void)
#endif
sv_table[SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
- sv_table[SYS_exit].sy_call = (sy_call_t *) filemon_wrapper_sys_exit;
- sv_table[SYS_execve].sy_call = (sy_call_t *) filemon_wrapper_execve;
- sv_table[SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork;
sv_table[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
sv_table[SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
sv_table[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
sv_table[SYS_stat].sy_call = (sy_call_t *) filemon_wrapper_stat;
sv_table[SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
- sv_table[SYS_vfork].sy_call = (sy_call_t *) filemon_wrapper_vfork;
sv_table[SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
sv_table[SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
#ifdef FILEMON_HAS_LINKAT
@@ -597,21 +538,24 @@ filemon_wrapper_install(void)
sv_table = ia32_freebsd_sysvec.sv_table;
sv_table[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
- sv_table[FREEBSD32_SYS_exit].sy_call = (sy_call_t *) filemon_wrapper_sys_exit;
- sv_table[FREEBSD32_SYS_freebsd32_execve].sy_call = (sy_call_t *) filemon_wrapper_freebsd32_execve;
- sv_table[FREEBSD32_SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork;
sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
sv_table[FREEBSD32_SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
sv_table[FREEBSD32_SYS_freebsd32_stat].sy_call = (sy_call_t *) filemon_wrapper_freebsd32_stat;
sv_table[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
- sv_table[FREEBSD32_SYS_vfork].sy_call = (sy_call_t *) filemon_wrapper_vfork;
sv_table[FREEBSD32_SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
sv_table[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
#ifdef FILEMON_HAS_LINKAT
sv_table[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat;
#endif
#endif /* COMPAT_ARCH32 */
+
+ filemon_exec_tag = EVENTHANDLER_REGISTER(process_exec,
+ filemon_event_process_exec, NULL, EVENTHANDLER_PRI_LAST);
+ filemon_exit_tag = EVENTHANDLER_REGISTER(process_exit,
+ filemon_event_process_exit, NULL, EVENTHANDLER_PRI_LAST);
+ filemon_fork_tag = EVENTHANDLER_REGISTER(process_fork,
+ filemon_event_process_fork, NULL, EVENTHANDLER_PRI_LAST);
}
static void
@@ -624,15 +568,11 @@ filemon_wrapper_deinstall(void)
#endif
sv_table[SYS_chdir].sy_call = (sy_call_t *)sys_chdir;
- sv_table[SYS_exit].sy_call = (sy_call_t *)sys_sys_exit;
- sv_table[SYS_execve].sy_call = (sy_call_t *)sys_execve;
- sv_table[SYS_fork].sy_call = (sy_call_t *)sys_fork;
sv_table[SYS_open].sy_call = (sy_call_t *)sys_open;
sv_table[SYS_openat].sy_call = (sy_call_t *)sys_openat;
sv_table[SYS_rename].sy_call = (sy_call_t *)sys_rename;
sv_table[SYS_stat].sy_call = (sy_call_t *)sys_stat;
sv_table[SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
- sv_table[SYS_vfork].sy_call = (sy_call_t *)sys_vfork;
sv_table[SYS_link].sy_call = (sy_call_t *)sys_link;
sv_table[SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
#ifdef FILEMON_HAS_LINKAT
@@ -643,19 +583,19 @@ filemon_wrapper_deinstall(void)
sv_table = ia32_freebsd_sysvec.sv_table;
sv_table[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *)sys_chdir;
- sv_table[FREEBSD32_SYS_exit].sy_call = (sy_call_t *)sys_sys_exit;
- sv_table[FREEBSD32_SYS_freebsd32_execve].sy_call = (sy_call_t *)freebsd32_execve;
- sv_table[FREEBSD32_SYS_fork].sy_call = (sy_call_t *)sys_fork;
sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *)sys_open;
sv_table[FREEBSD32_SYS_openat].sy_call = (sy_call_t *)sys_openat;
sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *)sys_rename;
sv_table[FREEBSD32_SYS_freebsd32_stat].sy_call = (sy_call_t *)freebsd32_stat;
sv_table[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
- sv_table[FREEBSD32_SYS_vfork].sy_call = (sy_call_t *)sys_vfork;
sv_table[FREEBSD32_SYS_link].sy_call = (sy_call_t *)sys_link;
sv_table[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
#ifdef FILEMON_HAS_LINKAT
sv_table[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *)sys_linkat;
#endif
#endif /* COMPAT_ARCH32 */
+
+ EVENTHANDLER_DEREGISTER(process_exec, filemon_exec_tag);
+ EVENTHANDLER_DEREGISTER(process_exit, filemon_exit_tag);
+ EVENTHANDLER_DEREGISTER(process_fork, filemon_fork_tag);
}
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index cf0e6a249ff9..dc9181758a30 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/rman.h>
diff --git a/sys/dev/hwpmc/hwpmc_riscv.h b/sys/dev/hwpmc/hwpmc_riscv.h
new file mode 100644
index 000000000000..3f1f5999f6bc
--- /dev/null
+++ b/sys/dev/hwpmc/hwpmc_riscv.h
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * This software was developed by the University of Cambridge Computer
+ * Laboratory with support from ARM Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DEV_HWPMC_RISCV_H_
+#define _DEV_HWPMC_RISCV_H_
+
+#define RISCV_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \
+ PMC_CAP_SYSTEM | PMC_CAP_EDGE | \
+ PMC_CAP_THRESHOLD | PMC_CAP_READ | \
+ PMC_CAP_WRITE | PMC_CAP_INVERT | \
+ PMC_CAP_QUALIFIER)
+
+#define RISCV_RELOAD_COUNT_TO_PERFCTR_VALUE(R) (-(R))
+#define RISCV_PERFCTR_VALUE_TO_RELOAD_COUNT(P) (-(P))
+#define EVENT_ID_MASK 0xFF
+
+#ifdef _KERNEL
+/* MD extension for 'struct pmc' */
+struct pmc_md_riscv_pmc {
+ uint32_t pm_riscv_evsel;
+};
+#endif /* _KERNEL */
+#endif /* _DEV_HWPMC_RISCV_H_ */
diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h
index 852e14ea5690..8e2ca57aa3ca 100644
--- a/sys/dev/hyperv/include/hyperv.h
+++ b/sys/dev/hyperv/include/hyperv.h
@@ -908,30 +908,6 @@ int hv_vmbus_channel_teardown_gpdal(
struct hv_vmbus_channel* vmbus_select_outgoing_channel(struct hv_vmbus_channel *promary);
-/*
- * Work abstraction defines
- */
-typedef struct hv_work_queue {
- struct taskqueue* queue;
- struct proc* proc;
- struct sema* work_sema;
-} hv_work_queue;
-
-typedef struct hv_work_item {
- struct task work;
- void (*callback)(void *);
- void* context;
- hv_work_queue* wq;
-} hv_work_item;
-
-struct hv_work_queue* hv_work_queue_create(char* name);
-
-void hv_work_queue_close(struct hv_work_queue* wq);
-
-int hv_queue_work_item(
- hv_work_queue* wq,
- void (*callback)(void *),
- void* context);
/**
* @brief Get physical address from virtual
*/
@@ -952,8 +928,8 @@ typedef struct hv_vmbus_service {
hv_guid guid; /* Hyper-V GUID */
char *name; /* name of service */
boolean_t enabled; /* service enabled */
- hv_work_queue *work_queue; /* background work queue */
-
+ void* context;
+ struct task task;
/*
* function to initialize service
*/
@@ -963,6 +939,11 @@ typedef struct hv_vmbus_service {
* function to process Hyper-V messages
*/
void (*callback)(void *);
+
+ /*
+ * function to uninitilize service
+ */
+ int (*uninit)(struct hv_vmbus_service *);
} hv_vmbus_service;
extern uint8_t* receive_buffer[];
diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c
index 8bf34a85c783..cd60b4969fd4 100644
--- a/sys/dev/hyperv/netvsc/hv_net_vsc.c
+++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c
@@ -74,10 +74,7 @@ hv_nv_alloc_net_device(struct hv_device *device)
netvsc_dev *net_dev;
hn_softc_t *sc = device_get_softc(device->device);
- net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_NOWAIT | M_ZERO);
- if (net_dev == NULL) {
- return (NULL);
- }
+ net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_WAITOK | M_ZERO);
net_dev->dev = device;
net_dev->destroy = FALSE;
@@ -136,15 +133,15 @@ hv_nv_get_next_send_section(netvsc_dev *net_dev)
int i;
for (i = 0; i < bitsmap_words; i++) {
- idx = ffs(~bitsmap[i]);
+ idx = ffsl(~bitsmap[i]);
if (0 == idx)
continue;
idx--;
- if (i * BITS_PER_LONG + idx >= net_dev->send_section_count)
- return (ret);
+ KASSERT(i * BITS_PER_LONG + idx < net_dev->send_section_count,
+ ("invalid i %d and idx %lu", i, idx));
- if (synch_test_and_set_bit(idx, &bitsmap[i]))
+ if (atomic_testandset_long(&bitsmap[i], idx))
continue;
ret = i * BITS_PER_LONG + idx;
@@ -224,11 +221,7 @@ hv_nv_init_rx_buffer_with_net_vsp(struct hv_device *device)
init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.num_sections;
net_dev->rx_sections = malloc(net_dev->rx_section_count *
- sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_NOWAIT);
- if (net_dev->rx_sections == NULL) {
- ret = EINVAL;
- goto cleanup;
- }
+ sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_WAITOK);
memcpy(net_dev->rx_sections,
init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.sections,
net_dev->rx_section_count * sizeof(nvsp_1_rx_buf_section));
@@ -326,11 +319,7 @@ hv_nv_init_send_buffer_with_net_vsp(struct hv_device *device)
BITS_PER_LONG);
net_dev->send_section_bitsmap =
malloc(net_dev->bitsmap_words * sizeof(long), M_NETVSC,
- M_NOWAIT | M_ZERO);
- if (NULL == net_dev->send_section_bitsmap) {
- ret = ENOMEM;
- goto cleanup;
- }
+ M_WAITOK | M_ZERO);
goto exit;
@@ -789,8 +778,27 @@ hv_nv_on_send_completion(netvsc_dev *net_dev,
if (NULL != net_vsc_pkt) {
if (net_vsc_pkt->send_buf_section_idx !=
NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
- synch_change_bit(net_vsc_pkt->send_buf_section_idx,
- net_dev->send_section_bitsmap);
+ u_long mask;
+ int idx;
+
+ idx = net_vsc_pkt->send_buf_section_idx /
+ BITS_PER_LONG;
+ KASSERT(idx < net_dev->bitsmap_words,
+ ("invalid section index %u",
+ net_vsc_pkt->send_buf_section_idx));
+ mask = 1UL <<
+ (net_vsc_pkt->send_buf_section_idx %
+ BITS_PER_LONG);
+
+ KASSERT(net_dev->send_section_bitsmap[idx] &
+ mask,
+ ("index bitmap 0x%lx, section index %u, "
+ "bitmap idx %d, bitmask 0x%lx",
+ net_dev->send_section_bitsmap[idx],
+ net_vsc_pkt->send_buf_section_idx,
+ idx, mask));
+ atomic_clear_long(
+ &net_dev->send_section_bitsmap[idx], mask);
}
/* Notify the layer above us */
diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h
index c19034043e38..4f52e0d7c7f9 100644
--- a/sys/dev/hyperv/netvsc/hv_net_vsc.h
+++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h
@@ -1015,6 +1015,7 @@ typedef struct hn_softc {
bus_dma_tag_t hn_tx_rndis_dtag;
int hn_tx_chimney_size;
int hn_tx_chimney_max;
+ uint64_t hn_csum_assist;
struct mtx hn_txlist_spin;
struct hn_txdesc_list hn_txlist;
@@ -1022,6 +1023,7 @@ typedef struct hn_softc {
int hn_txdesc_avail;
int hn_txeof;
+ int hn_sched_tx;
int hn_direct_tx_size;
struct taskqueue *hn_tx_taskq;
struct task hn_start_task;
@@ -1030,11 +1032,12 @@ typedef struct hn_softc {
struct lro_ctrl hn_lro;
int hn_lro_hiwat;
- /* Trust tcp segments verification on host side */
- int hn_trust_hosttcp;
+ /* Trust csum verification on host side */
+ int hn_trust_hcsum; /* HN_TRUST_HCSUM_ */
u_long hn_csum_ip;
u_long hn_csum_tcp;
+ u_long hn_csum_udp;
u_long hn_csum_trusted;
u_long hn_lro_tried;
u_long hn_small_pkts;
@@ -1045,6 +1048,9 @@ typedef struct hn_softc {
u_long hn_tx_chimney;
} hn_softc_t;
+#define HN_TRUST_HCSUM_IP 0x0001
+#define HN_TRUST_HCSUM_TCP 0x0002
+#define HN_TRUST_HCSUM_UDP 0x0004
/*
* Externs
diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
index ab88e367106d..be43bf413302 100644
--- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
+++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
@@ -132,6 +132,8 @@ __FBSDID("$FreeBSD$");
/* YYY should get it from the underlying channel */
#define HN_TX_DESC_CNT 512
+#define HN_LROENT_CNT_DEF 128
+
#define HN_RNDIS_MSG_LEN \
(sizeof(rndis_msg) + \
RNDIS_VLAN_PPI_SIZE + \
@@ -167,14 +169,12 @@ struct hn_txdesc {
#define HN_TXD_FLAG_DMAMAP 0x2
/*
- * A unified flag for all outbound check sum flags is useful,
- * and it helps avoiding unnecessary check sum calculation in
- * network forwarding scenario.
+ * Only enable UDP checksum offloading when it is on 2012R2 or
+ * later. UDP checksum offloading doesn't work on earlier
+ * Windows releases.
*/
-#define HV_CSUM_FOR_OUTBOUND \
- (CSUM_IP|CSUM_IP_UDP|CSUM_IP_TCP|CSUM_IP_SCTP|CSUM_IP_TSO| \
- CSUM_IP_ISCSI|CSUM_IP6_UDP|CSUM_IP6_TCP|CSUM_IP6_SCTP| \
- CSUM_IP6_TSO|CSUM_IP6_ISCSI)
+#define HN_CSUM_ASSIST_WIN8 (CSUM_TCP)
+#define HN_CSUM_ASSIST (CSUM_IP | CSUM_UDP | CSUM_TCP)
/* XXX move to netinet/tcp_lro.h */
#define HN_LRO_HIWAT_MAX 65535
@@ -212,6 +212,14 @@ int hv_promisc_mode = 0; /* normal mode by default */
static int hn_trust_hosttcp = 1;
TUNABLE_INT("dev.hn.trust_hosttcp", &hn_trust_hosttcp);
+/* Trust udp datagrams verification on host side. */
+static int hn_trust_hostudp = 1;
+TUNABLE_INT("dev.hn.trust_hostudp", &hn_trust_hostudp);
+
+/* Trust ip packets verification on host side. */
+static int hn_trust_hostip = 1;
+TUNABLE_INT("dev.hn.trust_hostip", &hn_trust_hostip);
+
#if __FreeBSD_version >= 1100045
/* Limit TSO burst size */
static int hn_tso_maxlen = 0;
@@ -226,6 +234,13 @@ TUNABLE_INT("dev.hn.tx_chimney_size", &hn_tx_chimney_size);
static int hn_direct_tx_size = HN_DIRECT_TX_SIZE_DEF;
TUNABLE_INT("dev.hn.direct_tx_size", &hn_direct_tx_size);
+#if defined(INET) || defined(INET6)
+#if __FreeBSD_version >= 1100095
+static int hn_lro_entry_count = HN_LROENT_CNT_DEF;
+TUNABLE_INT("dev.hn.lro_entry_count", &hn_lro_entry_count);
+#endif
+#endif
+
/*
* Forward declarations
*/
@@ -241,12 +256,14 @@ static void hn_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr);
#ifdef HN_LRO_HIWAT
static int hn_lro_hiwat_sysctl(SYSCTL_HANDLER_ARGS);
#endif
+static int hn_trust_hcsum_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_tx_chimney_size_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_check_iplen(const struct mbuf *, int);
static int hn_create_tx_ring(struct hn_softc *sc);
static void hn_destroy_tx_ring(struct hn_softc *sc);
static void hn_start_taskfunc(void *xsc, int pending);
static void hn_txeof_taskfunc(void *xsc, int pending);
+static int hn_encap(struct hn_softc *, struct hn_txdesc *, struct mbuf **);
static __inline void
hn_set_lro_hiwat(struct hn_softc *sc, int hiwat)
@@ -257,62 +274,6 @@ hn_set_lro_hiwat(struct hn_softc *sc, int hiwat)
#endif
}
-/*
- * NetVsc get message transport protocol type
- */
-static uint32_t get_transport_proto_type(struct mbuf *m_head)
-{
- uint32_t ret_val = TRANSPORT_TYPE_NOT_IP;
- uint16_t ether_type = 0;
- int ether_len = 0;
- struct ether_vlan_header *eh;
-#ifdef INET
- struct ip *iph;
-#endif
-#ifdef INET6
- struct ip6_hdr *ip6;
-#endif
-
- eh = mtod(m_head, struct ether_vlan_header*);
- if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
- ether_len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
- ether_type = eh->evl_proto;
- } else {
- ether_len = ETHER_HDR_LEN;
- ether_type = eh->evl_encap_proto;
- }
-
- switch (ntohs(ether_type)) {
-#ifdef INET6
- case ETHERTYPE_IPV6:
- ip6 = (struct ip6_hdr *)(m_head->m_data + ether_len);
-
- if (IPPROTO_TCP == ip6->ip6_nxt) {
- ret_val = TRANSPORT_TYPE_IPV6_TCP;
- } else if (IPPROTO_UDP == ip6->ip6_nxt) {
- ret_val = TRANSPORT_TYPE_IPV6_UDP;
- }
- break;
-#endif
-#ifdef INET
- case ETHERTYPE_IP:
- iph = (struct ip *)(m_head->m_data + ether_len);
-
- if (IPPROTO_TCP == iph->ip_p) {
- ret_val = TRANSPORT_TYPE_IPV4_TCP;
- } else if (IPPROTO_UDP == iph->ip_p) {
- ret_val = TRANSPORT_TYPE_IPV4_UDP;
- }
- break;
-#endif
- default:
- ret_val = TRANSPORT_TYPE_NOT_IP;
- break;
- }
-
- return (ret_val);
-}
-
static int
hn_ifmedia_upd(struct ifnet *ifp __unused)
{
@@ -383,6 +344,11 @@ netvsc_attach(device_t dev)
#if __FreeBSD_version >= 1100045
int tso_maxlen;
#endif
+#if defined(INET) || defined(INET6)
+#if __FreeBSD_version >= 1100095
+ int lroent_cnt;
+#endif
+#endif
sc = device_get_softc(dev);
if (sc == NULL) {
@@ -393,8 +359,13 @@ netvsc_attach(device_t dev)
sc->hn_unit = unit;
sc->hn_dev = dev;
sc->hn_lro_hiwat = HN_LRO_HIWAT_DEF;
- sc->hn_trust_hosttcp = hn_trust_hosttcp;
sc->hn_direct_tx_size = hn_direct_tx_size;
+ if (hn_trust_hosttcp)
+ sc->hn_trust_hcsum |= HN_TRUST_HCSUM_TCP;
+ if (hn_trust_hostudp)
+ sc->hn_trust_hcsum |= HN_TRUST_HCSUM_UDP;
+ if (hn_trust_hostip)
+ sc->hn_trust_hcsum |= HN_TRUST_HCSUM_IP;
sc->hn_tx_taskq = taskqueue_create_fast("hn_tx", M_WAITOK,
taskqueue_thread_enqueue, &sc->hn_tx_taskq);
@@ -444,15 +415,12 @@ netvsc_attach(device_t dev)
ifp->if_capenable |=
IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | IFCAP_TSO |
IFCAP_LRO;
- /*
- * Only enable UDP checksum offloading when it is on 2012R2 or
- * later. UDP checksum offloading doesn't work on earlier
- * Windows releases.
- */
+
if (hv_vmbus_protocal_version >= HV_VMBUS_VERSION_WIN8_1)
- ifp->if_hwassist = CSUM_TCP | CSUM_UDP | CSUM_TSO;
+ sc->hn_csum_assist = HN_CSUM_ASSIST;
else
- ifp->if_hwassist = CSUM_TCP | CSUM_TSO;
+ sc->hn_csum_assist = HN_CSUM_ASSIST_WIN8;
+ ifp->if_hwassist = sc->hn_csum_assist | CSUM_TSO;
error = hv_rf_on_device_add(device_ctx, &device_info);
if (error)
@@ -463,9 +431,17 @@ netvsc_attach(device_t dev)
}
#if defined(INET) || defined(INET6)
+#if __FreeBSD_version >= 1100095
+ lroent_cnt = hn_lro_entry_count;
+ if (lroent_cnt < TCP_LRO_ENTRIES)
+ lroent_cnt = TCP_LRO_ENTRIES;
+ tcp_lro_init_args(&sc->hn_lro, ifp, lroent_cnt, 0);
+ device_printf(dev, "LRO: entry count %d\n", lroent_cnt);
+#else
tcp_lro_init(&sc->hn_lro);
/* Driver private LRO settings */
sc->hn_lro.ifp = ifp;
+#endif
#ifdef HN_LRO_HIWAT
sc->hn_lro.lro_hiwat = sc->hn_lro_hiwat;
#endif
@@ -509,17 +485,30 @@ netvsc_attach(device_t dev)
CTLTYPE_INT | CTLFLAG_RW, sc, 0, hn_lro_hiwat_sysctl,
"I", "LRO high watermark");
#endif
- SYSCTL_ADD_INT(ctx, child, OID_AUTO, "trust_hosttcp",
- CTLFLAG_RW, &sc->hn_trust_hosttcp, 0,
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "trust_hosttcp",
+ CTLTYPE_INT | CTLFLAG_RW, sc, HN_TRUST_HCSUM_TCP,
+ hn_trust_hcsum_sysctl, "I",
"Trust tcp segement verification on host side, "
"when csum info is missing");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "trust_hostudp",
+ CTLTYPE_INT | CTLFLAG_RW, sc, HN_TRUST_HCSUM_UDP,
+ hn_trust_hcsum_sysctl, "I",
+ "Trust udp datagram verification on host side, "
+ "when csum info is missing");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "trust_hostip",
+ CTLTYPE_INT | CTLFLAG_RW, sc, HN_TRUST_HCSUM_IP,
+ hn_trust_hcsum_sysctl, "I",
+ "Trust ip packet verification on host side, "
+ "when csum info is missing");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "csum_ip",
CTLFLAG_RW, &sc->hn_csum_ip, "RXCSUM IP");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "csum_tcp",
CTLFLAG_RW, &sc->hn_csum_tcp, "RXCSUM TCP");
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "csum_udp",
+ CTLFLAG_RW, &sc->hn_csum_udp, "RXCSUM UDP");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "csum_trusted",
CTLFLAG_RW, &sc->hn_csum_trusted,
- "# of TCP segements that we trust host's csum verification");
+ "# of packets that we trust host's csum verification");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "small_pkts",
CTLFLAG_RW, &sc->hn_small_pkts, "# of small packets received");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "no_txdescs",
@@ -545,6 +534,10 @@ netvsc_attach(device_t dev)
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "direct_tx_size",
CTLFLAG_RW, &sc->hn_direct_tx_size, 0,
"Size of the packet for direct transmission");
+ SYSCTL_ADD_INT(ctx, child, OID_AUTO, "sched_tx",
+ CTLFLAG_RW, &sc->hn_sched_tx, 0,
+ "Always schedule transmission "
+ "instead of doing direct transmission");
if (unit == 0) {
struct sysctl_ctx_list *dc_ctx;
@@ -562,6 +555,14 @@ netvsc_attach(device_t dev)
CTLFLAG_RD, &hn_trust_hosttcp, 0,
"Trust tcp segement verification on host side, "
"when csum info is missing (global setting)");
+ SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "trust_hostudp",
+ CTLFLAG_RD, &hn_trust_hostudp, 0,
+ "Trust udp datagram verification on host side, "
+ "when csum info is missing (global setting)");
+ SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "trust_hostip",
+ CTLFLAG_RD, &hn_trust_hostip, 0,
+ "Trust ip packet verification on host side, "
+ "when csum info is missing (global setting)");
SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "tx_chimney_size",
CTLFLAG_RD, &hn_tx_chimney_size, 0,
"Chimney send packet size limit");
@@ -572,6 +573,12 @@ netvsc_attach(device_t dev)
SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "direct_tx_size",
CTLFLAG_RD, &hn_direct_tx_size, 0,
"Size of the packet for direct transmission");
+#if defined(INET) || defined(INET6)
+#if __FreeBSD_version >= 1100095
+ SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "lro_entry_count",
+ CTLFLAG_RD, &hn_lro_entry_count, 0, "LRO entry count");
+#endif
+#endif
}
return (0);
@@ -761,6 +768,15 @@ void
netvsc_channel_rollup(struct hv_device *device_ctx)
{
struct hn_softc *sc = device_get_softc(device_ctx->device);
+#if defined(INET) || defined(INET6)
+ struct lro_ctrl *lro = &sc->hn_lro;
+ struct lro_entry *queued;
+
+ while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) {
+ SLIST_REMOVE_HEAD(&lro->lro_active, next);
+ tcp_lro_flush(lro, queued);
+ }
+#endif
if (!sc->hn_txeof)
return;
@@ -770,177 +786,94 @@ netvsc_channel_rollup(struct hv_device *device_ctx)
}
/*
- * Start a transmit of one or more packets
+ * NOTE:
+ * This this function fails, then both txd and m_head0 will be freed
*/
static int
-hn_start_locked(struct ifnet *ifp, int len)
+hn_encap(struct hn_softc *sc, struct hn_txdesc *txd, struct mbuf **m_head0)
{
- hn_softc_t *sc = ifp->if_softc;
- struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev);
- netvsc_dev *net_dev = sc->net_dev;
- struct ether_vlan_header *eh;
+ bus_dma_segment_t segs[HN_TX_DATA_SEGCNT_MAX];
+ int error, nsegs, i;
+ struct mbuf *m_head = *m_head0;
+ netvsc_packet *packet;
rndis_msg *rndis_mesg;
rndis_packet *rndis_pkt;
rndis_per_packet_info *rppi;
- ndis_8021q_info *rppi_vlan_info;
- rndis_tcp_ip_csum_info *csum_info;
- rndis_tcp_tso_info *tso_info;
- int ether_len;
- uint32_t rndis_msg_size = 0;
- uint32_t trans_proto_type;
+ uint32_t rndis_msg_size;
- if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
- IFF_DRV_RUNNING)
- return 0;
+ packet = &txd->netvsc_pkt;
+ packet->is_data_pkt = TRUE;
+ packet->tot_data_buf_len = m_head->m_pkthdr.len;
- while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
- bus_dma_segment_t segs[HN_TX_DATA_SEGCNT_MAX];
- int error, nsegs, i, send_failed = 0;
- struct hn_txdesc *txd;
- netvsc_packet *packet;
- struct mbuf *m_head;
-
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
- if (m_head == NULL)
- break;
+ /*
+ * extension points to the area reserved for the
+ * rndis_filter_packet, which is placed just after
+ * the netvsc_packet (and rppi struct, if present;
+ * length is updated later).
+ */
+ rndis_mesg = txd->rndis_msg;
+ /* XXX not necessary */
+ memset(rndis_mesg, 0, HN_RNDIS_MSG_LEN);
+ rndis_mesg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG;
- if (len > 0 && m_head->m_pkthdr.len > len) {
- /*
- * This sending could be time consuming; let callers
- * dispatch this packet sending (and sending of any
- * following up packets) to tx taskqueue.
- */
- IF_PREPEND(&ifp->if_snd, m_head);
- return 1;
- }
+ rndis_pkt = &rndis_mesg->msg.packet;
+ rndis_pkt->data_offset = sizeof(rndis_packet);
+ rndis_pkt->data_length = packet->tot_data_buf_len;
+ rndis_pkt->per_pkt_info_offset = sizeof(rndis_packet);
- txd = hn_txdesc_get(sc);
- if (txd == NULL) {
- sc->hn_no_txdescs++;
- IF_PREPEND(&ifp->if_snd, m_head);
- atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
- break;
- }
+ rndis_msg_size = RNDIS_MESSAGE_SIZE(rndis_packet);
- packet = &txd->netvsc_pkt;
- packet->is_data_pkt = TRUE;
- /* Initialize it from the mbuf */
- packet->tot_data_buf_len = m_head->m_pkthdr.len;
+ if (m_head->m_flags & M_VLANTAG) {
+ ndis_8021q_info *rppi_vlan_info;
- /*
- * extension points to the area reserved for the
- * rndis_filter_packet, which is placed just after
- * the netvsc_packet (and rppi struct, if present;
- * length is updated later).
- */
- rndis_mesg = txd->rndis_msg;
- /* XXX not necessary */
- memset(rndis_mesg, 0, HN_RNDIS_MSG_LEN);
- rndis_mesg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG;
+ rndis_msg_size += RNDIS_VLAN_PPI_SIZE;
+ rppi = hv_set_rppi_data(rndis_mesg, RNDIS_VLAN_PPI_SIZE,
+ ieee_8021q_info);
- rndis_pkt = &rndis_mesg->msg.packet;
- rndis_pkt->data_offset = sizeof(rndis_packet);
- rndis_pkt->data_length = packet->tot_data_buf_len;
- rndis_pkt->per_pkt_info_offset = sizeof(rndis_packet);
+ rppi_vlan_info = (ndis_8021q_info *)((uint8_t *)rppi +
+ rppi->per_packet_info_offset);
+ rppi_vlan_info->u1.s1.vlan_id =
+ m_head->m_pkthdr.ether_vtag & 0xfff;
+ }
- rndis_msg_size = RNDIS_MESSAGE_SIZE(rndis_packet);
+ if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
+ rndis_tcp_tso_info *tso_info;
+ struct ether_vlan_header *eh;
+ int ether_len;
/*
- * If the Hyper-V infrastructure needs to embed a VLAN tag,
- * initialize netvsc_packet and rppi struct values as needed.
+ * XXX need m_pullup and use mtodo
*/
- if (m_head->m_flags & M_VLANTAG) {
- /*
- * set up some additional fields so the Hyper-V infrastructure will stuff the VLAN tag
- * into the frame.
- */
- rndis_msg_size += RNDIS_VLAN_PPI_SIZE;
-
- rppi = hv_set_rppi_data(rndis_mesg, RNDIS_VLAN_PPI_SIZE,
- ieee_8021q_info);
-
- /* VLAN info immediately follows rppi struct */
- rppi_vlan_info = (ndis_8021q_info *)((char*)rppi +
- rppi->per_packet_info_offset);
- /* FreeBSD does not support CFI or priority */
- rppi_vlan_info->u1.s1.vlan_id =
- m_head->m_pkthdr.ether_vtag & 0xfff;
- }
-
- /* Only check the flags for outbound and ignore the ones for inbound */
- if (0 == (m_head->m_pkthdr.csum_flags & HV_CSUM_FOR_OUTBOUND)) {
- goto pre_send;
- }
-
eh = mtod(m_head, struct ether_vlan_header*);
- if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
+ if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN))
ether_len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
- } else {
+ else
ether_len = ETHER_HDR_LEN;
- }
-
- trans_proto_type = get_transport_proto_type(m_head);
- if (TRANSPORT_TYPE_NOT_IP == trans_proto_type) {
- goto pre_send;
- }
- /*
- * TSO packet needless to setup the send side checksum
- * offload.
- */
- if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
- goto do_tso;
- }
-
- /* setup checksum offload */
- rndis_msg_size += RNDIS_CSUM_PPI_SIZE;
- rppi = hv_set_rppi_data(rndis_mesg, RNDIS_CSUM_PPI_SIZE,
- tcpip_chksum_info);
- csum_info = (rndis_tcp_ip_csum_info *)((char*)rppi +
- rppi->per_packet_info_offset);
-
- if (trans_proto_type & (TYPE_IPV4 << 16)) {
- csum_info->xmit.is_ipv4 = 1;
- } else {
- csum_info->xmit.is_ipv6 = 1;
- }
-
- if (trans_proto_type & TYPE_TCP) {
- csum_info->xmit.tcp_csum = 1;
- csum_info->xmit.tcp_header_offset = 0;
- } else if (trans_proto_type & TYPE_UDP) {
- csum_info->xmit.udp_csum = 1;
- }
-
- goto pre_send;
-
-do_tso:
- /* setup TCP segmentation offload */
rndis_msg_size += RNDIS_TSO_PPI_SIZE;
rppi = hv_set_rppi_data(rndis_mesg, RNDIS_TSO_PPI_SIZE,
tcp_large_send_info);
-
- tso_info = (rndis_tcp_tso_info *)((char *)rppi +
+
+ tso_info = (rndis_tcp_tso_info *)((uint8_t *)rppi +
rppi->per_packet_info_offset);
tso_info->lso_v2_xmit.type =
RNDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE;
-
+
#ifdef INET
- if (trans_proto_type & (TYPE_IPV4 << 16)) {
+ if (m_head->m_pkthdr.csum_flags & CSUM_IP_TSO) {
struct ip *ip =
(struct ip *)(m_head->m_data + ether_len);
unsigned long iph_len = ip->ip_hl << 2;
struct tcphdr *th =
(struct tcphdr *)((caddr_t)ip + iph_len);
-
+
tso_info->lso_v2_xmit.ip_version =
RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV4;
ip->ip_len = 0;
ip->ip_sum = 0;
-
+
th->th_sum = in_pseudo(ip->ip_src.s_addr,
- ip->ip_dst.s_addr,
- htons(IPPROTO_TCP));
+ ip->ip_dst.s_addr, htons(IPPROTO_TCP));
}
#endif
#if defined(INET6) && defined(INET)
@@ -948,8 +881,8 @@ do_tso:
#endif
#ifdef INET6
{
- struct ip6_hdr *ip6 =
- (struct ip6_hdr *)(m_head->m_data + ether_len);
+ struct ip6_hdr *ip6 = (struct ip6_hdr *)
+ (m_head->m_data + ether_len);
struct tcphdr *th = (struct tcphdr *)(ip6 + 1);
tso_info->lso_v2_xmit.ip_version =
@@ -960,98 +893,163 @@ do_tso:
#endif
tso_info->lso_v2_xmit.tcp_header_offset = 0;
tso_info->lso_v2_xmit.mss = m_head->m_pkthdr.tso_segsz;
+ } else if (m_head->m_pkthdr.csum_flags & sc->hn_csum_assist) {
+ rndis_tcp_ip_csum_info *csum_info;
-pre_send:
- rndis_mesg->msg_len = packet->tot_data_buf_len + rndis_msg_size;
- packet->tot_data_buf_len = rndis_mesg->msg_len;
-
- /* send packet with send buffer */
- if (packet->tot_data_buf_len < sc->hn_tx_chimney_size) {
- uint32_t send_buf_section_idx;
-
- send_buf_section_idx =
- hv_nv_get_next_send_section(net_dev);
- if (send_buf_section_idx !=
- NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
- uint8_t *dest = ((uint8_t *)net_dev->send_buf +
- (send_buf_section_idx *
- net_dev->send_section_size));
-
- memcpy(dest, rndis_mesg, rndis_msg_size);
- dest += rndis_msg_size;
-
- m_copydata(m_head, 0, m_head->m_pkthdr.len,
- dest);
-
- packet->send_buf_section_idx =
- send_buf_section_idx;
- packet->send_buf_section_size =
- packet->tot_data_buf_len;
- packet->page_buf_count = 0;
- sc->hn_tx_chimney++;
- goto do_send;
- }
- }
-
- error = hn_txdesc_dmamap_load(sc, txd, &m_head, segs, &nsegs);
- if (error) {
- int freed;
+ rndis_msg_size += RNDIS_CSUM_PPI_SIZE;
+ rppi = hv_set_rppi_data(rndis_mesg, RNDIS_CSUM_PPI_SIZE,
+ tcpip_chksum_info);
+ csum_info = (rndis_tcp_ip_csum_info *)((uint8_t *)rppi +
+ rppi->per_packet_info_offset);
- /*
- * This mbuf is not linked w/ the txd yet, so free
- * it now.
- */
- m_freem(m_head);
- freed = hn_txdesc_put(sc, txd);
- KASSERT(freed != 0,
- ("fail to free txd upon txdma error"));
+ csum_info->xmit.is_ipv4 = 1;
+ if (m_head->m_pkthdr.csum_flags & CSUM_IP)
+ csum_info->xmit.ip_header_csum = 1;
- sc->hn_txdma_failed++;
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- continue;
+ if (m_head->m_pkthdr.csum_flags & CSUM_TCP) {
+ csum_info->xmit.tcp_csum = 1;
+ csum_info->xmit.tcp_header_offset = 0;
+ } else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) {
+ csum_info->xmit.udp_csum = 1;
}
+ }
+
+ rndis_mesg->msg_len = packet->tot_data_buf_len + rndis_msg_size;
+ packet->tot_data_buf_len = rndis_mesg->msg_len;
- packet->page_buf_count = nsegs +
- HV_RF_NUM_TX_RESERVED_PAGE_BUFS;
+ /*
+ * Chimney send, if the packet could fit into one chimney buffer.
+ */
+ if (packet->tot_data_buf_len < sc->hn_tx_chimney_size) {
+ netvsc_dev *net_dev = sc->net_dev;
+ uint32_t send_buf_section_idx;
+
+ send_buf_section_idx =
+ hv_nv_get_next_send_section(net_dev);
+ if (send_buf_section_idx !=
+ NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
+ uint8_t *dest = ((uint8_t *)net_dev->send_buf +
+ (send_buf_section_idx *
+ net_dev->send_section_size));
+
+ memcpy(dest, rndis_mesg, rndis_msg_size);
+ dest += rndis_msg_size;
+ m_copydata(m_head, 0, m_head->m_pkthdr.len, dest);
+
+ packet->send_buf_section_idx = send_buf_section_idx;
+ packet->send_buf_section_size =
+ packet->tot_data_buf_len;
+ packet->page_buf_count = 0;
+ sc->hn_tx_chimney++;
+ goto done;
+ }
+ }
- /* send packet with page buffer */
- packet->page_buffers[0].pfn = atop(txd->rndis_msg_paddr);
- packet->page_buffers[0].offset =
- txd->rndis_msg_paddr & PAGE_MASK;
- packet->page_buffers[0].length = rndis_msg_size;
+ error = hn_txdesc_dmamap_load(sc, txd, &m_head, segs, &nsegs);
+ if (error) {
+ int freed;
/*
- * Fill the page buffers with mbuf info starting at index
- * HV_RF_NUM_TX_RESERVED_PAGE_BUFS.
+ * This mbuf is not linked w/ the txd yet, so free it now.
*/
- for (i = 0; i < nsegs; ++i) {
- hv_vmbus_page_buffer *pb = &packet->page_buffers[
- i + HV_RF_NUM_TX_RESERVED_PAGE_BUFS];
+ m_freem(m_head);
+ *m_head0 = NULL;
- pb->pfn = atop(segs[i].ds_addr);
- pb->offset = segs[i].ds_addr & PAGE_MASK;
- pb->length = segs[i].ds_len;
- }
+ freed = hn_txdesc_put(sc, txd);
+ KASSERT(freed != 0,
+ ("fail to free txd upon txdma error"));
- packet->send_buf_section_idx =
- NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
- packet->send_buf_section_size = 0;
+ sc->hn_txdma_failed++;
+ if_inc_counter(sc->hn_ifp, IFCOUNTER_OERRORS, 1);
+ return error;
+ }
+ *m_head0 = m_head;
+
+ packet->page_buf_count = nsegs + HV_RF_NUM_TX_RESERVED_PAGE_BUFS;
+
+ /* send packet with page buffer */
+ packet->page_buffers[0].pfn = atop(txd->rndis_msg_paddr);
+ packet->page_buffers[0].offset = txd->rndis_msg_paddr & PAGE_MASK;
+ packet->page_buffers[0].length = rndis_msg_size;
-do_send:
- txd->m = m_head;
+ /*
+ * Fill the page buffers with mbuf info starting at index
+ * HV_RF_NUM_TX_RESERVED_PAGE_BUFS.
+ */
+ for (i = 0; i < nsegs; ++i) {
+ hv_vmbus_page_buffer *pb = &packet->page_buffers[
+ i + HV_RF_NUM_TX_RESERVED_PAGE_BUFS];
+
+ pb->pfn = atop(segs[i].ds_addr);
+ pb->offset = segs[i].ds_addr & PAGE_MASK;
+ pb->length = segs[i].ds_len;
+ }
+
+ packet->send_buf_section_idx =
+ NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
+ packet->send_buf_section_size = 0;
+done:
+ txd->m = m_head;
+
+ /* Set the completion routine */
+ packet->compl.send.on_send_completion = netvsc_xmit_completion;
+ packet->compl.send.send_completion_context = packet;
+ packet->compl.send.send_completion_tid = (uint64_t)(uintptr_t)txd;
+
+ return 0;
+}
+
+/*
+ * Start a transmit of one or more packets
+ */
+static int
+hn_start_locked(struct ifnet *ifp, int len)
+{
+ struct hn_softc *sc = ifp->if_softc;
+ struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev);
+
+ if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+ IFF_DRV_RUNNING)
+ return 0;
+
+ while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
+ int error, send_failed = 0;
+ struct hn_txdesc *txd;
+ struct mbuf *m_head;
+
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
+ if (m_head == NULL)
+ break;
+
+ if (len > 0 && m_head->m_pkthdr.len > len) {
+ /*
+ * This sending could be time consuming; let callers
+ * dispatch this packet sending (and sending of any
+ * following up packets) to tx taskqueue.
+ */
+ IF_PREPEND(&ifp->if_snd, m_head);
+ return 1;
+ }
- /* Set the completion routine */
- packet->compl.send.on_send_completion = netvsc_xmit_completion;
- packet->compl.send.send_completion_context = packet;
- packet->compl.send.send_completion_tid =
- (uint64_t)(uintptr_t)txd;
+ txd = hn_txdesc_get(sc);
+ if (txd == NULL) {
+ sc->hn_no_txdescs++;
+ IF_PREPEND(&ifp->if_snd, m_head);
+ atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
+ break;
+ }
+ error = hn_encap(sc, txd, &m_head);
+ if (error) {
+ /* Both txd and m_head are freed */
+ continue;
+ }
again:
/*
* Make sure that txd is not freed before ETHER_BPF_MTAP.
*/
hn_txdesc_hold(txd);
- error = hv_nv_on_send(device_ctx, packet);
+ error = hv_nv_on_send(device_ctx, &txd->netvsc_pkt);
if (!error) {
ETHER_BPF_MTAP(ifp, m_head);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
@@ -1191,7 +1189,7 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet,
struct mbuf *m_new;
struct ifnet *ifp;
device_t dev = device_ctx->device;
- int size, do_lro = 0;
+ int size, do_lro = 0, do_csum = 1;
if (sc == NULL) {
return (0); /* TODO: KYS how can this be! */
@@ -1239,21 +1237,28 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet,
}
m_new->m_pkthdr.rcvif = ifp;
+ if (__predict_false((ifp->if_capenable & IFCAP_RXCSUM) == 0))
+ do_csum = 0;
+
/* receive side checksum offload */
- if (NULL != csum_info) {
+ if (csum_info != NULL) {
/* IP csum offload */
- if (csum_info->receive.ip_csum_succeeded) {
+ if (csum_info->receive.ip_csum_succeeded && do_csum) {
m_new->m_pkthdr.csum_flags |=
(CSUM_IP_CHECKED | CSUM_IP_VALID);
sc->hn_csum_ip++;
}
- /* TCP csum offload */
- if (csum_info->receive.tcp_csum_succeeded) {
+ /* TCP/UDP csum offload */
+ if ((csum_info->receive.tcp_csum_succeeded ||
+ csum_info->receive.udp_csum_succeeded) && do_csum) {
m_new->m_pkthdr.csum_flags |=
(CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
m_new->m_pkthdr.csum_data = 0xffff;
- sc->hn_csum_tcp++;
+ if (csum_info->receive.tcp_csum_succeeded)
+ sc->hn_csum_tcp++;
+ else
+ sc->hn_csum_udp++;
}
if (csum_info->receive.ip_csum_succeeded &&
@@ -1284,7 +1289,8 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet,
pr = hn_check_iplen(m_new, hoff);
if (pr == IPPROTO_TCP) {
- if (sc->hn_trust_hosttcp) {
+ if (do_csum &&
+ (sc->hn_trust_hcsum & HN_TRUST_HCSUM_TCP)) {
sc->hn_csum_trusted++;
m_new->m_pkthdr.csum_flags |=
(CSUM_IP_CHECKED | CSUM_IP_VALID |
@@ -1293,6 +1299,20 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet,
}
/* Rely on SW csum verification though... */
do_lro = 1;
+ } else if (pr == IPPROTO_UDP) {
+ if (do_csum &&
+ (sc->hn_trust_hcsum & HN_TRUST_HCSUM_UDP)) {
+ sc->hn_csum_trusted++;
+ m_new->m_pkthdr.csum_flags |=
+ (CSUM_IP_CHECKED | CSUM_IP_VALID |
+ CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
+ m_new->m_pkthdr.csum_data = 0xffff;
+ }
+ } else if (pr != IPPROTO_DONE && do_csum &&
+ (sc->hn_trust_hcsum & HN_TRUST_HCSUM_IP)) {
+ sc->hn_csum_trusted++;
+ m_new->m_pkthdr.csum_flags |=
+ (CSUM_IP_CHECKED | CSUM_IP_VALID);
}
}
}
@@ -1331,18 +1351,8 @@ skip:
}
void
-netvsc_recv_rollup(struct hv_device *device_ctx)
+netvsc_recv_rollup(struct hv_device *device_ctx __unused)
{
-#if defined(INET) || defined(INET6)
- hn_softc_t *sc = device_get_softc(device_ctx->device);
- struct lro_ctrl *lro = &sc->hn_lro;
- struct lro_entry *queued;
-
- while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lro->lro_active, next);
- tcp_lro_flush(lro, queued);
- }
-#endif
}
/*
@@ -1506,47 +1516,40 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = 0;
break;
case SIOCSIFCAP:
+ NV_LOCK(sc);
+
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
if (mask & IFCAP_TXCSUM) {
- if (IFCAP_TXCSUM & ifp->if_capenable) {
- ifp->if_capenable &= ~IFCAP_TXCSUM;
- ifp->if_hwassist &= ~(CSUM_TCP | CSUM_UDP);
- } else {
- ifp->if_capenable |= IFCAP_TXCSUM;
- /*
- * Only enable UDP checksum offloading on
- * Windows Server 2012R2 or later releases.
- */
- if (hv_vmbus_protocal_version >=
- HV_VMBUS_VERSION_WIN8_1) {
- ifp->if_hwassist |=
- (CSUM_TCP | CSUM_UDP);
- } else {
- ifp->if_hwassist |= CSUM_TCP;
- }
- }
+ ifp->if_capenable ^= IFCAP_TXCSUM;
+ if (ifp->if_capenable & IFCAP_TXCSUM)
+ ifp->if_hwassist |= sc->hn_csum_assist;
+ else
+ ifp->if_hwassist &= ~sc->hn_csum_assist;
}
- if (mask & IFCAP_RXCSUM) {
- if (IFCAP_RXCSUM & ifp->if_capenable) {
- ifp->if_capenable &= ~IFCAP_RXCSUM;
- } else {
- ifp->if_capenable |= IFCAP_RXCSUM;
- }
- }
+ if (mask & IFCAP_RXCSUM)
+ ifp->if_capenable ^= IFCAP_RXCSUM;
+
if (mask & IFCAP_LRO)
ifp->if_capenable ^= IFCAP_LRO;
if (mask & IFCAP_TSO4) {
ifp->if_capenable ^= IFCAP_TSO4;
- ifp->if_hwassist ^= CSUM_IP_TSO;
+ if (ifp->if_capenable & IFCAP_TSO4)
+ ifp->if_hwassist |= CSUM_IP_TSO;
+ else
+ ifp->if_hwassist &= ~CSUM_IP_TSO;
}
if (mask & IFCAP_TSO6) {
ifp->if_capenable ^= IFCAP_TSO6;
- ifp->if_hwassist ^= CSUM_IP6_TSO;
+ if (ifp->if_capenable & IFCAP_TSO6)
+ ifp->if_hwassist |= CSUM_IP6_TSO;
+ else
+ ifp->if_hwassist &= ~CSUM_IP6_TSO;
}
+ NV_UNLOCK(sc);
error = 0;
break;
case SIOCADDMULTI:
@@ -1603,9 +1606,11 @@ hn_stop(hn_softc_t *sc)
static void
hn_start(struct ifnet *ifp)
{
- hn_softc_t *sc;
+ struct hn_softc *sc = ifp->if_softc;
+
+ if (sc->hn_sched_tx)
+ goto do_sched;
- sc = ifp->if_softc;
if (NV_TRYLOCK(sc)) {
int sched;
@@ -1614,15 +1619,18 @@ hn_start(struct ifnet *ifp)
if (!sched)
return;
}
+do_sched:
taskqueue_enqueue_fast(sc->hn_tx_taskq, &sc->hn_start_task);
}
static void
hn_start_txeof(struct ifnet *ifp)
{
- hn_softc_t *sc;
+ struct hn_softc *sc = ifp->if_softc;
+
+ if (sc->hn_sched_tx)
+ goto do_sched;
- sc = ifp->if_softc;
if (NV_TRYLOCK(sc)) {
int sched;
@@ -1634,6 +1642,7 @@ hn_start_txeof(struct ifnet *ifp)
&sc->hn_start_task);
}
} else {
+do_sched:
/*
* Release the OACTIVE earlier, with the hope, that
* others could catch up. The task will clear the
@@ -1735,6 +1744,30 @@ hn_lro_hiwat_sysctl(SYSCTL_HANDLER_ARGS)
#endif /* HN_LRO_HIWAT */
static int
+hn_trust_hcsum_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct hn_softc *sc = arg1;
+ int hcsum = arg2;
+ int on, error;
+
+ on = 0;
+ if (sc->hn_trust_hcsum & hcsum)
+ on = 1;
+
+ error = sysctl_handle_int(oidp, &on, 0, req);
+ if (error || req->newptr == NULL)
+ return error;
+
+ NV_LOCK(sc);
+ if (on)
+ sc->hn_trust_hcsum |= hcsum;
+ else
+ sc->hn_trust_hcsum &= ~hcsum;
+ NV_UNLOCK(sc);
+ return 0;
+}
+
+static int
hn_tx_chimney_size_sysctl(SYSCTL_HANDLER_ARGS)
{
struct hn_softc *sc = arg1;
diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c
index dfd0b4727938..9fb78eeeb406 100644
--- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c
+++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c
@@ -135,12 +135,9 @@ hv_get_rndis_device(void)
{
rndis_device *device;
- device = malloc(sizeof(rndis_device), M_NETVSC, M_NOWAIT | M_ZERO);
- if (device == NULL) {
- return (NULL);
- }
+ device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO);
- mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_SPIN | MTX_RECURSE);
+ mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF);
/* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
STAILQ_INIT(&device->myrequest_list);
@@ -171,10 +168,7 @@ hv_rndis_request(rndis_device *device, uint32_t message_type,
rndis_msg *rndis_mesg;
rndis_set_request *set;
- request = malloc(sizeof(rndis_request), M_NETVSC, M_NOWAIT | M_ZERO);
- if (request == NULL) {
- return (NULL);
- }
+ request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
sema_init(&request->wait_sema, 0, "rndis sema");
@@ -193,9 +187,9 @@ hv_rndis_request(rndis_device *device, uint32_t message_type,
set->request_id += 1;
/* Add to the request list */
- mtx_lock_spin(&device->req_lock);
+ mtx_lock(&device->req_lock);
STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
- mtx_unlock_spin(&device->req_lock);
+ mtx_unlock(&device->req_lock);
return (request);
}
@@ -206,14 +200,14 @@ hv_rndis_request(rndis_device *device, uint32_t message_type,
static inline void
hv_put_rndis_request(rndis_device *device, rndis_request *request)
{
- mtx_lock_spin(&device->req_lock);
+ mtx_lock(&device->req_lock);
/* Fixme: Has O(n) performance */
/*
* XXXKYS: Use Doubly linked lists.
*/
STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
mylist_entry);
- mtx_unlock_spin(&device->req_lock);
+ mtx_unlock(&device->req_lock);
sema_destroy(&request->wait_sema);
free(request, M_NETVSC);
@@ -270,7 +264,7 @@ hv_rf_receive_response(rndis_device *device, rndis_msg *response)
rndis_request *next_request;
boolean_t found = FALSE;
- mtx_lock_spin(&device->req_lock);
+ mtx_lock(&device->req_lock);
request = STAILQ_FIRST(&device->myrequest_list);
while (request != NULL) {
/*
@@ -285,7 +279,7 @@ hv_rf_receive_response(rndis_device *device, rndis_msg *response)
next_request = STAILQ_NEXT(request, mylist_entry);
request = next_request;
}
- mtx_unlock_spin(&device->req_lock);
+ mtx_unlock(&device->req_lock);
if (found) {
if (response->msg_len <= sizeof(rndis_msg)) {
diff --git a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
index 098c8c9fda70..9683ad8f4ec4 100644
--- a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
+++ b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
@@ -1524,13 +1524,12 @@ static void
storvsc_destroy_bounce_buffer(struct sglist *sgl)
{
struct hv_sgl_node *sgl_node = NULL;
-
- sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.in_use_sgl_list);
- LIST_REMOVE(sgl_node, link);
- if (NULL == sgl_node) {
+ if (LIST_EMPTY(&g_hv_sgl_page_pool.in_use_sgl_list)) {
printf("storvsc error: not enough in use sgl\n");
return;
}
+ sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.in_use_sgl_list);
+ LIST_REMOVE(sgl_node, link);
sgl_node->sgl_data = sgl;
LIST_INSERT_HEAD(&g_hv_sgl_page_pool.free_sgl_list, sgl_node, link);
}
@@ -1556,12 +1555,12 @@ storvsc_create_bounce_buffer(uint16_t seg_count, int write)
struct hv_sgl_node *sgl_node = NULL;
/* get struct sglist from free_sgl_list */
- sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.free_sgl_list);
- LIST_REMOVE(sgl_node, link);
- if (NULL == sgl_node) {
+ if (LIST_EMPTY(&g_hv_sgl_page_pool.free_sgl_list)) {
printf("storvsc error: not enough free sgl\n");
return NULL;
}
+ sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.free_sgl_list);
+ LIST_REMOVE(sgl_node, link);
bounce_sgl = sgl_node->sgl_data;
LIST_INSERT_HEAD(&g_hv_sgl_page_pool.in_use_sgl_list, sgl_node, link);
diff --git a/sys/dev/hyperv/utilities/hv_kvp.c b/sys/dev/hyperv/utilities/hv_kvp.c
index 58d565c44bfb..86e037ab7e79 100644
--- a/sys/dev/hyperv/utilities/hv_kvp.c
+++ b/sys/dev/hyperv/utilities/hv_kvp.c
@@ -98,7 +98,7 @@ static d_poll_t hv_kvp_dev_daemon_poll;
static int hv_kvp_req_in_progress(void);
static void hv_kvp_transaction_init(uint32_t, hv_vmbus_channel *, uint64_t, uint8_t *);
static void hv_kvp_send_msg_to_daemon(void);
-static void hv_kvp_process_request(void *context);
+static void hv_kvp_process_request(void *context, int pending);
/* hv_kvp character device structure */
static struct cdevsw hv_kvp_cdevsw =
@@ -123,9 +123,6 @@ static struct selinfo hv_kvp_selinfo;
*/
static struct {
- /* Pre-allocated work item for queue */
- hv_work_item work_item;
-
/* Unless specified the pending mutex should be
* used to alter the values of the following paramters:
* 1. req_in_progress
@@ -642,7 +639,7 @@ hv_kvp_send_msg_to_daemon(void)
* and interact with daemon
*/
static void
-hv_kvp_process_request(void *context)
+hv_kvp_process_request(void *context, int pending)
{
uint8_t *kvp_buf;
hv_vmbus_channel *channel = context;
@@ -756,23 +753,18 @@ hv_kvp_callback(void *context)
uint64_t pending_cnt = 0;
if (kvp_globals.register_done == false) {
-
kvp_globals.channelp = context;
+ TASK_INIT(&service_table[HV_KVP].task, 0, hv_kvp_process_request, context);
} else {
-
mtx_lock(&kvp_globals.pending_mutex);
kvp_globals.pending_reqs = kvp_globals.pending_reqs + 1;
pending_cnt = kvp_globals.pending_reqs;
mtx_unlock(&kvp_globals.pending_mutex);
if (pending_cnt == 1) {
hv_kvp_log_info("%s: Queuing work item\n", __func__);
- hv_queue_work_item(
- service_table[HV_KVP].work_queue,
- hv_kvp_process_request,
- context
- );
+ taskqueue_enqueue(taskqueue_thread, &service_table[HV_KVP].task);
}
- }
+ }
}
@@ -977,26 +969,13 @@ int
hv_kvp_init(hv_vmbus_service *srv)
{
int error = 0;
- hv_work_queue *work_queue = NULL;
-
- memset(&kvp_globals, 0, sizeof(kvp_globals));
- work_queue = hv_work_queue_create("KVP Service");
- if (work_queue == NULL) {
- hv_kvp_log_info("%s: Work queue alloc failed\n", __func__);
- error = ENOMEM;
- hv_kvp_log_error("%s: ENOMEM\n", __func__);
- goto Finish;
- }
- srv->work_queue = work_queue;
+ memset(&kvp_globals, 0, sizeof(kvp_globals));
error = hv_kvp_dev_init();
mtx_init(&kvp_globals.pending_mutex, "hv-kvp pending mutex",
- NULL, MTX_DEF);
- kvp_globals.pending_reqs = 0;
-
+ NULL, MTX_DEF);
-Finish:
return (error);
}
diff --git a/sys/dev/hyperv/utilities/hv_util.c b/sys/dev/hyperv/utilities/hv_util.c
index dc4b1e2537ba..38054ca566ba 100644
--- a/sys/dev/hyperv/utilities/hv_util.c
+++ b/sys/dev/hyperv/utilities/hv_util.c
@@ -52,6 +52,8 @@ static void hv_heartbeat_cb(void *context);
static void hv_timesync_cb(void *context);
static int hv_timesync_init(hv_vmbus_service *serv);
+static int hv_timesync_uninit(hv_vmbus_service *serv);
+static void hv_set_host_time(void *context, int pending);
/*
* Note: GUID codes below are predefined by the host hypervisor
@@ -73,6 +75,7 @@ hv_vmbus_service service_table[] = {
.enabled = TRUE,
.init = hv_timesync_init,
.callback = hv_timesync_cb,
+ .uninit = hv_timesync_uninit,
},
/* Heartbeat Service */
@@ -111,10 +114,16 @@ struct hv_ictimesync_data {
static int
hv_timesync_init(hv_vmbus_service *serv)
{
+ void *time_msg = malloc(sizeof(time_sync_data), M_DEVBUF, M_WAITOK);
+ TASK_INIT(&serv->task, 1, hv_set_host_time, time_msg);
+ return (0);
+}
- serv->work_queue = hv_work_queue_create("Time Sync");
- if (serv->work_queue == NULL)
- return (ENOMEM);
+static int
+hv_timesync_uninit(hv_vmbus_service *serv)
+{
+ taskqueue_drain(taskqueue_thread, &serv->task);
+ free(serv->task.ta_context, M_DEVBUF);
return (0);
}
@@ -152,9 +161,9 @@ hv_negotiate_version(
* Set host time based on time sync message from host
*/
static void
-hv_set_host_time(void *context)
+hv_set_host_time(void *context, int pending)
{
- time_sync_data* time_msg = (time_sync_data*) context;
+ time_sync_data* time_msg = (time_sync_data*) context;
uint64_t hosttime = time_msg->data;
struct timespec guest_ts, host_ts;
uint64_t host_tns;
@@ -166,7 +175,7 @@ hv_set_host_time(void *context)
host_ts.tv_nsec = (long)(host_tns%HV_NANO_SEC_PER_SEC);
nanotime(&guest_ts);
-
+
diff = (int64_t)host_ts.tv_sec - (int64_t)guest_ts.tv_sec;
/*
@@ -175,12 +184,7 @@ hv_set_host_time(void *context)
if (diff > 5 || diff < -5) {
error = kern_clock_settime(curthread, CLOCK_REALTIME,
&host_ts);
- }
-
- /*
- * Free the hosttime that was allocated in hv_adj_guesttime()
- */
- free(time_msg, M_DEVBUF);
+ }
}
/**
@@ -197,23 +201,13 @@ hv_set_host_time(void *context)
static inline
void hv_adj_guesttime(uint64_t hosttime, uint8_t flags)
{
- time_sync_data* time_msg;
-
- time_msg = malloc(sizeof(time_sync_data), M_DEVBUF, M_NOWAIT);
+ time_sync_data* time_msg = service_table[HV_TIME_SYNCH].task.ta_context;
- if (time_msg == NULL)
- return;
-
time_msg->data = hosttime;
- if ((flags & HV_ICTIMESYNCFLAG_SYNC) != 0) {
- hv_queue_work_item(service_table[HV_TIME_SYNCH].work_queue,
- hv_set_host_time, time_msg);
- } else if ((flags & HV_ICTIMESYNCFLAG_SAMPLE) != 0) {
- hv_queue_work_item(service_table[HV_TIME_SYNCH].work_queue,
- hv_set_host_time, time_msg);
- } else {
- free(time_msg, M_DEVBUF);
+ if (((flags & HV_ICTIMESYNCFLAG_SYNC) != 0) ||
+ ((flags & HV_ICTIMESYNCFLAG_SAMPLE) != 0)) {
+ taskqueue_enqueue(taskqueue_thread, &service_table[HV_TIME_SYNCH].task);
}
}
@@ -452,19 +446,14 @@ hv_util_detach(device_t dev)
service = device_get_softc(dev);
receive_buffer_offset = service - &service_table[0];
- if (service->work_queue != NULL)
- hv_work_queue_close(service->work_queue);
+ if (service->uninit != NULL)
+ service->uninit(service);
free(receive_buffer[receive_buffer_offset], M_DEVBUF);
receive_buffer[receive_buffer_offset] = NULL;
return (0);
}
-static void
-hv_util_init(void)
-{
-}
-
static int
hv_util_modevent(module_t mod, int event, void *arg)
{
@@ -495,6 +484,3 @@ static devclass_t util_devclass;
DRIVER_MODULE(hv_utils, vmbus, util_driver, util_devclass, hv_util_modevent, 0);
MODULE_VERSION(hv_utils, 1);
MODULE_DEPEND(hv_utils, vmbus, 1, 1, 1);
-
-SYSINIT(hv_util_initx, SI_SUB_KTHREAD_IDLE, SI_ORDER_MIDDLE + 1,
- hv_util_init, NULL);
diff --git a/sys/dev/hyperv/vmbus/hv_channel.c b/sys/dev/hyperv/vmbus/hv_channel.c
index 762ace4fe423..af7395b445f5 100644
--- a/sys/dev/hyperv/vmbus/hv_channel.c
+++ b/sys/dev/hyperv/vmbus/hv_channel.c
@@ -68,9 +68,7 @@ vmbus_channel_set_event(hv_vmbus_channel *channel)
+ ((channel->offer_msg.child_rel_id >> 5))));
monitor_page = (hv_vmbus_monitor_page *)
- hv_vmbus_g_connection.monitor_pages;
-
- monitor_page++; /* Get the child to parent monitor page */
+ hv_vmbus_g_connection.monitor_page_2;
synch_set_bit(channel->monitor_bit,
(uint32_t *)&monitor_page->
diff --git a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
index 93008aad857e..21f7d956d39c 100644
--- a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
+++ b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
@@ -36,8 +36,10 @@
*/
static void vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr);
+static void vmbus_channel_on_offer_internal(void* context);
static void vmbus_channel_on_open_result(hv_vmbus_channel_msg_header* hdr);
static void vmbus_channel_on_offer_rescind(hv_vmbus_channel_msg_header* hdr);
+static void vmbus_channel_on_offer_rescind_internal(void* context);
static void vmbus_channel_on_gpadl_created(hv_vmbus_channel_msg_header* hdr);
static void vmbus_channel_on_gpadl_torndown(hv_vmbus_channel_msg_header* hdr);
static void vmbus_channel_on_offers_delivered(hv_vmbus_channel_msg_header* hdr);
@@ -49,41 +51,46 @@ static void vmbus_channel_on_version_response(hv_vmbus_channel_msg_header* hdr);
hv_vmbus_channel_msg_table_entry
g_channel_message_table[HV_CHANNEL_MESSAGE_COUNT] = {
{ HV_CHANNEL_MESSAGE_INVALID,
- 0, NULL },
+ NULL },
{ HV_CHANNEL_MESSAGE_OFFER_CHANNEL,
- 0, vmbus_channel_on_offer },
+ vmbus_channel_on_offer },
{ HV_CHANNEL_MESSAGE_RESCIND_CHANNEL_OFFER,
- 0, vmbus_channel_on_offer_rescind },
+ vmbus_channel_on_offer_rescind },
{ HV_CHANNEL_MESSAGE_REQUEST_OFFERS,
- 0, NULL },
+ NULL },
{ HV_CHANNEL_MESSAGE_ALL_OFFERS_DELIVERED,
- 1, vmbus_channel_on_offers_delivered },
+ vmbus_channel_on_offers_delivered },
{ HV_CHANNEL_MESSAGE_OPEN_CHANNEL,
- 0, NULL },
+ NULL },
{ HV_CHANNEL_MESSAGE_OPEN_CHANNEL_RESULT,
- 1, vmbus_channel_on_open_result },
+ vmbus_channel_on_open_result },
{ HV_CHANNEL_MESSAGE_CLOSE_CHANNEL,
- 0, NULL },
+ NULL },
{ HV_CHANNEL_MESSAGEL_GPADL_HEADER,
- 0, NULL },
+ NULL },
{ HV_CHANNEL_MESSAGE_GPADL_BODY,
- 0, NULL },
+ NULL },
{ HV_CHANNEL_MESSAGE_GPADL_CREATED,
- 1, vmbus_channel_on_gpadl_created },
+ vmbus_channel_on_gpadl_created },
{ HV_CHANNEL_MESSAGE_GPADL_TEARDOWN,
- 0, NULL },
+ NULL },
{ HV_CHANNEL_MESSAGE_GPADL_TORNDOWN,
- 1, vmbus_channel_on_gpadl_torndown },
+ vmbus_channel_on_gpadl_torndown },
{ HV_CHANNEL_MESSAGE_REL_ID_RELEASED,
- 0, NULL },
+ NULL },
{ HV_CHANNEL_MESSAGE_INITIATED_CONTACT,
- 0, NULL },
+ NULL },
{ HV_CHANNEL_MESSAGE_VERSION_RESPONSE,
- 1, vmbus_channel_on_version_response },
+ vmbus_channel_on_version_response },
{ HV_CHANNEL_MESSAGE_UNLOAD,
- 0, NULL }
+ NULL }
};
+typedef struct hv_work_item {
+ struct task work;
+ void (*callback)(void *);
+ void* context;
+} hv_work_item;
/**
* Implementation of the work abstraction.
@@ -93,120 +100,30 @@ work_item_callback(void *work, int pending)
{
struct hv_work_item *w = (struct hv_work_item *)work;
- /*
- * Serialize work execution.
- */
- if (w->wq->work_sema != NULL) {
- sema_wait(w->wq->work_sema);
- }
-
w->callback(w->context);
- if (w->wq->work_sema != NULL) {
- sema_post(w->wq->work_sema);
- }
-
free(w, M_DEVBUF);
}
-struct hv_work_queue*
-hv_work_queue_create(char* name)
-{
- static unsigned int qid = 0;
- char qname[64];
- int pri;
- struct hv_work_queue* wq;
-
- wq = malloc(sizeof(struct hv_work_queue), M_DEVBUF, M_NOWAIT | M_ZERO);
- KASSERT(wq != NULL, ("Error VMBUS: Failed to allocate work_queue\n"));
- if (wq == NULL)
- return (NULL);
-
- /*
- * We use work abstraction to handle messages
- * coming from the host and these are typically offers.
- * Some FreeBsd drivers appear to have a concurrency issue
- * where probe/attach needs to be serialized. We ensure that
- * by having only one thread process work elements in a
- * specific queue by serializing work execution.
- *
- */
- if (strcmp(name, "vmbusQ") == 0) {
- pri = PI_DISK;
- } else { /* control */
- pri = PI_NET;
- /*
- * Initialize semaphore for this queue by pointing
- * to the globale semaphore used for synchronizing all
- * control messages.
- */
- wq->work_sema = &hv_vmbus_g_connection.control_sema;
- }
-
- sprintf(qname, "hv_%s_%u", name, qid);
-
- /*
- * Fixme: FreeBSD 8.2 has a different prototype for
- * taskqueue_create(), and for certain other taskqueue functions.
- * We need to research the implications of these changes.
- * Fixme: Not sure when the changes were introduced.
- */
- wq->queue = taskqueue_create(qname, M_NOWAIT, taskqueue_thread_enqueue,
- &wq->queue
- #if __FreeBSD_version < 800000
- , &wq->proc
- #endif
- );
-
- if (wq->queue == NULL) {
- free(wq, M_DEVBUF);
- return (NULL);
- }
-
- if (taskqueue_start_threads(&wq->queue, 1, pri, "%s taskq", qname)) {
- taskqueue_free(wq->queue);
- free(wq, M_DEVBUF);
- return (NULL);
- }
-
- qid++;
-
- return (wq);
-}
-
-void
-hv_work_queue_close(struct hv_work_queue *wq)
-{
- /*
- * KYS: Need to drain the taskqueue
- * before we close the hv_work_queue.
- */
- /*KYS: taskqueue_drain(wq->tq, ); */
- taskqueue_free(wq->queue);
- free(wq, M_DEVBUF);
-}
-
/**
* @brief Create work item
*/
-int
+static int
hv_queue_work_item(
- struct hv_work_queue *wq,
void (*callback)(void *), void *context)
{
struct hv_work_item *w = malloc(sizeof(struct hv_work_item),
- M_DEVBUF, M_NOWAIT | M_ZERO);
+ M_DEVBUF, M_NOWAIT);
KASSERT(w != NULL, ("Error VMBUS: Failed to allocate WorkItem\n"));
if (w == NULL)
return (ENOMEM);
w->callback = callback;
w->context = context;
- w->wq = wq;
TASK_INIT(&w->work, 0, work_item_callback, w);
- return (taskqueue_enqueue(wq->queue, &w->work));
+ return (taskqueue_enqueue(taskqueue_thread, &w->work));
}
@@ -221,10 +138,7 @@ hv_vmbus_allocate_channel(void)
channel = (hv_vmbus_channel*) malloc(
sizeof(hv_vmbus_channel),
M_DEVBUF,
- M_NOWAIT | M_ZERO);
- KASSERT(channel != NULL, ("Error VMBUS: Failed to allocate channel!"));
- if (channel == NULL)
- return (NULL);
+ M_WAITOK | M_ZERO);
mtx_init(&channel->inbound_lock, "channel inbound", NULL, MTX_DEF);
mtx_init(&channel->sc_lock, "vmbus multi channel", NULL, MTX_DEF);
@@ -235,16 +149,6 @@ hv_vmbus_allocate_channel(void)
}
/**
- * @brief Release the vmbus channel object itself
- */
-static inline void
-ReleaseVmbusChannel(void *context)
-{
- hv_vmbus_channel* channel = (hv_vmbus_channel*) context;
- free(channel, M_DEVBUF);
-}
-
-/**
* @brief Release the resources used by the vmbus channel object
*/
void
@@ -252,13 +156,8 @@ hv_vmbus_free_vmbus_channel(hv_vmbus_channel* channel)
{
mtx_destroy(&channel->sc_lock);
mtx_destroy(&channel->inbound_lock);
- /*
- * We have to release the channel's workqueue/thread in
- * the vmbus's workqueue/thread context
- * ie we can't destroy ourselves
- */
- hv_queue_work_item(hv_vmbus_g_connection.work_queue,
- ReleaseVmbusChannel, (void *) channel);
+
+ free(channel, M_DEVBUF);
}
/**
@@ -456,7 +355,7 @@ static void
vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr)
{
hv_vmbus_channel_offer_channel* offer;
- hv_vmbus_channel* new_channel;
+ hv_vmbus_channel_offer_channel* copied;
offer = (hv_vmbus_channel_offer_channel*) hdr;
@@ -466,10 +365,25 @@ vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr)
guidType = &offer->offer.interface_type;
guidInstance = &offer->offer.interface_instance;
+ // copy offer data
+ copied = malloc(sizeof(*copied), M_DEVBUF, M_NOWAIT);
+ if (copied == NULL) {
+ printf("fail to allocate memory\n");
+ return;
+ }
+
+ memcpy(copied, hdr, sizeof(*copied));
+ hv_queue_work_item(vmbus_channel_on_offer_internal, copied);
+}
+
+static void
+vmbus_channel_on_offer_internal(void* context)
+{
+ hv_vmbus_channel* new_channel;
+
+ hv_vmbus_channel_offer_channel* offer = (hv_vmbus_channel_offer_channel*)context;
/* Allocate the channel object and save this offer */
new_channel = hv_vmbus_allocate_channel();
- if (new_channel == NULL)
- return;
/*
* By default we setup state to enable batched
@@ -509,6 +423,8 @@ vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr)
new_channel->monitor_bit = (uint8_t) offer->monitor_id % 32;
vmbus_channel_process_offer(new_channel);
+
+ free(offer, M_DEVBUF);
}
/**
@@ -526,13 +442,20 @@ vmbus_channel_on_offer_rescind(hv_vmbus_channel_msg_header* hdr)
rescind = (hv_vmbus_channel_rescind_offer*) hdr;
channel = hv_vmbus_g_connection.channels[rescind->child_rel_id];
- if (channel == NULL)
+ if (channel == NULL)
return;
- hv_vmbus_child_device_unregister(channel->device);
- mtx_lock(&hv_vmbus_g_connection.channel_lock);
+ hv_queue_work_item(vmbus_channel_on_offer_rescind_internal, channel);
hv_vmbus_g_connection.channels[rescind->child_rel_id] = NULL;
- mtx_unlock(&hv_vmbus_g_connection.channel_lock);
+}
+
+static void
+vmbus_channel_on_offer_rescind_internal(void *context)
+{
+ hv_vmbus_channel* channel;
+
+ channel = (hv_vmbus_channel*)context;
+ hv_vmbus_child_device_unregister(channel->device);
}
/**
@@ -709,35 +632,6 @@ vmbus_channel_on_version_response(hv_vmbus_channel_msg_header* hdr)
}
/**
- * @brief Handler for channel protocol messages.
- *
- * This is invoked in the vmbus worker thread context.
- */
-void
-hv_vmbus_on_channel_message(void *context)
-{
- hv_vmbus_message* msg;
- hv_vmbus_channel_msg_header* hdr;
- int size;
-
- msg = (hv_vmbus_message*) context;
- hdr = (hv_vmbus_channel_msg_header*) msg->u.payload;
- size = msg->header.payload_size;
-
- if (hdr->message_type >= HV_CHANNEL_MESSAGE_COUNT) {
- free(msg, M_DEVBUF);
- return;
- }
-
- if (g_channel_message_table[hdr->message_type].messageHandler) {
- g_channel_message_table[hdr->message_type].messageHandler(hdr);
- }
-
- /* Free the msg that was allocated in VmbusOnMsgDPC() */
- free(msg, M_DEVBUF);
-}
-
-/**
* @brief Send a request to get all our pending offers.
*/
int
@@ -762,8 +656,7 @@ hv_vmbus_request_channel_offers(void)
ret = hv_vmbus_post_message(msg, sizeof(hv_vmbus_channel_msg_header));
- if (msg_info)
- free(msg_info, M_DEVBUF);
+ free(msg_info, M_DEVBUF);
return (ret);
}
diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c
index 05b16120f303..e60c55709fc0 100644
--- a/sys/dev/hyperv/vmbus/hv_connection.c
+++ b/sys/dev/hyperv/vmbus/hv_connection.c
@@ -86,12 +86,10 @@ hv_vmbus_negotiate_version(hv_vmbus_channel_msg_info *msg_info,
hv_vmbus_g_connection.interrupt_page);
msg->monitor_page_1 = hv_get_phys_addr(
- hv_vmbus_g_connection.monitor_pages);
+ hv_vmbus_g_connection.monitor_page_1);
- msg->monitor_page_2 =
- hv_get_phys_addr(
- ((uint8_t *) hv_vmbus_g_connection.monitor_pages
- + PAGE_SIZE));
+ msg->monitor_page_2 = hv_get_phys_addr(
+ hv_vmbus_g_connection.monitor_page_2);
/**
* Add to list before we send the request since we may receive the
@@ -164,8 +162,6 @@ hv_vmbus_connect(void) {
* Initialize the vmbus connection
*/
hv_vmbus_g_connection.connect_state = HV_CONNECTING;
- hv_vmbus_g_connection.work_queue = hv_work_queue_create("vmbusQ");
- sema_init(&hv_vmbus_g_connection.control_sema, 1, "control_sema");
TAILQ_INIT(&hv_vmbus_g_connection.channel_msg_anchor);
mtx_init(&hv_vmbus_g_connection.channel_msg_lock, "vmbus channel msg",
@@ -179,18 +175,9 @@ hv_vmbus_connect(void) {
* Setup the vmbus event connection for channel interrupt abstraction
* stuff
*/
- hv_vmbus_g_connection.interrupt_page = contigmalloc(
+ hv_vmbus_g_connection.interrupt_page = malloc(
PAGE_SIZE, M_DEVBUF,
- M_NOWAIT | M_ZERO, 0UL,
- BUS_SPACE_MAXADDR,
- PAGE_SIZE, 0);
- KASSERT(hv_vmbus_g_connection.interrupt_page != NULL,
- ("Error VMBUS: malloc failed to allocate Channel"
- " Request Event message!"));
- if (hv_vmbus_g_connection.interrupt_page == NULL) {
- ret = ENOMEM;
- goto cleanup;
- }
+ M_WAITOK | M_ZERO);
hv_vmbus_g_connection.recv_interrupt_page =
hv_vmbus_g_connection.interrupt_page;
@@ -203,31 +190,19 @@ hv_vmbus_connect(void) {
* Set up the monitor notification facility. The 1st page for
* parent->child and the 2nd page for child->parent
*/
- hv_vmbus_g_connection.monitor_pages = contigmalloc(
- 2 * PAGE_SIZE,
+ hv_vmbus_g_connection.monitor_page_1 = malloc(
+ PAGE_SIZE,
M_DEVBUF,
- M_NOWAIT | M_ZERO,
- 0UL,
- BUS_SPACE_MAXADDR,
+ M_WAITOK | M_ZERO);
+ hv_vmbus_g_connection.monitor_page_2 = malloc(
PAGE_SIZE,
- 0);
- KASSERT(hv_vmbus_g_connection.monitor_pages != NULL,
- ("Error VMBUS: malloc failed to allocate Monitor Pages!"));
- if (hv_vmbus_g_connection.monitor_pages == NULL) {
- ret = ENOMEM;
- goto cleanup;
- }
+ M_DEVBUF,
+ M_WAITOK | M_ZERO);
msg_info = (hv_vmbus_channel_msg_info*)
malloc(sizeof(hv_vmbus_channel_msg_info) +
sizeof(hv_vmbus_channel_initiate_contact),
- M_DEVBUF, M_NOWAIT | M_ZERO);
- KASSERT(msg_info != NULL,
- ("Error VMBUS: malloc failed for Initiate Contact message!"));
- if (msg_info == NULL) {
- ret = ENOMEM;
- goto cleanup;
- }
+ M_DEVBUF, M_WAITOK | M_ZERO);
hv_vmbus_g_connection.channels = malloc(sizeof(hv_vmbus_channel*) *
HV_CHANNEL_MAX_COUNT,
@@ -269,8 +244,6 @@ hv_vmbus_connect(void) {
hv_vmbus_g_connection.connect_state = HV_DISCONNECTED;
- hv_work_queue_close(hv_vmbus_g_connection.work_queue);
- sema_destroy(&hv_vmbus_g_connection.control_sema);
mtx_destroy(&hv_vmbus_g_connection.channel_lock);
mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock);
@@ -282,13 +255,8 @@ hv_vmbus_connect(void) {
hv_vmbus_g_connection.interrupt_page = NULL;
}
- if (hv_vmbus_g_connection.monitor_pages != NULL) {
- contigfree(
- hv_vmbus_g_connection.monitor_pages,
- 2 * PAGE_SIZE,
- M_DEVBUF);
- hv_vmbus_g_connection.monitor_pages = NULL;
- }
+ free(hv_vmbus_g_connection.monitor_page_1, M_DEVBUF);
+ free(hv_vmbus_g_connection.monitor_page_2, M_DEVBUF);
if (msg_info) {
sema_destroy(&msg_info->wait_sema);
@@ -305,32 +273,19 @@ hv_vmbus_connect(void) {
int
hv_vmbus_disconnect(void) {
int ret = 0;
- hv_vmbus_channel_unload* msg;
-
- msg = malloc(sizeof(hv_vmbus_channel_unload),
- M_DEVBUF, M_NOWAIT | M_ZERO);
- KASSERT(msg != NULL,
- ("Error VMBUS: malloc failed to allocate Channel Unload Msg!"));
- if (msg == NULL)
- return (ENOMEM);
+ hv_vmbus_channel_unload msg;
- msg->message_type = HV_CHANNEL_MESSAGE_UNLOAD;
-
- ret = hv_vmbus_post_message(msg, sizeof(hv_vmbus_channel_unload));
+ msg.message_type = HV_CHANNEL_MESSAGE_UNLOAD;
+ ret = hv_vmbus_post_message(&msg, sizeof(hv_vmbus_channel_unload));
contigfree(hv_vmbus_g_connection.interrupt_page, PAGE_SIZE, M_DEVBUF);
mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock);
- hv_work_queue_close(hv_vmbus_g_connection.work_queue);
- sema_destroy(&hv_vmbus_g_connection.control_sema);
-
free(hv_vmbus_g_connection.channels, M_DEVBUF);
hv_vmbus_g_connection.connect_state = HV_DISCONNECTED;
- free(msg, M_DEVBUF);
-
return (ret);
}
diff --git a/sys/dev/hyperv/vmbus/hv_hv.c b/sys/dev/hyperv/vmbus/hv_hv.c
index ca5641f620bf..6afc2b8542bb 100644
--- a/sys/dev/hyperv/vmbus/hv_hv.c
+++ b/sys/dev/hyperv/vmbus/hv_hv.c
@@ -189,11 +189,7 @@ hv_vmbus_init(void)
* See if the hypercall page is already set
*/
hypercall_msr.as_uint64_t = rdmsr(HV_X64_MSR_HYPERCALL);
- virt_addr = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO);
- KASSERT(virt_addr != NULL,
- ("Error VMBUS: malloc failed to allocate page during init!"));
- if (virt_addr == NULL)
- goto cleanup;
+ virt_addr = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
hypercall_msr.u.enable = 1;
hypercall_msr.u.guest_physical_address =
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
index 7eac11679290..8a1e4126f13e 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
@@ -83,8 +83,6 @@ vmbus_msg_swintr(void *arg)
hv_vmbus_channel_msg_table_entry *entry;
hv_vmbus_channel_msg_type msg_type;
hv_vmbus_message* msg;
- hv_vmbus_message* copied;
- static bool warned = false;
cpu = (int)(long)arg;
KASSERT(cpu <= mp_maxid, ("VMBUS: vmbus_msg_swintr: "
@@ -100,31 +98,15 @@ vmbus_msg_swintr(void *arg)
hdr = (hv_vmbus_channel_msg_header *)msg->u.payload;
msg_type = hdr->message_type;
- if (msg_type >= HV_CHANNEL_MESSAGE_COUNT && !warned) {
- warned = true;
+ if (msg_type >= HV_CHANNEL_MESSAGE_COUNT) {
printf("VMBUS: unknown message type = %d\n", msg_type);
goto handled;
}
entry = &g_channel_message_table[msg_type];
- if (entry->handler_no_sleep)
+ if (entry->messageHandler)
entry->messageHandler(hdr);
- else {
-
- copied = malloc(sizeof(hv_vmbus_message),
- M_DEVBUF, M_NOWAIT);
- KASSERT(copied != NULL,
- ("Error VMBUS: malloc failed to allocate"
- " hv_vmbus_message!"));
- if (copied == NULL)
- continue;
-
- memcpy(copied, msg, sizeof(hv_vmbus_message));
- hv_queue_work_item(hv_vmbus_g_connection.work_queue,
- hv_vmbus_on_channel_message,
- copied);
- }
handled:
msg->header.message_type = HV_MESSAGE_TYPE_NONE;
@@ -309,12 +291,7 @@ hv_vmbus_child_device_create(
* Allocate the new child device
*/
child_dev = malloc(sizeof(hv_device), M_DEVBUF,
- M_NOWAIT | M_ZERO);
- KASSERT(child_dev != NULL,
- ("Error VMBUS: malloc failed to allocate hv_device!"));
-
- if (child_dev == NULL)
- return (NULL);
+ M_WAITOK | M_ZERO);
child_dev->channel = channel;
memcpy(&child_dev->class_id, &type, sizeof(hv_guid));
@@ -566,12 +543,7 @@ vmbus_bus_init(void)
*/
for(i = 0; i < 2; i++) {
setup_args.page_buffers[2 * j + i] =
- malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO);
- if (setup_args.page_buffers[2 * j + i] == NULL) {
- KASSERT(setup_args.page_buffers[2 * j + i] != NULL,
- ("Error VMBUS: malloc failed!"));
- goto cleanup1;
- }
+ malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
}
}
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
index 538ab1e7222e..5f6207217ecc 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
@@ -350,7 +350,8 @@ typedef struct {
* notification and 2nd is child->parent
* notification
*/
- void *monitor_pages;
+ void *monitor_page_1;
+ void *monitor_page_2;
TAILQ_HEAD(, hv_vmbus_channel_msg_info) channel_msg_anchor;
struct mtx channel_msg_lock;
/**
@@ -362,10 +363,8 @@ typedef struct {
/**
* channel table for fast lookup through id.
- */
+ */
hv_vmbus_channel **channels;
- hv_vmbus_handle work_queue;
- struct sema control_sema;
} hv_vmbus_connection;
typedef union {
@@ -632,7 +631,6 @@ typedef void (*vmbus_msg_handler)(hv_vmbus_channel_msg_header *msg);
typedef struct hv_vmbus_channel_msg_table_entry {
hv_vmbus_channel_msg_type messageType;
- bool handler_no_sleep; /* true: the handler doesn't sleep */
vmbus_msg_handler messageHandler;
} hv_vmbus_channel_msg_table_entry;
@@ -682,7 +680,6 @@ uint32_t hv_ring_buffer_read_end(
hv_vmbus_channel* hv_vmbus_allocate_channel(void);
void hv_vmbus_free_vmbus_channel(hv_vmbus_channel *channel);
-void hv_vmbus_on_channel_message(void *context);
int hv_vmbus_request_channel_offers(void);
void hv_vmbus_release_unattached_channels(void);
int hv_vmbus_init(void);
diff --git a/sys/dev/iicbus/iic.c b/sys/dev/iicbus/iic.c
index 84e1314a8d19..c6dd53d610b5 100644
--- a/sys/dev/iicbus/iic.c
+++ b/sys/dev/iicbus/iic.c
@@ -293,7 +293,8 @@ iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags)
struct iic_msg *buf, *m;
void **usrbufs;
device_t iicdev, parent;
- int error, i;
+ int error;
+ uint32_t i;
iicdev = priv->sc->sc_dev;
parent = device_get_parent(iicdev);
diff --git a/sys/dev/iscsi_initiator/isc_cam.c b/sys/dev/iscsi_initiator/isc_cam.c
index 6089694364c6..e53a0fb66ced 100644
--- a/sys/dev/iscsi_initiator/isc_cam.c
+++ b/sys/dev/iscsi_initiator/isc_cam.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/uio.h>
#include <sys/sysctl.h>
#include <sys/sx.h>
+#include <vm/uma.h>
#include <cam/cam.h>
#include <cam/cam_ccb.h>
diff --git a/sys/dev/iscsi_initiator/isc_sm.c b/sys/dev/iscsi_initiator/isc_sm.c
index 6810047b77ac..097cdcca2153 100644
--- a/sys/dev/iscsi_initiator/isc_sm.c
+++ b/sys/dev/iscsi_initiator/isc_sm.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/sbuf.h>
#include <sys/sx.h>
+#include <vm/uma.h>
#include <cam/cam.h>
#include <cam/cam_ccb.h>
diff --git a/sys/dev/iscsi_initiator/isc_soc.c b/sys/dev/iscsi_initiator/isc_soc.c
index e77f0700c69e..adb9914c00f7 100644
--- a/sys/dev/iscsi_initiator/isc_soc.c
+++ b/sys/dev/iscsi_initiator/isc_soc.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <sys/syslog.h>
#include <sys/mbuf.h>
#include <sys/user.h>
+#include <vm/uma.h>
#include <cam/cam.h>
#include <cam/cam_ccb.h>
diff --git a/sys/dev/iscsi_initiator/isc_subr.c b/sys/dev/iscsi_initiator/isc_subr.c
index 677c5f1674c8..d553cd1c3326 100644
--- a/sys/dev/iscsi_initiator/isc_subr.c
+++ b/sys/dev/iscsi_initiator/isc_subr.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/syslog.h>
#include <sys/mbuf.h>
#include <sys/libkern.h>
+#include <vm/uma.h>
#include <dev/iscsi_initiator/iscsi.h>
#include <dev/iscsi_initiator/iscsivar.h>
diff --git a/sys/dev/iscsi_initiator/iscsi_subr.c b/sys/dev/iscsi_initiator/iscsi_subr.c
index b22ed831207b..cf746cda65f7 100644
--- a/sys/dev/iscsi_initiator/iscsi_subr.c
+++ b/sys/dev/iscsi_initiator/iscsi_subr.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/uio.h>
#include <sys/sysctl.h>
#include <sys/sx.h>
+#include <vm/uma.h>
#include <cam/cam.h>
#include <cam/cam_ccb.h>
diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c
index 168fa1310f74..f0e218fab1ed 100644
--- a/sys/dev/ixgbe/if_ix.c
+++ b/sys/dev/ixgbe/if_ix.c
@@ -592,6 +592,12 @@ ixgbe_attach(device_t dev)
if (error)
goto err_late;
+ /* Enable the optics for 82599 SFP+ fiber */
+ ixgbe_enable_tx_laser(hw);
+
+ /* Enable power to the phy. */
+ ixgbe_set_phy_power(hw, TRUE);
+
/* Setup OS specific network interface */
if (ixgbe_setup_interface(dev, adapter) != 0)
goto err_late;
@@ -1011,6 +1017,7 @@ static void
ixgbe_set_if_hwassist(struct adapter *adapter)
{
struct ifnet *ifp = adapter->ifp;
+ struct ixgbe_hw *hw = &adapter->hw;
ifp->if_hwassist = 0;
#if __FreeBSD_version >= 1000000
@@ -1018,18 +1025,21 @@ ixgbe_set_if_hwassist(struct adapter *adapter)
ifp->if_hwassist |= CSUM_IP_TSO;
if (ifp->if_capenable & IFCAP_TSO6)
ifp->if_hwassist |= CSUM_IP6_TSO;
- if (ifp->if_capenable & IFCAP_TXCSUM)
- ifp->if_hwassist |= (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP |
- CSUM_IP_SCTP);
- if (ifp->if_capenable & IFCAP_TXCSUM_IPV6)
- ifp->if_hwassist |= (CSUM_IP6_UDP | CSUM_IP6_TCP |
- CSUM_IP6_SCTP);
+ if (ifp->if_capenable & IFCAP_TXCSUM) {
+ ifp->if_hwassist |= (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP);
+ if (hw->mac.type != ixgbe_mac_82598EB)
+ ifp->if_hwassist |= CSUM_IP_SCTP;
+ }
+ if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) {
+ ifp->if_hwassist |= (CSUM_IP6_UDP | CSUM_IP6_TCP);
+ if (hw->mac.type != ixgbe_mac_82598EB)
+ ifp->if_hwassist |= CSUM_IP6_SCTP;
+ }
#else
if (ifp->if_capenable & IFCAP_TSO)
ifp->if_hwassist |= CSUM_TSO;
if (ifp->if_capenable & IFCAP_TXCSUM) {
ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
- struct ixgbe_hw *hw = &adapter->hw;
if (hw->mac.type != ixgbe_mac_82598EB)
ifp->if_hwassist |= CSUM_SCTP;
}
@@ -1260,6 +1270,9 @@ ixgbe_init_locked(struct adapter *adapter)
device_printf(dev, "Error setting up EEE: %d\n", err);
}
+ /* Enable power to the phy. */
+ ixgbe_set_phy_power(hw, TRUE);
+
/* Config/Enable Link */
ixgbe_config_link(adapter);
@@ -3980,6 +3993,9 @@ ixgbe_setup_low_power_mode(struct adapter *adapter)
mtx_assert(&adapter->core_mtx, MA_OWNED);
+ if (!hw->wol_enabled)
+ ixgbe_set_phy_power(hw, FALSE);
+
/* Limit power management flow to X550EM baseT */
if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T
&& hw->phy.ops.enter_lplu) {
diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c
index d67e6802b184..feb74f6f8b34 100644
--- a/sys/dev/ixgbe/ixgbe_common.c
+++ b/sys/dev/ixgbe/ixgbe_common.c
@@ -199,9 +199,12 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
break;
}
- ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED,
+ if (!supported) {
+ ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED,
"Device %x does not support flow control autoneg",
hw->device_id);
+ }
+
return supported;
}
diff --git a/sys/dev/ixgbe/ixgbe_phy.c b/sys/dev/ixgbe/ixgbe_phy.c
index 6bff17291f1f..f5d22b252e3c 100644
--- a/sys/dev/ixgbe/ixgbe_phy.c
+++ b/sys/dev/ixgbe/ixgbe_phy.c
@@ -2734,6 +2734,9 @@ s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on)
u32 status;
u16 reg;
+ if (!on && ixgbe_mng_present(hw))
+ return 0;
+
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL,
IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
&reg);
diff --git a/sys/dev/ixgbe/ixgbe_type.h b/sys/dev/ixgbe/ixgbe_type.h
index d76cde26cddf..da03f79e5fc1 100644
--- a/sys/dev/ixgbe/ixgbe_type.h
+++ b/sys/dev/ixgbe/ixgbe_type.h
@@ -1479,7 +1479,10 @@ struct ixgbe_dmac_config {
#define IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK 0xFF01 /* int chip-wide mask */
#define IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG 0xFC01 /* int chip-wide mask */
#define IXGBE_MDIO_GLOBAL_ALARM_1 0xCC00 /* Global alarm 1 */
+#define IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT 0x0010 /* device fault */
#define IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL 0x4000 /* high temp failure */
+#define IXGBE_MDIO_GLOBAL_FAULT_MSG 0xC850 /* Global Fault Message */
+#define IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP 0x8007 /* high temp failure */
#define IXGBE_MDIO_GLOBAL_INT_MASK 0xD400 /* Global int mask */
#define IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN 0x1000 /* autoneg vendor alarm int enable */
#define IXGBE_MDIO_GLOBAL_ALARM_1_INT 0x4 /* int in Global alarm 1 */
diff --git a/sys/dev/ixgbe/ixgbe_x540.c b/sys/dev/ixgbe/ixgbe_x540.c
index 96478eaf6a7b..fd52ebeb8c52 100644
--- a/sys/dev/ixgbe/ixgbe_x540.c
+++ b/sys/dev/ixgbe/ixgbe_x540.c
@@ -82,8 +82,7 @@ s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw)
/* PHY */
phy->ops.init = ixgbe_init_phy_ops_generic;
phy->ops.reset = NULL;
- if (!ixgbe_mng_present(hw))
- phy->ops.set_phy_power = ixgbe_set_copper_phy_power;
+ phy->ops.set_phy_power = ixgbe_set_copper_phy_power;
/* MAC */
mac->ops.reset_hw = ixgbe_reset_hw_X540;
diff --git a/sys/dev/ixgbe/ixgbe_x550.c b/sys/dev/ixgbe/ixgbe_x550.c
index d62035d44f9f..1199d38f9158 100644
--- a/sys/dev/ixgbe/ixgbe_x550.c
+++ b/sys/dev/ixgbe/ixgbe_x550.c
@@ -965,7 +965,7 @@ void ixgbe_restore_mdd_vf_X550(struct ixgbe_hw *hw, u32 vf)
num_qs = 4; /* 32 VFs / pools */
bitmask = 0x0000000F;
break;
- default: /* 64 VFs / pools */
+ default: /* 64 VFs / pools */
num_qs = 2;
bitmask = 0x00000003;
break;
@@ -1264,7 +1264,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
IXGBE_MDIO_GLOBAL_ALARM_1_INT)))
return status;
- /* High temperature failure alarm triggered */
+ /* Global alarm triggered */
status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1,
IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
&reg);
@@ -1277,6 +1277,21 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
/* power down the PHY in case the PHY FW didn't already */
ixgbe_set_copper_phy_power(hw, FALSE);
return IXGBE_ERR_OVERTEMP;
+ } else if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
+ /* device fault alarm triggered */
+ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG,
+ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ &reg);
+
+ if (status != IXGBE_SUCCESS)
+ return status;
+
+ /* if device fault was due to high temp alarm handle and exit */
+ if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) {
+ /* power down the PHY in case the PHY FW didn't */
+ ixgbe_set_copper_phy_power(hw, FALSE);
+ return IXGBE_ERR_OVERTEMP;
+ }
}
/* Vendor alarm 2 triggered */
diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c
index 505d4b4cbb12..d5ab42fb6025 100644
--- a/sys/dev/ixl/if_ixl.c
+++ b/sys/dev/ixl/if_ixl.c
@@ -674,9 +674,9 @@ ixl_attach(device_t dev)
}
/* Limit phy interrupts to link and modules failure */
- error = i40e_aq_set_phy_int_mask(hw,
- I40E_AQ_EVENT_LINK_UPDOWN | I40E_AQ_EVENT_MODULE_QUAL_FAIL, NULL);
- if (error)
+ error = i40e_aq_set_phy_int_mask(hw, ~(I40E_AQ_EVENT_LINK_UPDOWN |
+ I40E_AQ_EVENT_MODULE_QUAL_FAIL), NULL);
+ if (error)
device_printf(dev, "set phy mask failed: %d\n", error);
/* Get the bus configuration and set the shared code */
diff --git a/sys/dev/le/lance.c b/sys/dev/le/lance.c
index 2b4202be2cdd..f8a333b9fd5c 100644
--- a/sys/dev/le/lance.c
+++ b/sys/dev/le/lance.c
@@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/lock.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/socket.h>
diff --git a/sys/dev/malo/if_malo.c b/sys/dev/malo/if_malo.c
index ff487082e708..6cd0f2969472 100644
--- a/sys/dev/malo/if_malo.c
+++ b/sys/dev/malo/if_malo.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/endian.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c
index 2fa9f460edd9..222bc403e67d 100644
--- a/sys/dev/md/md.c
+++ b/sys/dev/md/md.c
@@ -130,18 +130,12 @@ SYSCTL_INT(_vm, OID_AUTO, md_malloc_wait, CTLFLAG_RW, &md_malloc_wait, 0,
*/
#if defined(MD_ROOT_SIZE)
/*
+ * We put the mfs_root symbol into the oldmfs section of the kernel object file.
* Applications that patch the object with the image can determine
- * the size looking at the start and end markers (strings),
- * so we want them contiguous.
+ * the size looking at the oldmfs section size within the kernel.
*/
-static struct {
- u_char start[MD_ROOT_SIZE*1024];
- u_char end[128];
-} mfs_root = {
- .start = "MFS Filesystem goes here",
- .end = "MFS Filesystem had better STOP here",
-};
-const int mfs_root_size = sizeof(mfs_root.start);
+u_char mfs_root[MD_ROOT_SIZE*1024] __attribute__ ((section ("oldmfs")));
+const int mfs_root_size = sizeof(mfs_root);
#else
extern volatile u_char __weak_symbol mfs_root;
extern volatile u_char __weak_symbol mfs_root_end;
diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c
index 4080fc678fc1..5f183416e5ea 100644
--- a/sys/dev/mps/mps.c
+++ b/sys/dev/mps/mps.c
@@ -1476,6 +1476,14 @@ mps_setup_sysctl(struct mps_softc *sc)
OID_AUTO, "spinup_wait_time", CTLFLAG_RD,
&sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for "
"spinup after SATA ID error");
+
+ SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "mapping_table_dump", CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ mps_mapping_dump, "A", "Mapping Table Dump");
+
+ SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "encl_table_dump", CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ mps_mapping_encl_dump, "A", "Enclosure Table Dump");
}
int
diff --git a/sys/dev/mps/mps_mapping.c b/sys/dev/mps/mps_mapping.c
index d0819efc26e9..351625be4817 100644
--- a/sys/dev/mps/mps_mapping.c
+++ b/sys/dev/mps/mps_mapping.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/sysctl.h>
+#include <sys/sbuf.h>
#include <sys/eventhandler.h>
#include <sys/uio.h>
#include <machine/bus.h>
@@ -890,7 +891,7 @@ _mapping_get_dev_info(struct mps_softc *sc,
u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
Mpi2ConfigReply_t mpi_reply;
Mpi2SasDevicePage0_t sas_device_pg0;
- u8 entry, enc_idx, phy_idx, sata_end_device;
+ u8 entry, enc_idx, phy_idx;
u32 map_idx, index, device_info;
struct _map_phy_change *phy_change, *tmp_phy_change;
uint64_t sas_address;
@@ -920,10 +921,8 @@ _mapping_get_dev_info(struct mps_softc *sc,
sas_address = sas_device_pg0.SASAddress.High;
sas_address = (sas_address << 32) |
sas_device_pg0.SASAddress.Low;
- sata_end_device = 0;
if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
(device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) {
- sata_end_device = 1;
rc = mpssas_get_sas_address_for_sata_disk(sc,
&sas_address, phy_change->dev_handle, device_info,
&phy_change->is_SATA_SSD);
@@ -2265,3 +2264,61 @@ out:
if (sc->pending_map_events)
sc->pending_map_events--;
}
+
+int
+mps_mapping_dump(SYSCTL_HANDLER_ARGS)
+{
+ struct mps_softc *sc;
+ struct dev_mapping_table *mt_entry;
+ struct sbuf sbuf;
+ int i, error;
+
+ sc = (struct mps_softc *)arg1;
+
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0)
+ return (error);
+ sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
+
+ sbuf_printf(&sbuf, "\nindex physical_id handle id\n");
+ for (i = 0; i < sc->max_devices; i++) {
+ mt_entry = &sc->mapping_table[i];
+ if (mt_entry->physical_id == 0)
+ continue;
+ sbuf_printf(&sbuf, "%4d %jx %04x %hd\n",
+ i, mt_entry->physical_id, mt_entry->dev_handle,
+ mt_entry->id);
+ }
+ error = sbuf_finish(&sbuf);
+ sbuf_delete(&sbuf);
+ return (error);
+}
+
+int
+mps_mapping_encl_dump(SYSCTL_HANDLER_ARGS)
+{
+ struct mps_softc *sc;
+ struct enc_mapping_table *enc_entry;
+ struct sbuf sbuf;
+ int i, error;
+
+ sc = (struct mps_softc *)arg1;
+
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0)
+ return (error);
+ sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
+
+ sbuf_printf(&sbuf, "\nindex enclosure_id handle map_index\n");
+ for (i = 0; i < sc->max_enclosures; i++) {
+ enc_entry = &sc->enclosure_table[i];
+ if (enc_entry->enclosure_id == 0)
+ continue;
+ sbuf_printf(&sbuf, "%4d %jx %04x %d\n",
+ i, enc_entry->enclosure_id, enc_entry->enc_handle,
+ enc_entry->start_index);
+ }
+ error = sbuf_finish(&sbuf);
+ sbuf_delete(&sbuf);
+ return (error);
+}
diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c
index 4fbdbb2d20c0..8cba1d72286c 100644
--- a/sys/dev/mps/mps_sas.c
+++ b/sys/dev/mps/mps_sas.c
@@ -2797,11 +2797,9 @@ mpssas_send_smpcmd(struct mpssas_softc *sassc, union ccb *ccb, uint64_t sasaddr)
uint8_t *request, *response;
MPI2_SMP_PASSTHROUGH_REQUEST *req;
struct mps_softc *sc;
- struct sglist *sg;
int error;
sc = sassc->sc;
- sg = NULL;
error = 0;
/*
diff --git a/sys/dev/mps/mpsvar.h b/sys/dev/mps/mpsvar.h
index 96bb4e1cfa64..0cb51a0a3b19 100644
--- a/sys/dev/mps/mpsvar.h
+++ b/sys/dev/mps/mpsvar.h
@@ -756,6 +756,8 @@ void mps_mapping_enclosure_dev_status_change_event(struct mps_softc *,
Mpi2EventDataSasEnclDevStatusChange_t *event_data);
void mps_mapping_ir_config_change_event(struct mps_softc *sc,
Mpi2EventDataIrConfigChangeList_t *event_data);
+int mps_mapping_dump(SYSCTL_HANDLER_ARGS);
+int mps_mapping_encl_dump(SYSCTL_HANDLER_ARGS);
void mpssas_evt_handler(struct mps_softc *sc, uintptr_t data,
MPI2_EVENT_NOTIFICATION_REPLY *event);
diff --git a/sys/dev/netmap/netmap_offloadings.c b/sys/dev/netmap/netmap_offloadings.c
index 34eafab7c87e..4055c427cb56 100644
--- a/sys/dev/netmap/netmap_offloadings.c
+++ b/sys/dev/netmap/netmap_offloadings.c
@@ -31,6 +31,7 @@
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/param.h> /* defines used in kernel.h */
+#include <sys/malloc.h> /* types used in module initialization */
#include <sys/kernel.h> /* types used in module initialization */
#include <sys/sockio.h>
#include <sys/socketvar.h> /* struct socket */
diff --git a/sys/dev/nvd/nvd.c b/sys/dev/nvd/nvd.c
index 24ee07583034..e062f57973d4 100644
--- a/sys/dev/nvd/nvd.c
+++ b/sys/dev/nvd/nvd.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (C) 2012-2013 Intel Corporation
+ * Copyright (C) 2012-2016 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/taskqueue.h>
@@ -88,6 +89,19 @@ struct nvd_controller {
static TAILQ_HEAD(, nvd_controller) ctrlr_head;
static TAILQ_HEAD(disk_list, nvd_disk) disk_head;
+static SYSCTL_NODE(_hw, OID_AUTO, nvd, CTLFLAG_RD, 0, "nvd driver parameters");
+/*
+ * The NVMe specification does not define a maximum or optimal delete size, so
+ * technically max delete size is min(full size of the namespace, 2^32 - 1
+ * LBAs). A single delete for a multi-TB NVMe namespace though may take much
+ * longer to complete than the nvme(4) I/O timeout period. So choose a sensible
+ * default here that is still suitably large to minimize the number of overall
+ * delete operations.
+ */
+static uint64_t nvd_delete_max = (1024 * 1024 * 1024); /* 1GB */
+SYSCTL_UQUAD(_hw_nvd, OID_AUTO, delete_max, CTLFLAG_RDTUN, &nvd_delete_max, 0,
+ "nvd maximum BIO_DELETE size in bytes");
+
static int nvd_modevent(module_t mod, int type, void *arg)
{
int error = 0;
@@ -295,6 +309,8 @@ nvd_new_disk(struct nvme_namespace *ns, void *ctrlr_arg)
disk->d_sectorsize = nvme_ns_get_sector_size(ns);
disk->d_mediasize = (off_t)nvme_ns_get_size(ns);
disk->d_delmaxsize = (off_t)nvme_ns_get_size(ns);
+ if (disk->d_delmaxsize > nvd_delete_max)
+ disk->d_delmaxsize = nvd_delete_max;
disk->d_stripesize = nvme_ns_get_optimal_sector_size(ns);
if (TAILQ_EMPTY(&disk_head))
diff --git a/sys/dev/nvme/nvme.h b/sys/dev/nvme/nvme.h
index 227a89ef0daf..19a63e8d5d7d 100644
--- a/sys/dev/nvme/nvme.h
+++ b/sys/dev/nvme/nvme.h
@@ -392,6 +392,34 @@ enum nvme_activate_action {
NVME_AA_ACTIVATE = 0x2,
};
+struct nvme_power_state {
+ /** Maximum Power */
+ uint16_t mp; /* Maximum Power */
+ uint8_t ps_rsvd1;
+ uint8_t mps : 1; /* Max Power Scale */
+ uint8_t nops : 1; /* Non-Operational State */
+ uint8_t ps_rsvd2 : 6;
+ uint32_t enlat; /* Entry Latency */
+ uint32_t exlat; /* Exit Latency */
+ uint8_t rrt : 5; /* Relative Read Throughput */
+ uint8_t ps_rsvd3 : 3;
+ uint8_t rrl : 5; /* Relative Read Latency */
+ uint8_t ps_rsvd4 : 3;
+ uint8_t rwt : 5; /* Relative Write Throughput */
+ uint8_t ps_rsvd5 : 3;
+ uint8_t rwl : 5; /* Relative Write Latency */
+ uint8_t ps_rsvd6 : 3;
+ uint16_t idlp; /* Idle Power */
+ uint8_t ps_rsvd7 : 6;
+ uint8_t ips : 2; /* Idle Power Scale */
+ uint8_t ps_rsvd8;
+ uint16_t actp; /* Active Power */
+ uint8_t apw : 3; /* Active Power Workload */
+ uint8_t ps_rsvd9 : 3;
+ uint8_t aps : 2; /* Active Power Scale */
+ uint8_t ps_rsvd10[9];
+} __packed;
+
#define NVME_SERIAL_NUMBER_LENGTH 20
#define NVME_MODEL_NUMBER_LENGTH 40
#define NVME_FIRMWARE_REVISION_LENGTH 8
@@ -532,7 +560,7 @@ struct nvme_controller_data {
uint8_t reserved5[1344];
/* bytes 2048-3071: power state descriptors */
- uint8_t reserved6[1024];
+ struct nvme_power_state power_state[32];
/* bytes 3072-4095: vendor specific */
uint8_t vs[1024];
diff --git a/sys/dev/oce/oce_if.h b/sys/dev/oce/oce_if.h
index bb788413faa0..99707e496783 100644
--- a/sys/dev/oce/oce_if.h
+++ b/sys/dev/oce/oce_if.h
@@ -41,6 +41,7 @@
#include <sys/param.h>
#include <sys/endian.h>
#include <sys/eventhandler.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/bus.h>
diff --git a/sys/dev/otus/if_otus.c b/sys/dev/otus/if_otus.c
index daa96266353a..03bfa73d1f52 100644
--- a/sys/dev/otus/if_otus.c
+++ b/sys/dev/otus/if_otus.c
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/conf.h>
diff --git a/sys/dev/sfxge/sfxge.h b/sys/dev/sfxge/sfxge.h
index 9ff84c03a0b7..8c1d63657b7e 100644
--- a/sys/dev/sfxge/sfxge.h
+++ b/sys/dev/sfxge/sfxge.h
@@ -273,7 +273,7 @@ struct sfxge_softc {
size_t rx_prefix_size;
size_t rx_buffer_size;
size_t rx_buffer_align;
- uma_zone_t rx_buffer_zone;
+ int rx_cluster_size;
unsigned int evq_max;
unsigned int evq_count;
diff --git a/sys/dev/sfxge/sfxge_rx.c b/sys/dev/sfxge/sfxge_rx.c
index 3782c3496674..d4e4fd431c1b 100644
--- a/sys/dev/sfxge/sfxge_rx.c
+++ b/sys/dev/sfxge/sfxge_rx.c
@@ -34,7 +34,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/smp.h>
#include <sys/socket.h>
@@ -205,25 +206,6 @@ sfxge_rx_schedule_refill(struct sfxge_rxq *rxq, boolean_t retrying)
sfxge_rx_post_refill, rxq);
}
-static struct mbuf *sfxge_rx_alloc_mbuf(struct sfxge_softc *sc)
-{
- struct mb_args args;
- struct mbuf *m;
-
- /* Allocate mbuf structure */
- args.flags = M_PKTHDR;
- args.type = MT_DATA;
- m = (struct mbuf *)uma_zalloc_arg(zone_mbuf, &args, M_NOWAIT);
-
- /* Allocate (and attach) packet buffer */
- if (m != NULL && !uma_zalloc_arg(sc->rx_buffer_zone, m, M_NOWAIT)) {
- uma_zfree(zone_mbuf, m);
- m = NULL;
- }
-
- return (m);
-}
-
#define SFXGE_REFILL_BATCH 64
static void
@@ -273,7 +255,8 @@ sfxge_rx_qfill(struct sfxge_rxq *rxq, unsigned int target, boolean_t retrying)
KASSERT(rx_desc->mbuf == NULL, ("rx_desc->mbuf != NULL"));
rx_desc->flags = EFX_DISCARD;
- m = rx_desc->mbuf = sfxge_rx_alloc_mbuf(sc);
+ m = rx_desc->mbuf = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR,
+ sc->rx_cluster_size);
if (m == NULL)
break;
@@ -1125,13 +1108,13 @@ sfxge_rx_start(struct sfxge_softc *sc)
/* Select zone for packet buffers */
if (reserved <= MCLBYTES)
- sc->rx_buffer_zone = zone_clust;
+ sc->rx_cluster_size = MCLBYTES;
else if (reserved <= MJUMPAGESIZE)
- sc->rx_buffer_zone = zone_jumbop;
+ sc->rx_cluster_size = MJUMPAGESIZE;
else if (reserved <= MJUM9BYTES)
- sc->rx_buffer_zone = zone_jumbo9;
+ sc->rx_cluster_size = MJUM9BYTES;
else
- sc->rx_buffer_zone = zone_jumbo16;
+ sc->rx_cluster_size = MJUM16BYTES;
/*
* Set up the scale table. Enable all hash types and hash insertion.
diff --git a/sys/dev/sfxge/sfxge_tx.c b/sys/dev/sfxge/sfxge_tx.c
index 9cf5c79a8213..e729360c6b63 100644
--- a/sys/dev/sfxge/sfxge_tx.c
+++ b/sys/dev/sfxge/sfxge_tx.c
@@ -49,7 +49,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/smp.h>
#include <sys/socket.h>
diff --git a/sys/dev/sn/if_sn.c b/sys/dev/sn/if_sn.c
index 26e60bc0445a..c1fbc9ad8ac7 100644
--- a/sys/dev/sn/if_sn.c
+++ b/sys/dev/sn/if_sn.c
@@ -84,6 +84,7 @@ __FBSDID("$FreeBSD$");
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/sockio.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/syslog.h>
diff --git a/sys/dev/tx/if_tx.c b/sys/dev/tx/if_tx.c
index 7a12aee288d1..42b327fbdf26 100644
--- a/sys/dev/tx/if_tx.c
+++ b/sys/dev/tx/if_tx.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/queue.h>
diff --git a/sys/dev/usb/controller/ehci.c b/sys/dev/usb/controller/ehci.c
index 0f9372585d1c..eb4ccb9b5ca2 100644
--- a/sys/dev/usb/controller/ehci.c
+++ b/sys/dev/usb/controller/ehci.c
@@ -189,24 +189,8 @@ ehci_reset(ehci_softc_t *sc)
usb_pause_mtx(NULL, hz / 128);
hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET;
if (!hcr) {
- if (sc->sc_flags & (EHCI_SCFLG_SETMODE | EHCI_SCFLG_BIGEMMIO)) {
- /*
- * Force USBMODE as requested. Controllers
- * may have multiple operating modes.
- */
- uint32_t usbmode = EOREAD4(sc, EHCI_USBMODE);
- if (sc->sc_flags & EHCI_SCFLG_SETMODE) {
- usbmode = (usbmode &~ EHCI_UM_CM) | EHCI_UM_CM_HOST;
- device_printf(sc->sc_bus.bdev,
- "set host controller mode\n");
- }
- if (sc->sc_flags & EHCI_SCFLG_BIGEMMIO) {
- usbmode = (usbmode &~ EHCI_UM_ES) | EHCI_UM_ES_BE;
- device_printf(sc->sc_bus.bdev,
- "set big-endian mode\n");
- }
- EOWRITE4(sc, EHCI_USBMODE, usbmode);
- }
+ if (sc->sc_vendor_post_reset != NULL)
+ sc->sc_vendor_post_reset(sc);
return (0);
}
}
@@ -3066,6 +3050,36 @@ struct usb_hub_descriptor ehci_hubd =
.bDescriptorType = UDESC_HUB,
};
+uint16_t
+ehci_get_port_speed_portsc(struct ehci_softc *sc, uint16_t index)
+{
+ uint32_t v;
+
+ v = EOREAD4(sc, EHCI_PORTSC(index));
+ v = (v >> EHCI_PORTSC_PSPD_SHIFT) & EHCI_PORTSC_PSPD_MASK;
+
+ if (v == EHCI_PORT_SPEED_HIGH)
+ return (UPS_HIGH_SPEED);
+ if (v == EHCI_PORT_SPEED_LOW)
+ return (UPS_LOW_SPEED);
+ return (0);
+}
+
+uint16_t
+ehci_get_port_speed_hostc(struct ehci_softc *sc, uint16_t index)
+{
+ uint32_t v;
+
+ v = EOREAD4(sc, EHCI_HOSTC(index));
+ v = (v >> EHCI_HOSTC_PSPD_SHIFT) & EHCI_HOSTC_PSPD_MASK;
+
+ if (v == EHCI_PORT_SPEED_HIGH)
+ return (UPS_HIGH_SPEED);
+ if (v == EHCI_PORT_SPEED_LOW)
+ return (UPS_LOW_SPEED);
+ return (0);
+}
+
static void
ehci_disown(ehci_softc_t *sc, uint16_t index, uint8_t lowspeed)
{
@@ -3330,13 +3344,15 @@ ehci_roothub_exec(struct usb_device *udev,
}
v = EOREAD4(sc, EHCI_PORTSC(index));
DPRINTFN(9, "port status=0x%04x\n", v);
- if (sc->sc_flags & (EHCI_SCFLG_FORCESPEED | EHCI_SCFLG_TT)) {
- if ((v & 0xc000000) == 0x8000000)
+ if (sc->sc_flags & EHCI_SCFLG_TT) {
+ if (sc->sc_vendor_get_port_speed != NULL) {
+ i = sc->sc_vendor_get_port_speed(sc, index);
+ } else {
+ device_printf(sc->sc_bus.bdev,
+ "EHCI_SCFLG_TT quirk is set but "
+ "sc_vendor_get_hub_speed() is NULL\n");
i = UPS_HIGH_SPEED;
- else if ((v & 0xc000000) == 0x4000000)
- i = UPS_LOW_SPEED;
- else
- i = 0;
+ }
} else {
i = UPS_HIGH_SPEED;
}
diff --git a/sys/dev/usb/controller/ehci.h b/sys/dev/usb/controller/ehci.h
index 808ff9f51bf9..0d1e19a39e52 100644
--- a/sys/dev/usb/controller/ehci.h
+++ b/sys/dev/usb/controller/ehci.h
@@ -337,11 +337,8 @@ typedef struct ehci_softc {
uint16_t sc_intr_stat[EHCI_VIRTUAL_FRAMELIST_COUNT];
uint16_t sc_id_vendor; /* vendor ID for root hub */
uint16_t sc_flags; /* chip specific flags */
-#define EHCI_SCFLG_SETMODE 0x0001 /* set bridge mode again after init */
-#define EHCI_SCFLG_FORCESPEED 0x0002 /* force speed */
#define EHCI_SCFLG_NORESTERM 0x0004 /* don't terminate reset sequence */
#define EHCI_SCFLG_BIGEDESC 0x0008 /* big-endian byte order descriptors */
-#define EHCI_SCFLG_BIGEMMIO 0x0010 /* big-endian byte order MMIO */
#define EHCI_SCFLG_TT 0x0020 /* transaction translator present */
#define EHCI_SCFLG_LOSTINTRBUG 0x0040 /* workaround for VIA / ATI chipsets */
#define EHCI_SCFLG_IAADBUG 0x0080 /* workaround for nVidia chipsets */
@@ -358,6 +355,10 @@ typedef struct ehci_softc {
char sc_vendor[16]; /* vendor string for root hub */
+ void (*sc_vendor_post_reset)(struct ehci_softc *sc);
+ uint16_t (*sc_vendor_get_port_speed)(struct ehci_softc *sc,
+ uint16_t index);
+
} ehci_softc_t;
#define EREAD1(sc, a) bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (a))
@@ -446,5 +447,7 @@ usb_error_t ehci_reset(ehci_softc_t *sc);
usb_error_t ehci_init(ehci_softc_t *sc);
void ehci_detach(struct ehci_softc *sc);
void ehci_interrupt(ehci_softc_t *sc);
+uint16_t ehci_get_port_speed_portsc(struct ehci_softc *sc, uint16_t index);
+uint16_t ehci_get_port_speed_hostc(struct ehci_softc *sc, uint16_t index);
#endif /* _EHCI_H_ */
diff --git a/sys/dev/usb/controller/ehci_ixp4xx.c b/sys/dev/usb/controller/ehci_ixp4xx.c
index 301032ed0260..05efbb51c129 100644
--- a/sys/dev/usb/controller/ehci_ixp4xx.c
+++ b/sys/dev/usb/controller/ehci_ixp4xx.c
@@ -86,6 +86,19 @@ static void ehci_bs_w_2(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, uin
static uint32_t ehci_bs_r_4(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
static void ehci_bs_w_4(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, uint32_t);
+static void
+ehci_ixp_post_reset(struct ehci_softc *ehci_softc)
+{
+ uint32_t usbmode;
+
+ /* Force HOST mode, select big-endian mode */
+ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
+ usbmode &= ~EHCI_UM_CM;
+ usbmode |= EHCI_UM_CM_HOST;
+ usbmode |= EHCI_UM_ES_BE;
+ EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
+}
+
static int
ehci_ixp_probe(device_t self)
{
@@ -173,20 +186,21 @@ ehci_ixp_attach(device_t self)
}
/*
- * Arrange to force Host mode, select big-endian byte alignment,
- * and arrange to not terminate reset operations (the adapter
- * will ignore it if we do but might as well save a reg write).
- * Also, the controller has an embedded Transaction Translator
- * which means port speed must be read from the Port Status
- * register following a port enable.
+ * Select big-endian byte alignment and arrange to not terminate
+ * reset operations (the adapter will ignore it if we do but might
+ * as well save a reg write). Also, the controller has an embedded
+ * Transaction Translator which means port speed must be read from
+ * the Port Status register following a port enable.
*/
sc->sc_flags |= EHCI_SCFLG_TT
- | EHCI_SCFLG_SETMODE
| EHCI_SCFLG_BIGEDESC
- | EHCI_SCFLG_BIGEMMIO
| EHCI_SCFLG_NORESTERM
;
+ /* Setup callbacks. */
+ sc->sc_vendor_post_reset = ehci_ixp_post_reset;
+ sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc;
+
err = ehci_init(sc);
if (!err) {
err = device_probe_and_attach(sc->sc_bus.bdev);
diff --git a/sys/dev/usb/controller/ehci_mv.c b/sys/dev/usb/controller/ehci_mv.c
index f06a83056f7e..cd7d549aaf46 100644
--- a/sys/dev/usb/controller/ehci_mv.c
+++ b/sys/dev/usb/controller/ehci_mv.c
@@ -105,6 +105,18 @@ static struct ofw_compat_data compat_data[] = {
{NULL, false}
};
+static void
+mv_ehci_post_reset(struct ehci_softc *ehci_softc)
+{
+ uint32_t usbmode;
+
+ /* Force HOST mode */
+ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
+ usbmode &= ~EHCI_UM_CM;
+ usbmode |= EHCI_UM_CM_HOST;
+ EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
+}
+
static int
mv_ehci_probe(device_t self)
{
@@ -226,13 +238,13 @@ mv_ehci_attach(device_t self)
* Refer to errata document MV-S500832-00D.pdf (p. 5.24 GL USB-2) for
* details.
*/
- sc->sc_flags |= EHCI_SCFLG_SETMODE;
+ sc->sc_vendor_post_reset = mv_ehci_post_reset;
if (bootverbose)
device_printf(self, "5.24 GL USB-2 workaround enabled\n");
/* XXX all MV chips need it? */
- sc->sc_flags |= EHCI_SCFLG_FORCESPEED | EHCI_SCFLG_NORESTERM;
-
+ sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM;
+ sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc;
err = ehci_init(sc);
if (!err) {
err = device_probe_and_attach(sc->sc_bus.bdev);
diff --git a/sys/dev/usb/controller/ehcireg.h b/sys/dev/usb/controller/ehcireg.h
index 1f5fc5c06cad..2394b2c17c9a 100644
--- a/sys/dev/usb/controller/ehcireg.h
+++ b/sys/dev/usb/controller/ehcireg.h
@@ -157,7 +157,17 @@
#define EHCI_PS_CS 0x00000001 /* RO connect status */
#define EHCI_PS_CLEAR (EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC)
-#define EHCI_USBMODE 0x68 /* RW USB Device mode register */
+#define EHCI_PORT_RESET_COMPLETE 2 /* ms */
+
+/*
+ * Registers not covered by EHCI specification
+ *
+ *
+ * EHCI_USBMODE register offset is different for cores with LPM support,
+ * bits are equal
+ */
+#define EHCI_USBMODE_NOLPM 0x68 /* RW USB Device mode reg (no LPM) */
+#define EHCI_USBMODE_LPM 0xC8 /* RW USB Device mode reg (LPM) */
#define EHCI_UM_CM 0x00000003 /* R/WO Controller Mode */
#define EHCI_UM_CM_IDLE 0x0 /* Idle */
#define EHCI_UM_CM_HOST 0x3 /* Host Controller */
@@ -166,6 +176,18 @@
#define EHCI_UM_ES_BE 0x4 /* Big-endian byte alignment */
#define EHCI_UM_SDIS 0x00000010 /* R/WO Stream Disable Mode */
-#define EHCI_PORT_RESET_COMPLETE 2 /* ms */
+/*
+ * Actual port speed bits depends on EHCI_HOSTC(n) registers presence,
+ * speed encoding is equal
+ */
+#define EHCI_HOSTC(n) (0x80+(4*(n))) /* RO, RW Host mode control reg */
+#define EHCI_HOSTC_PSPD_SHIFT 25
+#define EHCI_HOSTC_PSPD_MASK 0x3
+
+#define EHCI_PORTSC_PSPD_SHIFT 26
+#define EHCI_PORTSC_PSPD_MASK 0x3
+#define EHCI_PORT_SPEED_FULL 0
+#define EHCI_PORT_SPEED_LOW 1
+#define EHCI_PORT_SPEED_HIGH 2
#endif /* _EHCIREG_H_ */
diff --git a/sys/dev/usb/wlan/if_rsu.c b/sys/dev/usb/wlan/if_rsu.c
index 0dcde19add44..5aa460ba82c1 100644
--- a/sys/dev/usb/wlan/if_rsu.c
+++ b/sys/dev/usb/wlan/if_rsu.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/endian.h>
#include <sys/sockio.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
diff --git a/sys/dev/vnic/mrml_bridge.c b/sys/dev/vnic/mrml_bridge.c
new file mode 100644
index 000000000000..edc15717c4ae
--- /dev/null
+++ b/sys/dev/vnic/mrml_bridge.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2016 Cavium Inc.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/fdt/simplebus.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+static MALLOC_DEFINE(M_MRMLB, "MRML bridge", "Cavium MRML bridge");
+
+static device_probe_t mrmlb_fdt_probe;
+static device_attach_t mrmlb_fdt_attach;
+
+static struct resource * mrmlb_ofw_bus_alloc_res(device_t, device_t, int, int *,
+ rman_res_t, rman_res_t, rman_res_t, u_int);
+
+static const struct ofw_bus_devinfo * mrmlb_ofw_get_devinfo(device_t, device_t);
+
+static device_method_t mrmlbus_fdt_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, mrmlb_fdt_probe),
+ DEVMETHOD(device_attach, mrmlb_fdt_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_alloc_resource, mrmlb_ofw_bus_alloc_res),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_devinfo, mrmlb_ofw_get_devinfo),
+ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
+ DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
+ DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
+ DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
+ DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(mrmlbus, mrmlbus_fdt_driver, mrmlbus_fdt_methods,
+ sizeof(struct simplebus_softc));
+
+static devclass_t mrmlbus_fdt_devclass;
+
+EARLY_DRIVER_MODULE(mrmlbus, pcib, mrmlbus_fdt_driver, mrmlbus_fdt_devclass, 0, 0,
+ BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+
+static int mrmlb_ofw_fill_ranges(phandle_t, struct simplebus_softc *);
+static int mrmlb_ofw_bus_attach(device_t);
+
+static int
+mrmlb_fdt_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "cavium,thunder-8890-mrml-bridge"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Cavium ThunderX MRML bridge");
+ return (BUS_PROBE_SPECIFIC);
+}
+
+static int
+mrmlb_fdt_attach(device_t dev)
+{
+ int err;
+
+ err = mrmlb_ofw_bus_attach(dev);
+ if (err != 0)
+ return (err);
+
+ return (bus_generic_attach(dev));
+}
+
+/* OFW bus interface */
+struct mrmlb_ofw_devinfo {
+ struct ofw_bus_devinfo di_dinfo;
+ struct resource_list di_rl;
+};
+
+static const struct ofw_bus_devinfo *
+mrmlb_ofw_get_devinfo(device_t bus __unused, device_t child)
+{
+ struct mrmlb_ofw_devinfo *di;
+
+ di = device_get_ivars(child);
+ return (&di->di_dinfo);
+}
+
+static struct resource *
+mrmlb_ofw_bus_alloc_res(device_t bus, device_t child, int type, int *rid,
+ rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+{
+ struct simplebus_softc *sc;
+ struct mrmlb_ofw_devinfo *di;
+ struct resource_list_entry *rle;
+ int i;
+
+ if ((start == 0UL) && (end == ~0UL)) {
+ if ((di = device_get_ivars(child)) == NULL)
+ return (NULL);
+ if (type == SYS_RES_IOPORT)
+ type = SYS_RES_MEMORY;
+
+ /* Find defaults for this rid */
+ rle = resource_list_find(&di->di_rl, type, *rid);
+ if (rle == NULL)
+ return (NULL);
+
+ start = rle->start;
+ end = rle->end;
+ count = rle->count;
+ }
+
+ sc = device_get_softc(bus);
+
+ if (type == SYS_RES_MEMORY) {
+ /* Remap through ranges property */
+ for (i = 0; i < sc->nranges; i++) {
+ if (start >= sc->ranges[i].bus && end <
+ sc->ranges[i].bus + sc->ranges[i].size) {
+ start -= sc->ranges[i].bus;
+ start += sc->ranges[i].host;
+ end -= sc->ranges[i].bus;
+ end += sc->ranges[i].host;
+ break;
+ }
+ }
+
+ if (i == sc->nranges && sc->nranges != 0) {
+ device_printf(bus, "Could not map resource "
+ "%#lx-%#lx\n", start, end);
+ return (NULL);
+ }
+ }
+
+ return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
+ count, flags));
+}
+
+/* Helper functions */
+
+static int
+mrmlb_ofw_fill_ranges(phandle_t node, struct simplebus_softc *sc)
+{
+ int host_address_cells;
+ cell_t *base_ranges;
+ ssize_t nbase_ranges;
+ int err;
+ int i, j, k;
+
+ err = OF_searchencprop(OF_parent(node), "#address-cells",
+ &host_address_cells, sizeof(host_address_cells));
+ if (err <= 0)
+ return (-1);
+
+ nbase_ranges = OF_getproplen(node, "ranges");
+ if (nbase_ranges < 0)
+ return (-1);
+ sc->nranges = nbase_ranges / sizeof(cell_t) /
+ (sc->acells + host_address_cells + sc->scells);
+ if (sc->nranges == 0)
+ return (0);
+
+ sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]),
+ M_MRMLB, M_WAITOK);
+ base_ranges = malloc(nbase_ranges, M_MRMLB, M_WAITOK);
+ OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
+
+ for (i = 0, j = 0; i < sc->nranges; i++) {
+ sc->ranges[i].bus = 0;
+ for (k = 0; k < sc->acells; k++) {
+ sc->ranges[i].bus <<= 32;
+ sc->ranges[i].bus |= base_ranges[j++];
+ }
+ sc->ranges[i].host = 0;
+ for (k = 0; k < host_address_cells; k++) {
+ sc->ranges[i].host <<= 32;
+ sc->ranges[i].host |= base_ranges[j++];
+ }
+ sc->ranges[i].size = 0;
+ for (k = 0; k < sc->scells; k++) {
+ sc->ranges[i].size <<= 32;
+ sc->ranges[i].size |= base_ranges[j++];
+ }
+ }
+
+ free(base_ranges, M_MRMLB);
+ return (sc->nranges);
+}
+
+static int
+mrmlb_ofw_bus_attach(device_t dev)
+{
+ struct simplebus_softc *sc;
+ struct mrmlb_ofw_devinfo *di;
+ device_t child;
+ phandle_t parent, node;
+
+ parent = ofw_bus_get_node(dev);
+ simplebus_init(dev, parent);
+
+ sc = device_get_softc(dev);
+
+ if (mrmlb_ofw_fill_ranges(parent, sc) < 0) {
+ device_printf(dev, "could not get ranges\n");
+ return (ENXIO);
+ }
+ /* Iterate through all bus subordinates */
+ for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
+ /* Allocate and populate devinfo. */
+ di = malloc(sizeof(*di), M_MRMLB, M_WAITOK | M_ZERO);
+ if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node) != 0) {
+ free(di, M_MRMLB);
+ continue;
+ }
+
+ /* Initialize and populate resource list. */
+ resource_list_init(&di->di_rl);
+ ofw_bus_reg_to_rl(dev, node, sc->acells, sc->scells,
+ &di->di_rl);
+ ofw_bus_intr_to_rl(dev, node, &di->di_rl, NULL);
+
+ /* Add newbus device for this FDT node */
+ child = device_add_child(dev, NULL, -1);
+ if (child == NULL) {
+ resource_list_free(&di->di_rl);
+ ofw_bus_gen_destroy_devinfo(&di->di_dinfo);
+ free(di, M_MRMLB);
+ continue;
+ }
+
+ device_set_ivars(child, di);
+ }
+
+ return (0);
+}
diff --git a/sys/dev/vnic/thunder_bgx.c b/sys/dev/vnic/thunder_bgx.c
index 32d97c871cf6..349475459961 100644
--- a/sys/dev/vnic/thunder_bgx.c
+++ b/sys/dev/vnic/thunder_bgx.c
@@ -68,7 +68,7 @@ __FBSDID("$FreeBSD$");
#define THUNDER_BGX_DEVSTR "ThunderX BGX Ethernet I/O Interface"
-static MALLOC_DEFINE(M_BGX, "thunder_bgx", "ThunderX BGX dynamic memory");
+MALLOC_DEFINE(M_BGX, "thunder_bgx", "ThunderX BGX dynamic memory");
#define BGX_NODE_ID_MASK 0x1
#define BGX_NODE_ID_SHIFT 24
diff --git a/sys/dev/vnic/thunder_bgx_fdt.c b/sys/dev/vnic/thunder_bgx_fdt.c
index 1560262c8cc0..ec6e68f64850 100644
--- a/sys/dev/vnic/thunder_bgx_fdt.c
+++ b/sys/dev/vnic/thunder_bgx_fdt.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <net/if_media.h>
#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
#include <dev/mii/miivar.h>
#include "thunder_bgx.h"
@@ -61,6 +62,11 @@ __FBSDID("$FreeBSD$");
#define CONN_TYPE_MAXLEN 16
#define CONN_TYPE_OFFSET 2
+#define BGX_NODE_NAME "bgx"
+#define BGX_MAXID 9
+
+#define FDT_NAME_MAXLEN 31
+
int bgx_fdt_init_phy(struct bgx *);
static void
@@ -119,28 +125,152 @@ bgx_fdt_phy_mode_match(struct bgx *bgx, char *qlm_mode, size_t size)
return (FALSE);
}
+static phandle_t
+bgx_fdt_traverse_nodes(phandle_t start, char *name, size_t len)
+{
+ phandle_t node, ret;
+ size_t buf_size;
+ char *node_name;
+ int err;
+
+ buf_size = sizeof(*node_name) * FDT_NAME_MAXLEN;
+ if (len > buf_size) {
+ /*
+ * This is an erroneous situation since the string
+ * to compare cannot be longer than FDT_NAME_MAXLEN.
+ */
+ return (0);
+ }
+
+ node_name = malloc(buf_size, M_BGX, M_WAITOK);
+ for (node = OF_child(start); node != 0; node = OF_peer(node)) {
+ /* Clean-up the buffer */
+ memset(node_name, 0, buf_size);
+ /* Recurse to children */
+ if (OF_child(node) != 0) {
+ ret = bgx_fdt_traverse_nodes(node, name, len);
+ if (ret != 0) {
+ free(node_name, M_BGX);
+ return (ret);
+ }
+ }
+ err = OF_getprop(node, "name", node_name, FDT_NAME_MAXLEN);
+ if ((err > 0) && (strncmp(node_name, name, len) == 0)) {
+ free(node_name, M_BGX);
+ return (node);
+ }
+ }
+ free(node_name, M_BGX);
+
+ return (0);
+}
+
+/*
+ * Similar functionality to pci_find_pcie_root_port()
+ * but this one works for ThunderX.
+ */
+static device_t
+bgx_find_root_pcib(device_t dev)
+{
+ devclass_t pci_class;
+ device_t pcib, bus;
+
+ pci_class = devclass_find("pci");
+ KASSERT(device_get_devclass(device_get_parent(dev)) == pci_class,
+ ("%s: non-pci device %s", __func__, device_get_nameunit(dev)));
+
+ /* Walk the bridge hierarchy until we find a non-PCI device */
+ for (;;) {
+ bus = device_get_parent(dev);
+ KASSERT(bus != NULL, ("%s: null parent of %s", __func__,
+ device_get_nameunit(dev)));
+
+ if (device_get_devclass(bus) != pci_class)
+ return (NULL);
+
+ pcib = device_get_parent(bus);
+ KASSERT(pcib != NULL, ("%s: null bridge of %s", __func__,
+ device_get_nameunit(bus)));
+
+ /*
+ * If the parent of this PCIB is not PCI
+ * then we found our root PCIB.
+ */
+ if (device_get_devclass(device_get_parent(pcib)) != pci_class)
+ return (pcib);
+
+ dev = pcib;
+ }
+}
+
+static __inline phandle_t
+bgx_fdt_find_node(struct bgx *bgx)
+{
+ device_t root_pcib;
+ phandle_t node;
+ char *bgx_sel;
+ size_t len;
+
+ KASSERT(bgx->bgx_id <= BGX_MAXID,
+ ("Invalid BGX ID: %d, max: %d", bgx->bgx_id, BGX_MAXID));
+
+ len = sizeof(BGX_NODE_NAME) + 1; /* <bgx_name>+<digit>+<\0> */
+ /* Allocate memory for BGX node name + "/" character */
+ bgx_sel = malloc(sizeof(*bgx_sel) * (len + 1), M_BGX,
+ M_ZERO | M_WAITOK);
+
+ /* Prepare node's name */
+ snprintf(bgx_sel, len + 1, "/"BGX_NODE_NAME"%d", bgx->bgx_id);
+ /* First try the root node */
+ node = OF_finddevice(bgx_sel);
+ if ((int)node > 0) {
+ /* Found relevant node */
+ goto out;
+ }
+ /*
+ * Clean-up and try to find BGX in DT
+ * starting from the parent PCI bridge node.
+ */
+ memset(bgx_sel, 0, sizeof(*bgx_sel) * (len + 1));
+ snprintf(bgx_sel, len, BGX_NODE_NAME"%d", bgx->bgx_id);
+
+ /* Find PCI bridge that we are connected to */
+
+ root_pcib = bgx_find_root_pcib(bgx->dev);
+ if (root_pcib == NULL) {
+ device_printf(bgx->dev, "Unable to find BGX root bridge\n");
+ node = 0;
+ goto out;
+ }
+
+ node = ofw_bus_get_node(root_pcib);
+ if ((int)node <= 0) {
+ device_printf(bgx->dev, "No parent FDT node for BGX\n");
+ goto out;
+ }
+
+ node = bgx_fdt_traverse_nodes(node, bgx_sel, len);
+out:
+ free(bgx_sel, M_BGX);
+ return (node);
+}
+
int
bgx_fdt_init_phy(struct bgx *bgx)
{
phandle_t node, child;
phandle_t phy, mdio;
uint8_t lmac;
- char bgx_sel[6];
char qlm_mode[CONN_TYPE_MAXLEN];
- const char *mac;
-
- (void)mac;
- lmac = 0;
- /* Get BGX node from DT */
- snprintf(bgx_sel, 6, "/bgx%d", bgx->bgx_id);
- node = OF_finddevice(bgx_sel);
- if (node == 0 || node == -1) {
+ node = bgx_fdt_find_node(bgx);
+ if (node == 0) {
device_printf(bgx->dev,
- "Could not find %s node in FDT\n", bgx_sel);
+ "Could not find bgx%d node in FDT\n", bgx->bgx_id);
return (ENXIO);
}
+ lmac = 0;
for (child = OF_child(node); child > 0; child = OF_peer(child)) {
if (OF_getprop(child, "qlm-mode", qlm_mode,
sizeof(qlm_mode)) <= 0) {
diff --git a/sys/dev/vnic/thunder_bgx_var.h b/sys/dev/vnic/thunder_bgx_var.h
index bfb1ef0ccbb5..42f32d918210 100644
--- a/sys/dev/vnic/thunder_bgx_var.h
+++ b/sys/dev/vnic/thunder_bgx_var.h
@@ -30,6 +30,8 @@
#ifndef __THUNDER_BGX_VAR_H__
#define __THUNDER_BGX_VAR_H__
+MALLOC_DECLARE(M_BGX);
+
struct lmac {
struct bgx *bgx;
int dmac;
diff --git a/sys/dev/vnic/thunder_mdio_fdt.c b/sys/dev/vnic/thunder_mdio_fdt.c
index b24be1dc3ee6..cc9415050388 100644
--- a/sys/dev/vnic/thunder_mdio_fdt.c
+++ b/sys/dev/vnic/thunder_mdio_fdt.c
@@ -38,6 +38,10 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/fdt/simplebus.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
#include "thunder_mdio_var.h"
@@ -60,17 +64,26 @@ static devclass_t thunder_mdio_fdt_devclass;
EARLY_DRIVER_MODULE(thunder_mdio, ofwbus, thunder_mdio_fdt_driver,
thunder_mdio_fdt_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+EARLY_DRIVER_MODULE(thunder_mdio, mdionexus, thunder_mdio_fdt_driver,
+ thunder_mdio_fdt_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+
+static struct ofw_compat_data mdio_compat_data[] = {
+ {"cavium,octeon-3860-mdio", true},
+ {"cavium,thunder-8890-mdio", true},
+ {NULL, false}
+};
static int
thunder_mdio_fdt_probe(device_t dev)
{
- if (ofw_bus_is_compatible(dev, "cavium,octeon-3860-mdio")) {
- device_set_desc(dev, THUNDER_MDIO_DEVSTR);
- return (BUS_PROBE_DEFAULT);
- }
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+ if (!ofw_bus_search_compatible(dev, mdio_compat_data)->ocd_data)
+ return (ENXIO);
- return (ENXIO);
+ device_set_desc(dev, THUNDER_MDIO_DEVSTR);
+ return (BUS_PROBE_DEFAULT);
}
static int
@@ -93,3 +106,184 @@ thunder_mdio_fdt_attach(device_t dev)
return (0);
}
+
+struct mdionexus_softc {
+ struct simplebus_softc simplebus_sc;
+};
+
+static device_probe_t mdionexus_fdt_probe;
+static device_attach_t mdionexus_fdt_attach;
+
+static const struct ofw_bus_devinfo * mdionexus_ofw_get_devinfo(device_t,
+ device_t);
+
+static device_method_t mdionexus_fdt_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, mdionexus_fdt_probe),
+ DEVMETHOD(device_attach, mdionexus_fdt_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_devinfo, mdionexus_ofw_get_devinfo),
+ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
+ DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
+ DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
+ DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
+ DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(mdionexus, mdionexus_fdt_driver, mdionexus_fdt_methods,
+ sizeof(struct mdionexus_softc));
+
+static devclass_t mdionexus_fdt_devclass;
+
+EARLY_DRIVER_MODULE(mdionexus, mrmlbus, mdionexus_fdt_driver,
+ mdionexus_fdt_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+
+static int mdionexus_ofw_fill_ranges(phandle_t, struct simplebus_softc *);
+static int mdionexus_ofw_bus_attach(device_t);
+
+static int
+mdionexus_fdt_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "cavium,thunder-8890-mdio-nexus"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Cavium ThunderX MDIO nexus");
+ return (BUS_PROBE_SPECIFIC);
+}
+
+static int
+mdionexus_fdt_attach(device_t dev)
+{
+ int err;
+
+ err = mdionexus_ofw_bus_attach(dev);
+ if (err != 0)
+ return (err);
+
+ return (bus_generic_attach(dev));
+}
+
+/* OFW bus interface */
+struct mdionexus_ofw_devinfo {
+ struct ofw_bus_devinfo di_dinfo;
+ struct resource_list di_rl;
+};
+
+static const struct ofw_bus_devinfo *
+mdionexus_ofw_get_devinfo(device_t bus __unused, device_t child)
+{
+ struct mdionexus_ofw_devinfo *di;
+
+ di = device_get_ivars(child);
+ return (&di->di_dinfo);
+}
+
+/* Helper functions */
+
+static int
+mdionexus_ofw_fill_ranges(phandle_t node, struct simplebus_softc *sc)
+{
+ int host_address_cells;
+ cell_t *base_ranges;
+ ssize_t nbase_ranges;
+ int err;
+ int i, j, k;
+
+ err = OF_searchencprop(OF_parent(node), "#address-cells",
+ &host_address_cells, sizeof(host_address_cells));
+ if (err <= 0)
+ return (-1);
+
+ nbase_ranges = OF_getproplen(node, "ranges");
+ if (nbase_ranges < 0)
+ return (-1);
+ sc->nranges = nbase_ranges / sizeof(cell_t) /
+ (sc->acells + host_address_cells + sc->scells);
+ if (sc->nranges == 0)
+ return (0);
+
+ sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]),
+ M_THUNDER_MDIO, M_WAITOK);
+ base_ranges = malloc(nbase_ranges, M_THUNDER_MDIO, M_WAITOK);
+ OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
+
+ for (i = 0, j = 0; i < sc->nranges; i++) {
+ sc->ranges[i].bus = 0;
+ for (k = 0; k < sc->acells; k++) {
+ sc->ranges[i].bus <<= 32;
+ sc->ranges[i].bus |= base_ranges[j++];
+ }
+ sc->ranges[i].host = 0;
+ for (k = 0; k < host_address_cells; k++) {
+ sc->ranges[i].host <<= 32;
+ sc->ranges[i].host |= base_ranges[j++];
+ }
+ sc->ranges[i].size = 0;
+ for (k = 0; k < sc->scells; k++) {
+ sc->ranges[i].size <<= 32;
+ sc->ranges[i].size |= base_ranges[j++];
+ }
+ }
+
+ free(base_ranges, M_THUNDER_MDIO);
+ return (sc->nranges);
+}
+
+static int
+mdionexus_ofw_bus_attach(device_t dev)
+{
+ struct simplebus_softc *sc;
+ struct mdionexus_ofw_devinfo *di;
+ device_t child;
+ phandle_t parent, node;
+
+ parent = ofw_bus_get_node(dev);
+ simplebus_init(dev, parent);
+
+ sc = (struct simplebus_softc *)device_get_softc(dev);
+
+ if (mdionexus_ofw_fill_ranges(parent, sc) < 0) {
+ device_printf(dev, "could not get ranges\n");
+ return (ENXIO);
+ }
+ /* Iterate through all bus subordinates */
+ for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
+ /* Allocate and populate devinfo. */
+ di = malloc(sizeof(*di), M_THUNDER_MDIO, M_WAITOK | M_ZERO);
+ if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node) != 0) {
+ free(di, M_THUNDER_MDIO);
+ continue;
+ }
+
+ /* Initialize and populate resource list. */
+ resource_list_init(&di->di_rl);
+ ofw_bus_reg_to_rl(dev, node, sc->acells, sc->scells,
+ &di->di_rl);
+ ofw_bus_intr_to_rl(dev, node, &di->di_rl, NULL);
+
+ /* Add newbus device for this FDT node */
+ child = device_add_child(dev, NULL, -1);
+ if (child == NULL) {
+ resource_list_free(&di->di_rl);
+ ofw_bus_gen_destroy_devinfo(&di->di_dinfo);
+ free(di, M_THUNDER_MDIO);
+ continue;
+ }
+
+ device_set_ivars(child, di);
+ }
+
+ return (0);
+}
diff --git a/sys/dev/vnic/thunder_mdio_var.h b/sys/dev/vnic/thunder_mdio_var.h
index 01c4ca7f637c..73fedcc77811 100644
--- a/sys/dev/vnic/thunder_mdio_var.h
+++ b/sys/dev/vnic/thunder_mdio_var.h
@@ -34,6 +34,7 @@
#define __THUNDER_MDIO_VAR_H__
#define THUNDER_MDIO_DEVSTR "Cavium ThunderX SMI/MDIO driver"
+MALLOC_DECLARE(M_THUNDER_MDIO);
DECLARE_CLASS(thunder_mdio_driver);
enum thunder_mdio_mode {
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index 832e6aa37c04..8f9d1a0e7525 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$");
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/module.h>
#include <sys/bus.h>
diff --git a/sys/dev/wi/if_wi_pci.c b/sys/dev/wi/if_wi_pci.c
index b218c2479a69..a0e872af9c88 100644
--- a/sys/dev/wi/if_wi_pci.c
+++ b/sys/dev/wi/if_wi_pci.c
@@ -42,6 +42,7 @@
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/module.h>
diff --git a/sys/dev/xe/if_xe.c b/sys/dev/xe/if_xe.c
index 4a7aa6e8eb69..4975fd53726b 100644
--- a/sys/dev/xe/if_xe.c
+++ b/sys/dev/xe/if_xe.c
@@ -96,6 +96,7 @@ __FBSDID("$FreeBSD$");
#include <sys/cdefs.h>
#include <sys/errno.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
diff --git a/sys/dev/xl/if_xl.c b/sys/dev/xl/if_xl.c
index f7bd599a04ed..9568967d609b 100644
--- a/sys/dev/xl/if_xl.c
+++ b/sys/dev/xl/if_xl.c
@@ -106,8 +106,9 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/sockio.h>
#include <sys/endian.h>
-#include <sys/mbuf.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/taskqueue.h>
diff --git a/sys/fs/ext2fs/ext2_inode_cnv.c b/sys/fs/ext2fs/ext2_inode_cnv.c
index 78679cff0fdb..d62e9ba0a92e 100644
--- a/sys/fs/ext2fs/ext2_inode_cnv.c
+++ b/sys/fs/ext2fs/ext2_inode_cnv.c
@@ -149,11 +149,13 @@ ext2_i2ei(struct inode *ip, struct ext2fs_dinode *ei)
ei->e2di_atime = ip->i_atime;
ei->e2di_mtime = ip->i_mtime;
ei->e2di_ctime = ip->i_ctime;
- ei->e2di_ctime_extra = NSEC_TO_XTIME(ip->i_ctimensec);
- ei->e2di_mtime_extra = NSEC_TO_XTIME(ip->i_mtimensec);
- ei->e2di_atime_extra = NSEC_TO_XTIME(ip->i_atimensec);
- ei->e2di_crtime = ip->i_birthtime;
- ei->e2di_crtime_extra = NSEC_TO_XTIME(ip->i_birthnsec);
+ if (E2DI_HAS_XTIME(ip)) {
+ ei->e2di_ctime_extra = NSEC_TO_XTIME(ip->i_ctimensec);
+ ei->e2di_mtime_extra = NSEC_TO_XTIME(ip->i_mtimensec);
+ ei->e2di_atime_extra = NSEC_TO_XTIME(ip->i_atimensec);
+ ei->e2di_crtime = ip->i_birthtime;
+ ei->e2di_crtime_extra = NSEC_TO_XTIME(ip->i_birthnsec);
+ }
ei->e2di_flags = 0;
ei->e2di_flags |= (ip->i_flags & SF_APPEND) ? EXT2_APPEND: 0;
ei->e2di_flags |= (ip->i_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE: 0;
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 8a7a11a242d9..43d48000d140 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -258,7 +258,7 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp,
int interp_name_len, int32_t *osrel)
{
const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header;
- Elf_Brandinfo *bi;
+ Elf_Brandinfo *bi, *bi_m;
boolean_t ret;
int i;
@@ -270,6 +270,7 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp,
*/
/* Look for an ".note.ABI-tag" ELF section */
+ bi_m = NULL;
for (i = 0; i < MAX_BRANDS; i++) {
bi = elf_brand_list[i];
if (bi == NULL)
@@ -280,10 +281,28 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp,
/* Give brand a chance to veto check_note's guess */
if (ret && bi->header_supported)
ret = bi->header_supported(imgp);
+ /*
+ * If note checker claimed the binary, but the
+ * interpreter path in the image does not
+ * match default one for the brand, try to
+ * search for other brands with the same
+ * interpreter. Either there is better brand
+ * with the right interpreter, or, failing
+ * this, we return first brand which accepted
+ * our note and, optionally, header.
+ */
+ if (ret && bi_m == NULL && (strlen(bi->interp_path) +
+ 1 != interp_name_len || strncmp(interp,
+ bi->interp_path, interp_name_len) != 0)) {
+ bi_m = bi;
+ ret = 0;
+ }
if (ret)
return (bi);
}
}
+ if (bi_m != NULL)
+ return (bi_m);
/* If the executable has a brand, search for it in the brand list. */
for (i = 0; i < MAX_BRANDS; i++) {
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 8d5580b6d046..d5f8f4ddbe31 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -828,12 +828,15 @@ start_init(void *dummy)
static void
create_init(const void *udata __unused)
{
+ struct fork_req fr;
struct ucred *newcred, *oldcred;
struct thread *td;
int error;
- error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc,
- NULL, 0, NULL);
+ bzero(&fr, sizeof(fr));
+ fr.fr_flags = RFFDG | RFPROC | RFSTOPPED;
+ fr.fr_procp = &initproc;
+ error = fork1(&thread0, &fr);
if (error)
panic("cannot fork init: %d\n", error);
KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1"));
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index d41ac96a70af..805b6b541612 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -373,11 +373,21 @@ filt_procattach(struct knote *kn)
kn->kn_flags |= EV_CLEAR; /* automatically set */
/*
- * internal flag indicating registration done by kernel
+ * Internal flag indicating registration done by kernel for the
+ * purposes of getting a NOTE_CHILD notification.
*/
- if (kn->kn_flags & EV_FLAG1) {
+ if (kn->kn_flags & EV_FLAG2) {
+ kn->kn_flags &= ~EV_FLAG2;
kn->kn_data = kn->kn_sdata; /* ppid */
kn->kn_fflags = NOTE_CHILD;
+ kn->kn_sfflags &= ~NOTE_EXIT;
+ immediate = 1; /* Force immediate activation of child note. */
+ }
+ /*
+ * Internal flag indicating registration done by kernel (for other than
+ * NOTE_CHILD).
+ */
+ if (kn->kn_flags & EV_FLAG1) {
kn->kn_flags &= ~EV_FLAG1;
}
@@ -385,9 +395,10 @@ filt_procattach(struct knote *kn)
knlist_add(&p->p_klist, kn, 1);
/*
- * Immediately activate any exit notes if the target process is a
- * zombie. This is necessary to handle the case where the target
- * process, e.g. a child, dies before the kevent is registered.
+ * Immediately activate any child notes or, in the case of a zombie
+ * target process, exit notes. The latter is necessary to handle the
+ * case where the target process, e.g. a child, dies before the kevent
+ * is registered.
*/
if (immediate && filt_proc(kn, NOTE_EXIT))
KNOTE_ACTIVATE(kn, 0);
@@ -495,7 +506,7 @@ knote_fork(struct knlist *list, int pid)
/*
* The NOTE_TRACK case. In addition to the activation
- * of the event, we need to register new event to
+ * of the event, we need to register new events to
* track the child. Drop the locks in preparation for
* the call to kqueue_register().
*/
@@ -504,8 +515,27 @@ knote_fork(struct knlist *list, int pid)
list->kl_unlock(list->kl_lockarg);
/*
- * Activate existing knote and register a knote with
+ * Activate existing knote and register tracking knotes with
* new process.
+ *
+ * First register a knote to get just the child notice. This
+ * must be a separate note from a potential NOTE_EXIT
+ * notification since both NOTE_CHILD and NOTE_EXIT are defined
+ * to use the data field (in conflicting ways).
+ */
+ kev.ident = pid;
+ kev.filter = kn->kn_filter;
+ kev.flags = kn->kn_flags | EV_ADD | EV_ENABLE | EV_ONESHOT | EV_FLAG2;
+ kev.fflags = kn->kn_sfflags;
+ kev.data = kn->kn_id; /* parent */
+ kev.udata = kn->kn_kevent.udata;/* preserve udata */
+ error = kqueue_register(kq, &kev, NULL, 0);
+ if (error)
+ kn->kn_fflags |= NOTE_TRACKERR;
+
+ /*
+ * Then register another knote to track other potential events
+ * from the new process.
*/
kev.ident = pid;
kev.filter = kn->kn_filter;
@@ -1129,7 +1159,7 @@ findkn:
if (fp->f_type == DTYPE_KQUEUE) {
/*
- * if we add some inteligence about what we are doing,
+ * If we add some intelligence about what we are doing,
* we should be able to support events on ourselves.
* We need to know when we are doing this to prevent
* getting both the knlist lock and the kq lock since
@@ -1161,7 +1191,18 @@ findkn:
kqueue_expand(kq, fops, kev->ident, waitok);
KQ_LOCK(kq);
- if (kq->kq_knhashmask != 0) {
+
+ /*
+ * If possible, find an existing knote to use for this kevent.
+ */
+ if (kev->filter == EVFILT_PROC &&
+ (kev->flags & (EV_FLAG1 | EV_FLAG2)) != 0) {
+ /* This is an internal creation of a process tracking
+ * note. Don't attempt to coalesce this with an
+ * existing note.
+ */
+ ;
+ } else if (kq->kq_knhashmask != 0) {
struct klist *list;
list = &kq->kq_knhash[
@@ -1173,7 +1214,7 @@ findkn:
}
}
- /* knote is in the process of changing, wait for it to stablize. */
+ /* knote is in the process of changing, wait for it to stabilize. */
if (kn != NULL && (kn->kn_status & KN_INFLUX) == KN_INFLUX) {
KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal);
if (filedesc_unlock) {
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index e7d727619be0..9abe08c037c5 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -101,12 +101,15 @@ struct fork_args {
int
sys_fork(struct thread *td, struct fork_args *uap)
{
- int error;
- struct proc *p2;
+ struct fork_req fr;
+ int error, pid;
- error = fork1(td, RFFDG | RFPROC, 0, &p2, NULL, 0, NULL);
+ bzero(&fr, sizeof(fr));
+ fr.fr_flags = RFFDG | RFPROC;
+ fr.fr_pidp = &pid;
+ error = fork1(td, &fr);
if (error == 0) {
- td->td_retval[0] = p2->p_pid;
+ td->td_retval[0] = pid;
td->td_retval[1] = 0;
}
return (error);
@@ -114,22 +117,24 @@ sys_fork(struct thread *td, struct fork_args *uap)
/* ARGUSED */
int
-sys_pdfork(td, uap)
- struct thread *td;
- struct pdfork_args *uap;
+sys_pdfork(struct thread *td, struct pdfork_args *uap)
{
- int error, fd;
- struct proc *p2;
-
+ struct fork_req fr;
+ int error, fd, pid;
+
+ bzero(&fr, sizeof(fr));
+ fr.fr_flags = RFFDG | RFPROC | RFPROCDESC;
+ fr.fr_pidp = &pid;
+ fr.fr_pd_fd = &fd;
+ fr.fr_pd_flags = uap->flags;
/*
* It is necessary to return fd by reference because 0 is a valid file
* descriptor number, and the child needs to be able to distinguish
* itself from the parent using the return value.
*/
- error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2,
- &fd, uap->flags, NULL);
+ error = fork1(td, &fr);
if (error == 0) {
- td->td_retval[0] = p2->p_pid;
+ td->td_retval[0] = pid;
td->td_retval[1] = 0;
error = copyout(&fd, uap->fdp, sizeof(fd));
}
@@ -140,13 +145,15 @@ sys_pdfork(td, uap)
int
sys_vfork(struct thread *td, struct vfork_args *uap)
{
- int error, flags;
- struct proc *p2;
+ struct fork_req fr;
+ int error, pid;
- flags = RFFDG | RFPROC | RFPPWAIT | RFMEM;
- error = fork1(td, flags, 0, &p2, NULL, 0, NULL);
+ bzero(&fr, sizeof(fr));
+ fr.fr_flags = RFFDG | RFPROC | RFPPWAIT | RFMEM;
+ fr.fr_pidp = &pid;
+ error = fork1(td, &fr);
if (error == 0) {
- td->td_retval[0] = p2->p_pid;
+ td->td_retval[0] = pid;
td->td_retval[1] = 0;
}
return (error);
@@ -155,17 +162,20 @@ sys_vfork(struct thread *td, struct vfork_args *uap)
int
sys_rfork(struct thread *td, struct rfork_args *uap)
{
- struct proc *p2;
- int error;
+ struct fork_req fr;
+ int error, pid;
/* Don't allow kernel-only flags. */
if ((uap->flags & RFKERNELONLY) != 0)
return (EINVAL);
AUDIT_ARG_FFLAGS(uap->flags);
- error = fork1(td, uap->flags, 0, &p2, NULL, 0, NULL);
+ bzero(&fr, sizeof(fr));
+ fr.fr_flags = uap->flags;
+ fr.fr_pidp = &pid;
+ error = fork1(td, &fr);
if (error == 0) {
- td->td_retval[0] = p2 ? p2->p_pid : 0;
+ td->td_retval[0] = pid;
td->td_retval[1] = 0;
}
return (error);
@@ -366,11 +376,11 @@ fail:
}
static void
-do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
- struct vmspace *vm2, int pdflags)
+do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *td2,
+ struct vmspace *vm2, struct file *fp_procdesc)
{
struct proc *p1, *pptr;
- int p2_held, trypid;
+ int trypid;
struct filedesc *fd;
struct filedesc_to_leader *fdtol;
struct sigacts *newsigacts;
@@ -378,10 +388,9 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
sx_assert(&proctree_lock, SX_SLOCKED);
sx_assert(&allproc_lock, SX_XLOCKED);
- p2_held = 0;
p1 = td->td_proc;
- trypid = fork_findpid(flags);
+ trypid = fork_findpid(fr->fr_flags);
sx_sunlock(&proctree_lock);
@@ -414,7 +423,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
/*
* Malloc things while we don't hold any locks.
*/
- if (flags & RFSIGSHARE)
+ if (fr->fr_flags & RFSIGSHARE)
newsigacts = NULL;
else
newsigacts = sigacts_alloc();
@@ -422,10 +431,10 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
/*
* Copy filedesc.
*/
- if (flags & RFCFDG) {
+ if (fr->fr_flags & RFCFDG) {
fd = fdinit(p1->p_fd, false);
fdtol = NULL;
- } else if (flags & RFFDG) {
+ } else if (fr->fr_flags & RFFDG) {
fd = fdcopy(p1->p_fd);
fdtol = NULL;
} else {
@@ -433,7 +442,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
if (p1->p_fdtol == NULL)
p1->p_fdtol = filedesc_to_leader_alloc(NULL, NULL,
p1->p_leader);
- if ((flags & RFTHREAD) != 0) {
+ if ((fr->fr_flags & RFTHREAD) != 0) {
/*
* Shared file descriptor table, and shared
* process leaders.
@@ -501,16 +510,16 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
vm_domain_policy_localcopy(&p2->p_vm_dom_policy,
&p1->p_vm_dom_policy);
- if (flags & RFSIGSHARE) {
+ if (fr->fr_flags & RFSIGSHARE) {
p2->p_sigacts = sigacts_hold(p1->p_sigacts);
} else {
sigacts_copy(newsigacts, p1->p_sigacts);
p2->p_sigacts = newsigacts;
}
- if (flags & RFTSIGZMB)
- p2->p_sigparent = RFTSIGNUM(flags);
- else if (flags & RFLINUXTHPN)
+ if (fr->fr_flags & RFTSIGZMB)
+ p2->p_sigparent = RFTSIGNUM(fr->fr_flags);
+ else if (fr->fr_flags & RFLINUXTHPN)
p2->p_sigparent = SIGUSR1;
else
p2->p_sigparent = SIGCHLD;
@@ -543,7 +552,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
/*
* Set up linkage for kernel based threading.
*/
- if ((flags & RFTHREAD) != 0) {
+ if ((fr->fr_flags & RFTHREAD) != 0) {
mtx_lock(&ppeers_lock);
p2->p_peers = p1->p_peers;
p1->p_peers = p2;
@@ -590,7 +599,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT)
p2->p_flag |= P_CONTROLT;
SESS_UNLOCK(p1->p_session);
- if (flags & RFPPWAIT)
+ if (fr->fr_flags & RFPPWAIT)
p2->p_flag |= P_PPWAIT;
p2->p_pgrp = p1->p_pgrp;
@@ -624,7 +633,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
* of init. This effectively disassociates the child from the
* parent.
*/
- if ((flags & RFNOWAIT) != 0) {
+ if ((fr->fr_flags & RFNOWAIT) != 0) {
pptr = p1->p_reaper;
p2->p_reaper = pptr;
} else {
@@ -652,13 +661,13 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
* Finish creating the child process. It will return via a different
* execution path later. (ie: directly into user mode)
*/
- vm_forkproc(td, p2, td2, vm2, flags);
+ vm_forkproc(td, p2, td2, vm2, fr->fr_flags);
- if (flags == (RFFDG | RFPROC)) {
+ if (fr->fr_flags == (RFFDG | RFPROC)) {
PCPU_INC(cnt.v_forks);
PCPU_ADD(cnt.v_forkpages, p2->p_vmspace->vm_dsize +
p2->p_vmspace->vm_ssize);
- } else if (flags == (RFFDG | RFPROC | RFPPWAIT | RFMEM)) {
+ } else if (fr->fr_flags == (RFFDG | RFPROC | RFPPWAIT | RFMEM)) {
PCPU_INC(cnt.v_vforks);
PCPU_ADD(cnt.v_vforkpages, p2->p_vmspace->vm_dsize +
p2->p_vmspace->vm_ssize);
@@ -677,14 +686,14 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
* can happen that might cause that process to need the descriptor.
* However, don't do this until after fork(2) can no longer fail.
*/
- if (flags & RFPROCDESC)
- procdesc_new(p2, pdflags);
+ if (fr->fr_flags & RFPROCDESC)
+ procdesc_new(p2, fr->fr_pd_flags);
/*
* Both processes are set up, now check if any loadable modules want
* to adjust anything.
*/
- EVENTHANDLER_INVOKE(process_fork, p1, p2, flags);
+ EVENTHANDLER_INVOKE(process_fork, p1, p2, fr->fr_flags);
/*
* Set the child start time and mark the process as being complete.
@@ -703,9 +712,14 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
* this only after p_state is PRS_NORMAL since the fasttrap module will
* use pfind() later on.
*/
- if ((flags & RFMEM) == 0 && dtrace_fasttrap_fork)
+ if ((fr->fr_flags & RFMEM) == 0 && dtrace_fasttrap_fork)
dtrace_fasttrap_fork(p1, p2);
#endif
+ /*
+ * Hold the process so that it cannot exit after we make it runnable,
+ * but before we wait for the debugger.
+ */
+ _PHOLD(p2);
if ((p1->p_flag & (P_TRACED | P_FOLLOWFORK)) == (P_TRACED |
P_FOLLOWFORK)) {
/*
@@ -718,24 +732,12 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
td->td_dbgflags |= TDB_FORK;
td->td_dbg_forked = p2->p_pid;
td2->td_dbgflags |= TDB_STOPATFORK;
- _PHOLD(p2);
- p2_held = 1;
}
- if (flags & RFPPWAIT) {
+ if (fr->fr_flags & RFPPWAIT) {
td->td_pflags |= TDP_RFPPWAIT;
td->td_rfppwait_p = p2;
}
PROC_UNLOCK(p2);
- if ((flags & RFSTOPPED) == 0) {
- /*
- * If RFSTOPPED not requested, make child runnable and
- * add to run queue.
- */
- thread_lock(td2);
- TD_SET_CAN_RUN(td2);
- sched_add(td2, SRQ_BORING);
- thread_unlock(td2);
- }
/*
* Now can be swapped.
@@ -747,22 +749,41 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
* Tell any interested parties about the new process.
*/
knote_fork(&p1->p_klist, p2->p_pid);
- SDT_PROBE3(proc, , , create, p2, p1, flags);
+ SDT_PROBE3(proc, , , create, p2, p1, fr->fr_flags);
+ if (fr->fr_flags & RFPROCDESC) {
+ procdesc_finit(p2->p_procdesc, fp_procdesc);
+ fdrop(fp_procdesc, td);
+ }
+
+ if ((fr->fr_flags & RFSTOPPED) == 0) {
+ /*
+ * If RFSTOPPED not requested, make child runnable and
+ * add to run queue.
+ */
+ thread_lock(td2);
+ TD_SET_CAN_RUN(td2);
+ sched_add(td2, SRQ_BORING);
+ thread_unlock(td2);
+ if (fr->fr_pidp != NULL)
+ *fr->fr_pidp = p2->p_pid;
+ } else {
+ *fr->fr_procp = p2;
+ }
+
+ PROC_LOCK(p2);
/*
* Wait until debugger is attached to child.
*/
- PROC_LOCK(p2);
- while ((td2->td_dbgflags & TDB_STOPATFORK) != 0)
+ while (td2->td_proc == p2 && (td2->td_dbgflags & TDB_STOPATFORK) != 0)
cv_wait(&p2->p_dbgwait, &p2->p_mtx);
- if (p2_held)
- _PRELE(p2);
+ _PRELE(p2);
+ racct_proc_fork_done(p2);
PROC_UNLOCK(p2);
}
int
-fork1(struct thread *td, int flags, int pages, struct proc **procp,
- int *procdescp, int pdflags, struct filecaps *fcaps)
+fork1(struct thread *td, struct fork_req *fr)
{
struct proc *p1, *newproc;
struct thread *td2;
@@ -772,6 +793,15 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
int error, nprocs_new, ok;
static int curfail;
static struct timeval lastfail;
+ int flags, pages;
+
+ flags = fr->fr_flags;
+ pages = fr->fr_pages;
+
+ if ((flags & RFSTOPPED) != 0)
+ MPASS(fr->fr_procp != NULL && fr->fr_pidp == NULL);
+ else
+ MPASS(fr->fr_procp == NULL);
/* Check for the undefined or unimplemented flags. */
if ((flags & ~(RFFLAGS | RFTSIGFLAGS(RFTSIGMASK))) != 0)
@@ -795,7 +825,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
return (EINVAL);
/* Must provide a place to put a procdesc if creating one. */
- if (procdescp == NULL)
+ if (fr->fr_pd_fd == NULL)
return (EINVAL);
}
@@ -806,7 +836,10 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
* certain parts of a process from itself.
*/
if ((flags & RFPROC) == 0) {
- *procp = NULL;
+ if (fr->fr_procp != NULL)
+ *fr->fr_procp = NULL;
+ else if (fr->fr_pidp != NULL)
+ *fr->fr_pidp = 0;
return (fork_norfproc(td, flags));
}
@@ -845,7 +878,8 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
* later.
*/
if (flags & RFPROCDESC) {
- error = falloc_caps(td, &fp_procdesc, procdescp, 0, fcaps);
+ error = falloc_caps(td, &fp_procdesc, fr->fr_pd_fd, 0,
+ fr->fr_pd_fcaps);
if (error != 0)
goto fail2;
}
@@ -933,17 +967,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
lim_cur(td, RLIMIT_NPROC));
}
if (ok) {
- do_fork(td, flags, newproc, td2, vm2, pdflags);
-
- /*
- * Return child proc pointer to parent.
- */
- *procp = newproc;
- if (flags & RFPROCDESC) {
- procdesc_finit(newproc->p_procdesc, fp_procdesc);
- fdrop(fp_procdesc, td);
- }
- racct_proc_fork_done(newproc);
+ do_fork(td, fr, newproc, td2, vm2, fp_procdesc);
return (0);
}
@@ -962,7 +986,7 @@ fail2:
vmspace_free(vm2);
uma_zfree(proc_zone, newproc);
if ((flags & RFPROCDESC) != 0 && fp_procdesc != NULL) {
- fdclose(td, fp_procdesc, *procdescp);
+ fdclose(td, fp_procdesc, *fr->fr_pd_fd);
fdrop(fp_procdesc, td);
}
atomic_add_int(&nprocs, -1);
diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c
index 2072dc726b08..9cca255fef91 100644
--- a/sys/kern/kern_kthread.c
+++ b/sys/kern/kern_kthread.c
@@ -80,6 +80,7 @@ int
kproc_create(void (*func)(void *), void *arg,
struct proc **newpp, int flags, int pages, const char *fmt, ...)
{
+ struct fork_req fr;
int error;
va_list ap;
struct thread *td;
@@ -88,8 +89,11 @@ kproc_create(void (*func)(void *), void *arg,
if (!proc0.p_stats)
panic("kproc_create called too soon");
- error = fork1(&thread0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags,
- pages, &p2, NULL, 0, NULL);
+ bzero(&fr, sizeof(fr));
+ fr.fr_flags = RFMEM | RFFDG | RFPROC | RFSTOPPED | flags;
+ fr.fr_pages = pages;
+ fr.fr_procp = &p2;
+ error = fork1(&thread0, &fr);
if (error)
return error;
diff --git a/sys/kern/kern_ktr.c b/sys/kern/kern_ktr.c
index 6885706e4c06..1af3b94f55d4 100644
--- a/sys/kern/kern_ktr.c
+++ b/sys/kern/kern_ktr.c
@@ -419,7 +419,7 @@ DB_SHOW_COMMAND(ktr, db_ktr_all)
db_ktr_verbose |= (strchr(modif, 'V') != NULL) ? 1 : 0; /* just timestap please */
if (strchr(modif, 'a') != NULL) {
db_disable_pager();
- while (cncheckc() != -1)
+ while (cncheckc() == -1)
if (db_mach_vtrace() == 0)
break;
} else {
diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c
index e7c81d67e936..f7c67f2d7610 100644
--- a/sys/kern/kern_malloc.c
+++ b/sys/kern/kern_malloc.c
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/sbuf.h>
#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
#include <sys/time.h>
#include <sys/vmem.h>
diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c
index a864c946873c..55964398b6a1 100644
--- a/sys/kern/kern_mbuf.c
+++ b/sys/kern/kern_mbuf.c
@@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_page.h>
#include <vm/vm_map.h>
#include <vm/uma.h>
-#include <vm/uma_int.h>
#include <vm/uma_dbg.h>
/*
@@ -275,12 +274,6 @@ uma_zone_t zone_jumbo16;
uma_zone_t zone_ext_refcnt;
/*
- * Callout to assist us in freeing mbufs.
- */
-static struct callout mb_reclaim_callout;
-static struct mtx mb_reclaim_callout_mtx;
-
-/*
* Local prototypes.
*/
static int mb_ctor_mbuf(void *, int, void *, int);
@@ -292,9 +285,8 @@ static void mb_dtor_pack(void *, int, void *);
static int mb_zinit_pack(void *, int, int);
static void mb_zfini_pack(void *, int);
-static void mb_reclaim(void *);
+static void mb_reclaim(uma_zone_t, int);
static void *mbuf_jumbo_alloc(uma_zone_t, vm_size_t, uint8_t *, int);
-static void mb_maxaction(uma_zone_t);
/* Ensure that MSIZE is a power of 2. */
CTASSERT((((MSIZE - 1) ^ MSIZE) + 1) >> 1 == MSIZE);
@@ -320,7 +312,7 @@ mbuf_init(void *dummy)
if (nmbufs > 0)
nmbufs = uma_zone_set_max(zone_mbuf, nmbufs);
uma_zone_set_warning(zone_mbuf, "kern.ipc.nmbufs limit reached");
- uma_zone_set_maxaction(zone_mbuf, mb_maxaction);
+ uma_zone_set_maxaction(zone_mbuf, mb_reclaim);
zone_clust = uma_zcreate(MBUF_CLUSTER_MEM_NAME, MCLBYTES,
mb_ctor_clust, mb_dtor_clust,
@@ -333,7 +325,7 @@ mbuf_init(void *dummy)
if (nmbclusters > 0)
nmbclusters = uma_zone_set_max(zone_clust, nmbclusters);
uma_zone_set_warning(zone_clust, "kern.ipc.nmbclusters limit reached");
- uma_zone_set_maxaction(zone_clust, mb_maxaction);
+ uma_zone_set_maxaction(zone_clust, mb_reclaim);
zone_pack = uma_zsecond_create(MBUF_PACKET_MEM_NAME, mb_ctor_pack,
mb_dtor_pack, mb_zinit_pack, mb_zfini_pack, zone_mbuf);
@@ -350,7 +342,7 @@ mbuf_init(void *dummy)
if (nmbjumbop > 0)
nmbjumbop = uma_zone_set_max(zone_jumbop, nmbjumbop);
uma_zone_set_warning(zone_jumbop, "kern.ipc.nmbjumbop limit reached");
- uma_zone_set_maxaction(zone_jumbop, mb_maxaction);
+ uma_zone_set_maxaction(zone_jumbop, mb_reclaim);
zone_jumbo9 = uma_zcreate(MBUF_JUMBO9_MEM_NAME, MJUM9BYTES,
mb_ctor_clust, mb_dtor_clust,
@@ -364,7 +356,7 @@ mbuf_init(void *dummy)
if (nmbjumbo9 > 0)
nmbjumbo9 = uma_zone_set_max(zone_jumbo9, nmbjumbo9);
uma_zone_set_warning(zone_jumbo9, "kern.ipc.nmbjumbo9 limit reached");
- uma_zone_set_maxaction(zone_jumbo9, mb_maxaction);
+ uma_zone_set_maxaction(zone_jumbo9, mb_reclaim);
zone_jumbo16 = uma_zcreate(MBUF_JUMBO16_MEM_NAME, MJUM16BYTES,
mb_ctor_clust, mb_dtor_clust,
@@ -378,20 +370,13 @@ mbuf_init(void *dummy)
if (nmbjumbo16 > 0)
nmbjumbo16 = uma_zone_set_max(zone_jumbo16, nmbjumbo16);
uma_zone_set_warning(zone_jumbo16, "kern.ipc.nmbjumbo16 limit reached");
- uma_zone_set_maxaction(zone_jumbo16, mb_maxaction);
+ uma_zone_set_maxaction(zone_jumbo16, mb_reclaim);
zone_ext_refcnt = uma_zcreate(MBUF_EXTREFCNT_MEM_NAME, sizeof(u_int),
NULL, NULL,
NULL, NULL,
UMA_ALIGN_PTR, UMA_ZONE_ZINIT);
- /* uma_prealloc() goes here... */
-
- /* Initialize the mb_reclaim() callout. */
- mtx_init(&mb_reclaim_callout_mtx, "mb_reclaim_callout_mtx", NULL,
- MTX_DEF);
- callout_init(&mb_reclaim_callout, 1);
-
/*
* Hook event handler for low-memory situation, used to
* drain protocols and push data back to the caches (UMA
@@ -678,81 +663,23 @@ m_pkthdr_init(struct mbuf *m, int how)
}
/*
- * This is the protocol drain routine.
+ * This is the protocol drain routine. Called by UMA whenever any of the
+ * mbuf zones is closed to its limit.
*
* No locks should be held when this is called. The drain routines have to
* presently acquire some locks which raises the possibility of lock order
* reversal.
*/
static void
-mb_reclaim(void *junk)
+mb_reclaim(uma_zone_t zone __unused, int pending __unused)
{
struct domain *dp;
struct protosw *pr;
- WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK | WARN_PANIC, NULL,
- "mb_reclaim()");
+ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK | WARN_PANIC, NULL, __func__);
for (dp = domains; dp != NULL; dp = dp->dom_next)
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
if (pr->pr_drain != NULL)
(*pr->pr_drain)();
}
-
-/*
- * This is the function called by the mb_reclaim_callout, which is
- * used when we hit the maximum for a zone.
- *
- * (See mb_maxaction() below.)
- */
-static void
-mb_reclaim_timer(void *junk __unused)
-{
-
- mtx_lock(&mb_reclaim_callout_mtx);
-
- /*
- * Avoid running this function extra times by skipping this invocation
- * if the callout has already been rescheduled.
- */
- if (callout_pending(&mb_reclaim_callout) ||
- !callout_active(&mb_reclaim_callout)) {
- mtx_unlock(&mb_reclaim_callout_mtx);
- return;
- }
- mtx_unlock(&mb_reclaim_callout_mtx);
-
- mb_reclaim(NULL);
-
- mtx_lock(&mb_reclaim_callout_mtx);
- callout_deactivate(&mb_reclaim_callout);
- mtx_unlock(&mb_reclaim_callout_mtx);
-}
-
-/*
- * This function is called when we hit the maximum for a zone.
- *
- * At that point, we want to call the protocol drain routine to free up some
- * mbufs. However, we will use the callout routines to schedule this to
- * occur in another thread. (The thread calling this function holds the
- * zone lock.)
- */
-static void
-mb_maxaction(uma_zone_t zone __unused)
-{
-
- /*
- * If we can't immediately obtain the lock, either the callout
- * is currently running, or another thread is scheduling the
- * callout.
- */
- if (!mtx_trylock(&mb_reclaim_callout_mtx))
- return;
-
- /* If not already scheduled/running, schedule the callout. */
- if (!callout_active(&mb_reclaim_callout)) {
- callout_reset(&mb_reclaim_callout, 1, mb_reclaim_timer, NULL);
- }
-
- mtx_unlock(&mb_reclaim_callout_mtx);
-}
diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c
index 0c7c0c444382..ce7e2a4d92c8 100644
--- a/sys/kern/kern_racct.c
+++ b/sys/kern/kern_racct.c
@@ -957,16 +957,15 @@ void
racct_proc_fork_done(struct proc *child)
{
+ PROC_LOCK_ASSERT(child, MA_OWNED);
#ifdef RCTL
if (!racct_enable)
return;
- PROC_LOCK(child);
mtx_lock(&racct_lock);
rctl_enforce(child, RACCT_NPROC, 0);
rctl_enforce(child, RACCT_NTHR, 0);
mtx_unlock(&racct_lock);
- PROC_UNLOCK(child);
#endif
}
diff --git a/sys/kern/subr_mchain.c b/sys/kern/subr_mchain.c
index e9d7d22129b4..233a78aac706 100644
--- a/sys/kern/subr_mchain.c
+++ b/sys/kern/subr_mchain.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/endian.h>
#include <sys/errno.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/uio.h>
diff --git a/sys/kern/uipc_debug.c b/sys/kern/uipc_debug.c
index caecad9bac84..7c8b93cdbd92 100644
--- a/sys/kern/uipc_debug.c
+++ b/sys/kern/uipc_debug.c
@@ -461,9 +461,9 @@ db_print_socket(struct socket *so, const char *socketname, int indent)
db_print_indent(indent);
/* so_list skipped */
- db_printf("so_qlen: %d ", so->so_qlen);
- db_printf("so_incqlen: %d ", so->so_incqlen);
- db_printf("so_qlimit: %d ", so->so_qlimit);
+ db_printf("so_qlen: %u ", so->so_qlen);
+ db_printf("so_incqlen: %u ", so->so_incqlen);
+ db_printf("so_qlimit: %u ", so->so_qlimit);
db_printf("so_timeo: %d ", so->so_timeo);
db_printf("so_error: %d\n", so->so_error);
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index ba77fcaca92a..edf03a3b51fc 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/aio.h> /* for aio_swake proto */
#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/proc.h>
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 350ca3cdd0b0..5d2247fddb1d 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -196,7 +196,7 @@ VNET_DEFINE(struct hhook_head *, socket_hhh[HHOOK_SOCKET_LAST + 1]);
* NB: The orginal sysctl somaxconn is still available but hidden
* to prevent confusion about the actual purpose of this number.
*/
-static int somaxconn = SOMAXCONN;
+static u_int somaxconn = SOMAXCONN;
static int
sysctl_somaxconn(SYSCTL_HANDLER_ARGS)
@@ -209,7 +209,13 @@ sysctl_somaxconn(SYSCTL_HANDLER_ARGS)
if (error || !req->newptr )
return (error);
- if (val < 1 || val > USHRT_MAX)
+ /*
+ * The purpose of the UINT_MAX / 3 limit, is so that the formula
+ * 3 * so_qlimit / 2
+ * below, will not overflow.
+ */
+
+ if (val < 1 || val > UINT_MAX / 3)
return (EINVAL);
somaxconn = val;
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index 14a66c3bb7d7..5b2083c65312 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -196,7 +196,7 @@ typedef struct oaiocb {
} oaiocb_t;
/*
- * Below is a key of locks used to protect each member of struct aiocblist
+ * Below is a key of locks used to protect each member of struct kaiocb
* aioliojob and kaioinfo and any backends.
*
* * - need not protected
@@ -219,10 +219,10 @@ typedef struct oaiocb {
* daemons.
*/
-struct aiocblist {
- TAILQ_ENTRY(aiocblist) list; /* (b) internal list of for backend */
- TAILQ_ENTRY(aiocblist) plist; /* (a) list of jobs for each backend */
- TAILQ_ENTRY(aiocblist) allist; /* (a) list of all jobs in proc */
+struct kaiocb {
+ TAILQ_ENTRY(kaiocb) list; /* (b) internal list of for backend */
+ TAILQ_ENTRY(kaiocb) plist; /* (a) list of jobs for each backend */
+ TAILQ_ENTRY(kaiocb) allist; /* (a) list of all jobs in proc */
int jobflags; /* (a) job flags */
int jobstate; /* (b) job state */
int inputcharge; /* (*) input blockes */
@@ -235,7 +235,7 @@ struct aiocblist {
struct ucred *cred; /* (*) active credential when created */
struct file *fd_file; /* (*) pointer to file structure */
struct aioliojob *lio; /* (*) optional lio job */
- struct aiocb *uuaiocb; /* (*) pointer in userspace of aiocb */
+ struct aiocb *ujob; /* (*) pointer in userspace of aiocb */
struct knlist klist; /* (a) list of knotes */
struct aiocb uaiocb; /* (*) kernel I/O control block */
ksiginfo_t ksi; /* (a) realtime signal info */
@@ -244,10 +244,10 @@ struct aiocblist {
};
/* jobflags */
-#define AIOCBLIST_DONE 0x01
-#define AIOCBLIST_BUFDONE 0x02
-#define AIOCBLIST_RUNDOWN 0x04
-#define AIOCBLIST_CHECKSYNC 0x08
+#define KAIOCB_DONE 0x01
+#define KAIOCB_BUFDONE 0x02
+#define KAIOCB_RUNDOWN 0x04
+#define KAIOCB_CHECKSYNC 0x08
/*
* AIO process info
@@ -289,12 +289,12 @@ struct kaioinfo {
int kaio_count; /* (a) size of AIO queue */
int kaio_ballowed_count; /* (*) maximum number of buffers */
int kaio_buffer_count; /* (a) number of physio buffers */
- TAILQ_HEAD(,aiocblist) kaio_all; /* (a) all AIOs in a process */
- TAILQ_HEAD(,aiocblist) kaio_done; /* (a) done queue for process */
+ TAILQ_HEAD(,kaiocb) kaio_all; /* (a) all AIOs in a process */
+ TAILQ_HEAD(,kaiocb) kaio_done; /* (a) done queue for process */
TAILQ_HEAD(,aioliojob) kaio_liojoblist; /* (a) list of lio jobs */
- TAILQ_HEAD(,aiocblist) kaio_jobqueue; /* (a) job queue for process */
- TAILQ_HEAD(,aiocblist) kaio_bufqueue; /* (a) buffer job queue */
- TAILQ_HEAD(,aiocblist) kaio_syncqueue; /* (a) queue for aio_fsync */
+ TAILQ_HEAD(,kaiocb) kaio_jobqueue; /* (a) job queue for process */
+ TAILQ_HEAD(,kaiocb) kaio_bufqueue; /* (a) buffer job queue */
+ TAILQ_HEAD(,kaiocb) kaio_syncqueue; /* (a) queue for aio_fsync */
struct task kaio_task; /* (*) task to kick aio processes */
};
@@ -323,28 +323,28 @@ struct aiocb_ops {
static TAILQ_HEAD(,aioproc) aio_freeproc; /* (c) Idle daemons */
static struct sema aio_newproc_sem;
static struct mtx aio_job_mtx;
-static TAILQ_HEAD(,aiocblist) aio_jobs; /* (c) Async job list */
+static TAILQ_HEAD(,kaiocb) aio_jobs; /* (c) Async job list */
static struct unrhdr *aiod_unr;
void aio_init_aioinfo(struct proc *p);
static int aio_onceonly(void);
-static int aio_free_entry(struct aiocblist *aiocbe);
-static void aio_process_rw(struct aiocblist *aiocbe);
-static void aio_process_sync(struct aiocblist *aiocbe);
-static void aio_process_mlock(struct aiocblist *aiocbe);
+static int aio_free_entry(struct kaiocb *job);
+static void aio_process_rw(struct kaiocb *job);
+static void aio_process_sync(struct kaiocb *job);
+static void aio_process_mlock(struct kaiocb *job);
static int aio_newproc(int *);
-int aio_aqueue(struct thread *td, struct aiocb *job,
+int aio_aqueue(struct thread *td, struct aiocb *ujob,
struct aioliojob *lio, int type, struct aiocb_ops *ops);
static void aio_physwakeup(struct bio *bp);
static void aio_proc_rundown(void *arg, struct proc *p);
static void aio_proc_rundown_exec(void *arg, struct proc *p,
struct image_params *imgp);
-static int aio_qphysio(struct proc *p, struct aiocblist *iocb);
+static int aio_qphysio(struct proc *p, struct kaiocb *job);
static void aio_daemon(void *param);
static void aio_swake_cb(struct socket *, struct sockbuf *);
static int aio_unload(void);
-static void aio_bio_done_notify(struct proc *userp,
- struct aiocblist *aiocbe, int type);
+static void aio_bio_done_notify(struct proc *userp, struct kaiocb *job,
+ int type);
#define DONE_BUF 1
#define DONE_QUEUE 2
static int aio_kick(struct proc *userp);
@@ -488,7 +488,7 @@ aio_onceonly(void)
NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
aiop_zone = uma_zcreate("AIOP", sizeof(struct aioproc), NULL,
NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
- aiocb_zone = uma_zcreate("AIOCB", sizeof(struct aiocblist), NULL, NULL,
+ aiocb_zone = uma_zcreate("AIOCB", sizeof(struct kaiocb), NULL, NULL,
NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
aiol_zone = uma_zcreate("AIOL", AIO_LISTIO_MAX*sizeof(intptr_t) , NULL,
NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
@@ -625,29 +625,29 @@ aio_sendsig(struct proc *p, struct sigevent *sigev, ksiginfo_t *ksi)
* restart the queue scan.
*/
static int
-aio_free_entry(struct aiocblist *aiocbe)
+aio_free_entry(struct kaiocb *job)
{
struct kaioinfo *ki;
struct aioliojob *lj;
struct proc *p;
- p = aiocbe->userproc;
+ p = job->userproc;
MPASS(curproc == p);
ki = p->p_aioinfo;
MPASS(ki != NULL);
AIO_LOCK_ASSERT(ki, MA_OWNED);
- MPASS(aiocbe->jobstate == JOBST_JOBFINISHED);
+ MPASS(job->jobstate == JOBST_JOBFINISHED);
atomic_subtract_int(&num_queue_count, 1);
ki->kaio_count--;
MPASS(ki->kaio_count >= 0);
- TAILQ_REMOVE(&ki->kaio_done, aiocbe, plist);
- TAILQ_REMOVE(&ki->kaio_all, aiocbe, allist);
+ TAILQ_REMOVE(&ki->kaio_done, job, plist);
+ TAILQ_REMOVE(&ki->kaio_all, job, allist);
- lj = aiocbe->lio;
+ lj = job->lio;
if (lj) {
lj->lioj_count--;
lj->lioj_finished_count--;
@@ -663,14 +663,14 @@ aio_free_entry(struct aiocblist *aiocbe)
}
}
- /* aiocbe is going away, we need to destroy any knotes */
- knlist_delete(&aiocbe->klist, curthread, 1);
+ /* job is going away, we need to destroy any knotes */
+ knlist_delete(&job->klist, curthread, 1);
PROC_LOCK(p);
- sigqueue_take(&aiocbe->ksi);
+ sigqueue_take(&job->ksi);
PROC_UNLOCK(p);
- MPASS(aiocbe->bp == NULL);
- aiocbe->jobstate = JOBST_NULL;
+ MPASS(job->bp == NULL);
+ job->jobstate = JOBST_NULL;
AIO_UNLOCK(ki);
/*
@@ -682,7 +682,7 @@ aio_free_entry(struct aiocblist *aiocbe)
* another process.
*
* Currently, all the callers of this function call it to remove
- * an aiocblist from the current process' job list either via a
+ * a kaiocb from the current process' job list either via a
* syscall or due to the current process calling exit() or
* execve(). Thus, we know that p == curproc. We also know that
* curthread can't exit since we are curthread.
@@ -693,10 +693,10 @@ aio_free_entry(struct aiocblist *aiocbe)
* at open time, but this is already true of file descriptors in
* a multithreaded process.
*/
- if (aiocbe->fd_file)
- fdrop(aiocbe->fd_file, curthread);
- crfree(aiocbe->cred);
- uma_zfree(aiocb_zone, aiocbe);
+ if (job->fd_file)
+ fdrop(job->fd_file, curthread);
+ crfree(job->cred);
+ uma_zfree(aiocb_zone, job);
AIO_LOCK(ki);
return (0);
@@ -717,7 +717,7 @@ aio_proc_rundown(void *arg, struct proc *p)
{
struct kaioinfo *ki;
struct aioliojob *lj;
- struct aiocblist *cbe, *cbn;
+ struct kaiocb *job, *jobn;
struct file *fp;
struct socket *so;
int remove;
@@ -737,30 +737,30 @@ restart:
* Try to cancel all pending requests. This code simulates
* aio_cancel on all pending I/O requests.
*/
- TAILQ_FOREACH_SAFE(cbe, &ki->kaio_jobqueue, plist, cbn) {
+ TAILQ_FOREACH_SAFE(job, &ki->kaio_jobqueue, plist, jobn) {
remove = 0;
mtx_lock(&aio_job_mtx);
- if (cbe->jobstate == JOBST_JOBQGLOBAL) {
- TAILQ_REMOVE(&aio_jobs, cbe, list);
+ if (job->jobstate == JOBST_JOBQGLOBAL) {
+ TAILQ_REMOVE(&aio_jobs, job, list);
remove = 1;
- } else if (cbe->jobstate == JOBST_JOBQSOCK) {
- fp = cbe->fd_file;
+ } else if (job->jobstate == JOBST_JOBQSOCK) {
+ fp = job->fd_file;
MPASS(fp->f_type == DTYPE_SOCKET);
so = fp->f_data;
- TAILQ_REMOVE(&so->so_aiojobq, cbe, list);
+ TAILQ_REMOVE(&so->so_aiojobq, job, list);
remove = 1;
- } else if (cbe->jobstate == JOBST_JOBQSYNC) {
- TAILQ_REMOVE(&ki->kaio_syncqueue, cbe, list);
+ } else if (job->jobstate == JOBST_JOBQSYNC) {
+ TAILQ_REMOVE(&ki->kaio_syncqueue, job, list);
remove = 1;
}
mtx_unlock(&aio_job_mtx);
if (remove) {
- cbe->jobstate = JOBST_JOBFINISHED;
- cbe->uaiocb._aiocb_private.status = -1;
- cbe->uaiocb._aiocb_private.error = ECANCELED;
- TAILQ_REMOVE(&ki->kaio_jobqueue, cbe, plist);
- aio_bio_done_notify(p, cbe, DONE_QUEUE);
+ job->jobstate = JOBST_JOBFINISHED;
+ job->uaiocb._aiocb_private.status = -1;
+ job->uaiocb._aiocb_private.error = ECANCELED;
+ TAILQ_REMOVE(&ki->kaio_jobqueue, job, plist);
+ aio_bio_done_notify(p, job, DONE_QUEUE);
}
}
@@ -773,8 +773,8 @@ restart:
}
/* Free all completed I/O requests. */
- while ((cbe = TAILQ_FIRST(&ki->kaio_done)) != NULL)
- aio_free_entry(cbe);
+ while ((job = TAILQ_FIRST(&ki->kaio_done)) != NULL)
+ aio_free_entry(job);
while ((lj = TAILQ_FIRST(&ki->kaio_liojoblist)) != NULL) {
if (lj->lioj_count == 0) {
@@ -799,27 +799,27 @@ restart:
/*
* Select a job to run (called by an AIO daemon).
*/
-static struct aiocblist *
+static struct kaiocb *
aio_selectjob(struct aioproc *aiop)
{
- struct aiocblist *aiocbe;
+ struct kaiocb *job;
struct kaioinfo *ki;
struct proc *userp;
mtx_assert(&aio_job_mtx, MA_OWNED);
- TAILQ_FOREACH(aiocbe, &aio_jobs, list) {
- userp = aiocbe->userproc;
+ TAILQ_FOREACH(job, &aio_jobs, list) {
+ userp = job->userproc;
ki = userp->p_aioinfo;
if (ki->kaio_active_count < ki->kaio_maxactive_count) {
- TAILQ_REMOVE(&aio_jobs, aiocbe, list);
+ TAILQ_REMOVE(&aio_jobs, job, list);
/* Account for currently active jobs. */
ki->kaio_active_count++;
- aiocbe->jobstate = JOBST_JOBRUNNING;
+ job->jobstate = JOBST_JOBRUNNING;
break;
}
}
- return (aiocbe);
+ return (job);
}
/*
@@ -857,7 +857,7 @@ drop:
* XXX I don't think it works well for socket, pipe, and fifo.
*/
static void
-aio_process_rw(struct aiocblist *aiocbe)
+aio_process_rw(struct kaiocb *job)
{
struct ucred *td_savedcred;
struct thread *td;
@@ -871,15 +871,15 @@ aio_process_rw(struct aiocblist *aiocbe)
int oublock_st, oublock_end;
int inblock_st, inblock_end;
- KASSERT(aiocbe->uaiocb.aio_lio_opcode == LIO_READ ||
- aiocbe->uaiocb.aio_lio_opcode == LIO_WRITE,
- ("%s: opcode %d", __func__, aiocbe->uaiocb.aio_lio_opcode));
+ KASSERT(job->uaiocb.aio_lio_opcode == LIO_READ ||
+ job->uaiocb.aio_lio_opcode == LIO_WRITE,
+ ("%s: opcode %d", __func__, job->uaiocb.aio_lio_opcode));
td = curthread;
td_savedcred = td->td_ucred;
- td->td_ucred = aiocbe->cred;
- cb = &aiocbe->uaiocb;
- fp = aiocbe->fd_file;
+ td->td_ucred = job->cred;
+ cb = &job->uaiocb;
+ fp = job->fd_file;
aiov.iov_base = (void *)(uintptr_t)cb->aio_buf;
aiov.iov_len = cb->aio_nbytes;
@@ -913,8 +913,8 @@ aio_process_rw(struct aiocblist *aiocbe)
inblock_end = td->td_ru.ru_inblock;
oublock_end = td->td_ru.ru_oublock;
- aiocbe->inputcharge = inblock_end - inblock_st;
- aiocbe->outputcharge = oublock_end - oublock_st;
+ job->inputcharge = inblock_end - inblock_st;
+ job->outputcharge = oublock_end - oublock_st;
if ((error) && (auio.uio_resid != cnt)) {
if (error == ERESTART || error == EINTR || error == EWOULDBLOCK)
@@ -927,9 +927,9 @@ aio_process_rw(struct aiocblist *aiocbe)
sigpipe = 0;
}
if (sigpipe) {
- PROC_LOCK(aiocbe->userproc);
- kern_psignal(aiocbe->userproc, SIGPIPE);
- PROC_UNLOCK(aiocbe->userproc);
+ PROC_LOCK(job->userproc);
+ kern_psignal(job->userproc, SIGPIPE);
+ PROC_UNLOCK(job->userproc);
}
}
}
@@ -941,18 +941,18 @@ aio_process_rw(struct aiocblist *aiocbe)
}
static void
-aio_process_sync(struct aiocblist *aiocbe)
+aio_process_sync(struct kaiocb *job)
{
struct thread *td = curthread;
struct ucred *td_savedcred = td->td_ucred;
- struct aiocb *cb = &aiocbe->uaiocb;
- struct file *fp = aiocbe->fd_file;
+ struct aiocb *cb = &job->uaiocb;
+ struct file *fp = job->fd_file;
int error = 0;
- KASSERT(aiocbe->uaiocb.aio_lio_opcode == LIO_SYNC,
- ("%s: opcode %d", __func__, aiocbe->uaiocb.aio_lio_opcode));
+ KASSERT(job->uaiocb.aio_lio_opcode == LIO_SYNC,
+ ("%s: opcode %d", __func__, job->uaiocb.aio_lio_opcode));
- td->td_ucred = aiocbe->cred;
+ td->td_ucred = job->cred;
if (fp->f_vnode != NULL)
error = aio_fsync_vnode(td, fp->f_vnode);
cb->_aiocb_private.error = error;
@@ -961,31 +961,31 @@ aio_process_sync(struct aiocblist *aiocbe)
}
static void
-aio_process_mlock(struct aiocblist *aiocbe)
+aio_process_mlock(struct kaiocb *job)
{
- struct aiocb *cb = &aiocbe->uaiocb;
+ struct aiocb *cb = &job->uaiocb;
int error;
- KASSERT(aiocbe->uaiocb.aio_lio_opcode == LIO_MLOCK,
- ("%s: opcode %d", __func__, aiocbe->uaiocb.aio_lio_opcode));
+ KASSERT(job->uaiocb.aio_lio_opcode == LIO_MLOCK,
+ ("%s: opcode %d", __func__, job->uaiocb.aio_lio_opcode));
- error = vm_mlock(aiocbe->userproc, aiocbe->cred,
+ error = vm_mlock(job->userproc, job->cred,
__DEVOLATILE(void *, cb->aio_buf), cb->aio_nbytes);
cb->_aiocb_private.error = error;
cb->_aiocb_private.status = 0;
}
static void
-aio_bio_done_notify(struct proc *userp, struct aiocblist *aiocbe, int type)
+aio_bio_done_notify(struct proc *userp, struct kaiocb *job, int type)
{
struct aioliojob *lj;
struct kaioinfo *ki;
- struct aiocblist *scb, *scbn;
+ struct kaiocb *sjob, *sjobn;
int lj_done;
ki = userp->p_aioinfo;
AIO_LOCK_ASSERT(ki, MA_OWNED);
- lj = aiocbe->lio;
+ lj = job->lio;
lj_done = 0;
if (lj) {
lj->lioj_finished_count++;
@@ -993,21 +993,21 @@ aio_bio_done_notify(struct proc *userp, struct aiocblist *aiocbe, int type)
lj_done = 1;
}
if (type == DONE_QUEUE) {
- aiocbe->jobflags |= AIOCBLIST_DONE;
+ job->jobflags |= KAIOCB_DONE;
} else {
- aiocbe->jobflags |= AIOCBLIST_BUFDONE;
+ job->jobflags |= KAIOCB_BUFDONE;
}
- TAILQ_INSERT_TAIL(&ki->kaio_done, aiocbe, plist);
- aiocbe->jobstate = JOBST_JOBFINISHED;
+ TAILQ_INSERT_TAIL(&ki->kaio_done, job, plist);
+ job->jobstate = JOBST_JOBFINISHED;
if (ki->kaio_flags & KAIO_RUNDOWN)
goto notification_done;
- if (aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL ||
- aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID)
- aio_sendsig(userp, &aiocbe->uaiocb.aio_sigevent, &aiocbe->ksi);
+ if (job->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL ||
+ job->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID)
+ aio_sendsig(userp, &job->uaiocb.aio_sigevent, &job->ksi);
- KNOTE_LOCKED(&aiocbe->klist, 1);
+ KNOTE_LOCKED(&job->klist, 1);
if (lj_done) {
if (lj->lioj_signal.sigev_notify == SIGEV_KEVENT) {
@@ -1024,16 +1024,16 @@ aio_bio_done_notify(struct proc *userp, struct aiocblist *aiocbe, int type)
}
notification_done:
- if (aiocbe->jobflags & AIOCBLIST_CHECKSYNC) {
- TAILQ_FOREACH_SAFE(scb, &ki->kaio_syncqueue, list, scbn) {
- if (aiocbe->fd_file == scb->fd_file &&
- aiocbe->seqno < scb->seqno) {
- if (--scb->pending == 0) {
+ if (job->jobflags & KAIOCB_CHECKSYNC) {
+ TAILQ_FOREACH_SAFE(sjob, &ki->kaio_syncqueue, list, sjobn) {
+ if (job->fd_file == sjob->fd_file &&
+ job->seqno < sjob->seqno) {
+ if (--sjob->pending == 0) {
mtx_lock(&aio_job_mtx);
- scb->jobstate = JOBST_JOBQGLOBAL;
- TAILQ_REMOVE(&ki->kaio_syncqueue, scb,
+ sjob->jobstate = JOBST_JOBQGLOBAL;
+ TAILQ_REMOVE(&ki->kaio_syncqueue, sjob,
list);
- TAILQ_INSERT_TAIL(&aio_jobs, scb, list);
+ TAILQ_INSERT_TAIL(&aio_jobs, sjob, list);
aio_kick_nowait(userp);
mtx_unlock(&aio_job_mtx);
}
@@ -1047,10 +1047,10 @@ notification_done:
}
static void
-aio_switch_vmspace(struct aiocblist *aiocbe)
+aio_switch_vmspace(struct kaiocb *job)
{
- vmspace_switch_aio(aiocbe->userproc->p_vmspace);
+ vmspace_switch_aio(job->userproc->p_vmspace);
}
/*
@@ -1060,7 +1060,7 @@ aio_switch_vmspace(struct aiocblist *aiocbe)
static void
aio_daemon(void *_id)
{
- struct aiocblist *aiocbe;
+ struct kaiocb *job;
struct aioproc *aiop;
struct kaioinfo *ki;
struct proc *p, *userp;
@@ -1105,28 +1105,28 @@ aio_daemon(void *_id)
/*
* Check for jobs.
*/
- while ((aiocbe = aio_selectjob(aiop)) != NULL) {
+ while ((job = aio_selectjob(aiop)) != NULL) {
mtx_unlock(&aio_job_mtx);
- userp = aiocbe->userproc;
+ userp = job->userproc;
/*
* Connect to process address space for user program.
*/
- aio_switch_vmspace(aiocbe);
+ aio_switch_vmspace(job);
ki = userp->p_aioinfo;
/* Do the I/O function. */
- switch(aiocbe->uaiocb.aio_lio_opcode) {
+ switch(job->uaiocb.aio_lio_opcode) {
case LIO_READ:
case LIO_WRITE:
- aio_process_rw(aiocbe);
+ aio_process_rw(job);
break;
case LIO_SYNC:
- aio_process_sync(aiocbe);
+ aio_process_sync(job);
break;
case LIO_MLOCK:
- aio_process_mlock(aiocbe);
+ aio_process_mlock(job);
break;
}
@@ -1136,8 +1136,8 @@ aio_daemon(void *_id)
mtx_unlock(&aio_job_mtx);
AIO_LOCK(ki);
- TAILQ_REMOVE(&ki->kaio_jobqueue, aiocbe, plist);
- aio_bio_done_notify(userp, aiocbe, DONE_QUEUE);
+ TAILQ_REMOVE(&ki->kaio_jobqueue, job, plist);
+ aio_bio_done_notify(userp, job, DONE_QUEUE);
AIO_UNLOCK(ki);
mtx_lock(&aio_job_mtx);
@@ -1226,7 +1226,7 @@ aio_newproc(int *start)
* duration of this call.
*/
static int
-aio_qphysio(struct proc *p, struct aiocblist *aiocbe)
+aio_qphysio(struct proc *p, struct kaiocb *job)
{
struct aiocb *cb;
struct file *fp;
@@ -1240,8 +1240,8 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe)
int error, ref, unmap, poff;
vm_prot_t prot;
- cb = &aiocbe->uaiocb;
- fp = aiocbe->fd_file;
+ cb = &job->uaiocb;
+ fp = job->fd_file;
if (fp == NULL || fp->f_type != DTYPE_VNODE)
return (-1);
@@ -1286,9 +1286,9 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe)
goto unref;
}
}
- aiocbe->bp = bp = g_alloc_bio();
+ job->bp = bp = g_alloc_bio();
if (!unmap) {
- aiocbe->pbuf = pbuf = (struct buf *)getpbuf(NULL);
+ job->pbuf = pbuf = (struct buf *)getpbuf(NULL);
BUF_KERNPROC(pbuf);
}
@@ -1296,12 +1296,12 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe)
ki->kaio_count++;
if (!unmap)
ki->kaio_buffer_count++;
- lj = aiocbe->lio;
+ lj = job->lio;
if (lj)
lj->lioj_count++;
- TAILQ_INSERT_TAIL(&ki->kaio_bufqueue, aiocbe, plist);
- TAILQ_INSERT_TAIL(&ki->kaio_all, aiocbe, allist);
- aiocbe->jobstate = JOBST_JOBQBUF;
+ TAILQ_INSERT_TAIL(&ki->kaio_bufqueue, job, plist);
+ TAILQ_INSERT_TAIL(&ki->kaio_all, job, allist);
+ job->jobstate = JOBST_JOBQBUF;
cb->_aiocb_private.status = cb->aio_nbytes;
AIO_UNLOCK(ki);
@@ -1312,25 +1312,25 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe)
bp->bio_offset = cb->aio_offset;
bp->bio_cmd = cb->aio_lio_opcode == LIO_WRITE ? BIO_WRITE : BIO_READ;
bp->bio_dev = dev;
- bp->bio_caller1 = (void *)aiocbe;
+ bp->bio_caller1 = (void *)job;
prot = VM_PROT_READ;
if (cb->aio_lio_opcode == LIO_READ)
prot |= VM_PROT_WRITE; /* Less backwards than it looks */
- if ((aiocbe->npages = vm_fault_quick_hold_pages(
+ if ((job->npages = vm_fault_quick_hold_pages(
&curproc->p_vmspace->vm_map,
- (vm_offset_t)bp->bio_data, bp->bio_length, prot, aiocbe->pages,
- sizeof(aiocbe->pages)/sizeof(aiocbe->pages[0]))) < 0) {
+ (vm_offset_t)bp->bio_data, bp->bio_length, prot, job->pages,
+ sizeof(job->pages)/sizeof(job->pages[0]))) < 0) {
error = EFAULT;
goto doerror;
}
if (!unmap) {
pmap_qenter((vm_offset_t)pbuf->b_data,
- aiocbe->pages, aiocbe->npages);
+ job->pages, job->npages);
bp->bio_data = pbuf->b_data + poff;
} else {
- bp->bio_ma = aiocbe->pages;
- bp->bio_ma_n = aiocbe->npages;
+ bp->bio_ma = job->pages;
+ bp->bio_ma_n = job->npages;
bp->bio_ma_offset = poff;
bp->bio_data = unmapped_buf;
bp->bio_flags |= BIO_UNMAPPED;
@@ -1347,9 +1347,9 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe)
doerror:
AIO_LOCK(ki);
- aiocbe->jobstate = JOBST_NULL;
- TAILQ_REMOVE(&ki->kaio_bufqueue, aiocbe, plist);
- TAILQ_REMOVE(&ki->kaio_all, aiocbe, allist);
+ job->jobstate = JOBST_NULL;
+ TAILQ_REMOVE(&ki->kaio_bufqueue, job, plist);
+ TAILQ_REMOVE(&ki->kaio_all, job, allist);
ki->kaio_count--;
if (!unmap)
ki->kaio_buffer_count--;
@@ -1358,10 +1358,10 @@ doerror:
AIO_UNLOCK(ki);
if (pbuf) {
relpbuf(pbuf, NULL);
- aiocbe->pbuf = NULL;
+ job->pbuf = NULL;
}
g_destroy_bio(bp);
- aiocbe->bp = NULL;
+ job->bp = NULL;
unref:
dev_relthread(dev, ref);
return (error);
@@ -1373,7 +1373,7 @@ unref:
static void
aio_swake_cb(struct socket *so, struct sockbuf *sb)
{
- struct aiocblist *cb, *cbn;
+ struct kaiocb *job, *jobn;
int opcode;
SOCKBUF_LOCK_ASSERT(sb);
@@ -1384,18 +1384,18 @@ aio_swake_cb(struct socket *so, struct sockbuf *sb)
sb->sb_flags &= ~SB_AIO;
mtx_lock(&aio_job_mtx);
- TAILQ_FOREACH_SAFE(cb, &so->so_aiojobq, list, cbn) {
- if (opcode == cb->uaiocb.aio_lio_opcode) {
- if (cb->jobstate != JOBST_JOBQSOCK)
+ TAILQ_FOREACH_SAFE(job, &so->so_aiojobq, list, jobn) {
+ if (opcode == job->uaiocb.aio_lio_opcode) {
+ if (job->jobstate != JOBST_JOBQSOCK)
panic("invalid queue value");
/* XXX
* We don't have actual sockets backend yet,
* so we simply move the requests to the generic
* file I/O backend.
*/
- TAILQ_REMOVE(&so->so_aiojobq, cb, list);
- TAILQ_INSERT_TAIL(&aio_jobs, cb, list);
- aio_kick_nowait(cb->userproc);
+ TAILQ_REMOVE(&so->so_aiojobq, job, list);
+ TAILQ_INSERT_TAIL(&aio_jobs, job, list);
+ aio_kick_nowait(job->userproc);
}
}
mtx_unlock(&aio_job_mtx);
@@ -1515,14 +1515,14 @@ static struct aiocb_ops aiocb_ops_osigevent = {
* technique is done in this code.
*/
int
-aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj,
+aio_aqueue(struct thread *td, struct aiocb *ujob, struct aioliojob *lj,
int type, struct aiocb_ops *ops)
{
struct proc *p = td->td_proc;
cap_rights_t rights;
struct file *fp;
struct socket *so;
- struct aiocblist *aiocbe, *cb;
+ struct kaiocb *job, *job2;
struct kaioinfo *ki;
struct kevent kev;
struct sockbuf *sb;
@@ -1537,57 +1537,57 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj,
ki = p->p_aioinfo;
- ops->store_status(job, -1);
- ops->store_error(job, 0);
- ops->store_kernelinfo(job, -1);
+ ops->store_status(ujob, -1);
+ ops->store_error(ujob, 0);
+ ops->store_kernelinfo(ujob, -1);
if (num_queue_count >= max_queue_count ||
ki->kaio_count >= ki->kaio_qallowed_count) {
- ops->store_error(job, EAGAIN);
+ ops->store_error(ujob, EAGAIN);
return (EAGAIN);
}
- aiocbe = uma_zalloc(aiocb_zone, M_WAITOK | M_ZERO);
- knlist_init_mtx(&aiocbe->klist, AIO_MTX(ki));
+ job = uma_zalloc(aiocb_zone, M_WAITOK | M_ZERO);
+ knlist_init_mtx(&job->klist, AIO_MTX(ki));
- error = ops->copyin(job, &aiocbe->uaiocb);
+ error = ops->copyin(ujob, &job->uaiocb);
if (error) {
- ops->store_error(job, error);
- uma_zfree(aiocb_zone, aiocbe);
+ ops->store_error(ujob, error);
+ uma_zfree(aiocb_zone, job);
return (error);
}
/* XXX: aio_nbytes is later casted to signed types. */
- if (aiocbe->uaiocb.aio_nbytes > INT_MAX) {
- uma_zfree(aiocb_zone, aiocbe);
+ if (job->uaiocb.aio_nbytes > INT_MAX) {
+ uma_zfree(aiocb_zone, job);
return (EINVAL);
}
- if (aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT &&
- aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_SIGNAL &&
- aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_THREAD_ID &&
- aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_NONE) {
- ops->store_error(job, EINVAL);
- uma_zfree(aiocb_zone, aiocbe);
+ if (job->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT &&
+ job->uaiocb.aio_sigevent.sigev_notify != SIGEV_SIGNAL &&
+ job->uaiocb.aio_sigevent.sigev_notify != SIGEV_THREAD_ID &&
+ job->uaiocb.aio_sigevent.sigev_notify != SIGEV_NONE) {
+ ops->store_error(ujob, EINVAL);
+ uma_zfree(aiocb_zone, job);
return (EINVAL);
}
- if ((aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL ||
- aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID) &&
- !_SIG_VALID(aiocbe->uaiocb.aio_sigevent.sigev_signo)) {
- uma_zfree(aiocb_zone, aiocbe);
+ if ((job->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL ||
+ job->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID) &&
+ !_SIG_VALID(job->uaiocb.aio_sigevent.sigev_signo)) {
+ uma_zfree(aiocb_zone, job);
return (EINVAL);
}
- ksiginfo_init(&aiocbe->ksi);
+ ksiginfo_init(&job->ksi);
/* Save userspace address of the job info. */
- aiocbe->uuaiocb = job;
+ job->ujob = ujob;
/* Get the opcode. */
if (type != LIO_NOP)
- aiocbe->uaiocb.aio_lio_opcode = type;
- opcode = aiocbe->uaiocb.aio_lio_opcode;
+ job->uaiocb.aio_lio_opcode = type;
+ opcode = job->uaiocb.aio_lio_opcode;
/*
* Validate the opcode and fetch the file object for the specified
@@ -1597,7 +1597,7 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj,
* retrieve a file descriptor without knowing what the capabiltity
* should be.
*/
- fd = aiocbe->uaiocb.aio_fildes;
+ fd = job->uaiocb.aio_fildes;
switch (opcode) {
case LIO_WRITE:
error = fget_write(td, fd,
@@ -1620,8 +1620,8 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj,
error = EINVAL;
}
if (error) {
- uma_zfree(aiocb_zone, aiocbe);
- ops->store_error(job, error);
+ uma_zfree(aiocb_zone, job);
+ ops->store_error(ujob, error);
return (error);
}
@@ -1630,60 +1630,60 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj,
goto aqueue_fail;
}
- if (opcode != LIO_SYNC && aiocbe->uaiocb.aio_offset == -1LL) {
+ if (opcode != LIO_SYNC && job->uaiocb.aio_offset == -1LL) {
error = EINVAL;
goto aqueue_fail;
}
- aiocbe->fd_file = fp;
+ job->fd_file = fp;
mtx_lock(&aio_job_mtx);
jid = jobrefid++;
- aiocbe->seqno = jobseqno++;
+ job->seqno = jobseqno++;
mtx_unlock(&aio_job_mtx);
- error = ops->store_kernelinfo(job, jid);
+ error = ops->store_kernelinfo(ujob, jid);
if (error) {
error = EINVAL;
goto aqueue_fail;
}
- aiocbe->uaiocb._aiocb_private.kernelinfo = (void *)(intptr_t)jid;
+ job->uaiocb._aiocb_private.kernelinfo = (void *)(intptr_t)jid;
if (opcode == LIO_NOP) {
fdrop(fp, td);
- uma_zfree(aiocb_zone, aiocbe);
+ uma_zfree(aiocb_zone, job);
return (0);
}
- if (aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT)
+ if (job->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT)
goto no_kqueue;
- evflags = aiocbe->uaiocb.aio_sigevent.sigev_notify_kevent_flags;
+ evflags = job->uaiocb.aio_sigevent.sigev_notify_kevent_flags;
if ((evflags & ~(EV_CLEAR | EV_DISPATCH | EV_ONESHOT)) != 0) {
error = EINVAL;
goto aqueue_fail;
}
- kqfd = aiocbe->uaiocb.aio_sigevent.sigev_notify_kqueue;
- kev.ident = (uintptr_t)aiocbe->uuaiocb;
+ kqfd = job->uaiocb.aio_sigevent.sigev_notify_kqueue;
+ kev.ident = (uintptr_t)job->ujob;
kev.filter = EVFILT_AIO;
kev.flags = EV_ADD | EV_ENABLE | EV_FLAG1 | evflags;
- kev.data = (intptr_t)aiocbe;
- kev.udata = aiocbe->uaiocb.aio_sigevent.sigev_value.sival_ptr;
+ kev.data = (intptr_t)job;
+ kev.udata = job->uaiocb.aio_sigevent.sigev_value.sival_ptr;
error = kqfd_register(kqfd, &kev, td, 1);
aqueue_fail:
if (error) {
if (fp)
fdrop(fp, td);
- uma_zfree(aiocb_zone, aiocbe);
- ops->store_error(job, error);
+ uma_zfree(aiocb_zone, job);
+ ops->store_error(ujob, error);
goto done;
}
no_kqueue:
- ops->store_error(job, EINPROGRESS);
- aiocbe->uaiocb._aiocb_private.error = EINPROGRESS;
- aiocbe->userproc = p;
- aiocbe->cred = crhold(td->td_ucred);
- aiocbe->jobflags = 0;
- aiocbe->lio = lj;
+ ops->store_error(ujob, EINPROGRESS);
+ job->uaiocb._aiocb_private.error = EINPROGRESS;
+ job->userproc = p;
+ job->cred = crhold(td->td_ucred);
+ job->jobflags = 0;
+ job->lio = lj;
if (opcode == LIO_SYNC)
goto queueit;
@@ -1695,7 +1695,7 @@ no_kqueue:
* socket is ready to be read or written (based on the requested
* operation).
*
- * If it is not ready for io, then queue the aiocbe on the
+ * If it is not ready for io, then queue the job on the
* socket, and set the flags so we get a call when sbnotify()
* happens.
*
@@ -1710,13 +1710,13 @@ no_kqueue:
sb->sb_flags |= SB_AIO;
mtx_lock(&aio_job_mtx);
- TAILQ_INSERT_TAIL(&so->so_aiojobq, aiocbe, list);
+ TAILQ_INSERT_TAIL(&so->so_aiojobq, job, list);
mtx_unlock(&aio_job_mtx);
AIO_LOCK(ki);
- TAILQ_INSERT_TAIL(&ki->kaio_all, aiocbe, allist);
- TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, aiocbe, plist);
- aiocbe->jobstate = JOBST_JOBQSOCK;
+ TAILQ_INSERT_TAIL(&ki->kaio_all, job, allist);
+ TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, job, plist);
+ job->jobstate = JOBST_JOBQSOCK;
ki->kaio_count++;
if (lj)
lj->lioj_count++;
@@ -1729,12 +1729,12 @@ no_kqueue:
SOCKBUF_UNLOCK(sb);
}
- if ((error = aio_qphysio(p, aiocbe)) == 0)
+ if ((error = aio_qphysio(p, job)) == 0)
goto done;
#if 0
if (error > 0) {
- aiocbe->uaiocb._aiocb_private.error = error;
- ops->store_error(job, error);
+ job->uaiocb._aiocb_private.error = error;
+ ops->store_error(ujob, error);
goto done;
}
#endif
@@ -1745,35 +1745,35 @@ queueit:
ki->kaio_count++;
if (lj)
lj->lioj_count++;
- TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, aiocbe, plist);
- TAILQ_INSERT_TAIL(&ki->kaio_all, aiocbe, allist);
+ TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, job, plist);
+ TAILQ_INSERT_TAIL(&ki->kaio_all, job, allist);
if (opcode == LIO_SYNC) {
- TAILQ_FOREACH(cb, &ki->kaio_jobqueue, plist) {
- if (cb->fd_file == aiocbe->fd_file &&
- cb->uaiocb.aio_lio_opcode != LIO_SYNC &&
- cb->seqno < aiocbe->seqno) {
- cb->jobflags |= AIOCBLIST_CHECKSYNC;
- aiocbe->pending++;
+ TAILQ_FOREACH(job2, &ki->kaio_jobqueue, plist) {
+ if (job2->fd_file == job->fd_file &&
+ job2->uaiocb.aio_lio_opcode != LIO_SYNC &&
+ job2->seqno < job->seqno) {
+ job2->jobflags |= KAIOCB_CHECKSYNC;
+ job->pending++;
}
}
- TAILQ_FOREACH(cb, &ki->kaio_bufqueue, plist) {
- if (cb->fd_file == aiocbe->fd_file &&
- cb->uaiocb.aio_lio_opcode != LIO_SYNC &&
- cb->seqno < aiocbe->seqno) {
- cb->jobflags |= AIOCBLIST_CHECKSYNC;
- aiocbe->pending++;
+ TAILQ_FOREACH(job2, &ki->kaio_bufqueue, plist) {
+ if (job2->fd_file == job->fd_file &&
+ job2->uaiocb.aio_lio_opcode != LIO_SYNC &&
+ job2->seqno < job->seqno) {
+ job2->jobflags |= KAIOCB_CHECKSYNC;
+ job->pending++;
}
}
- if (aiocbe->pending != 0) {
- TAILQ_INSERT_TAIL(&ki->kaio_syncqueue, aiocbe, list);
- aiocbe->jobstate = JOBST_JOBQSYNC;
+ if (job->pending != 0) {
+ TAILQ_INSERT_TAIL(&ki->kaio_syncqueue, job, list);
+ job->jobstate = JOBST_JOBQSYNC;
AIO_UNLOCK(ki);
goto done;
}
}
mtx_lock(&aio_job_mtx);
- TAILQ_INSERT_TAIL(&aio_jobs, aiocbe, list);
- aiocbe->jobstate = JOBST_JOBQGLOBAL;
+ TAILQ_INSERT_TAIL(&aio_jobs, job, list);
+ job->jobstate = JOBST_JOBQGLOBAL;
aio_kick_nowait(p);
mtx_unlock(&aio_job_mtx);
AIO_UNLOCK(ki);
@@ -1848,10 +1848,10 @@ aio_kick_helper(void *context, int pending)
* released.
*/
static int
-kern_aio_return(struct thread *td, struct aiocb *uaiocb, struct aiocb_ops *ops)
+kern_aio_return(struct thread *td, struct aiocb *ujob, struct aiocb_ops *ops)
{
struct proc *p = td->td_proc;
- struct aiocblist *cb;
+ struct kaiocb *job;
struct kaioinfo *ki;
int status, error;
@@ -1859,26 +1859,26 @@ kern_aio_return(struct thread *td, struct aiocb *uaiocb, struct aiocb_ops *ops)
if (ki == NULL)
return (EINVAL);
AIO_LOCK(ki);
- TAILQ_FOREACH(cb, &ki->kaio_done, plist) {
- if (cb->uuaiocb == uaiocb)
+ TAILQ_FOREACH(job, &ki->kaio_done, plist) {
+ if (job->ujob == ujob)
break;
}
- if (cb != NULL) {
- MPASS(cb->jobstate == JOBST_JOBFINISHED);
- status = cb->uaiocb._aiocb_private.status;
- error = cb->uaiocb._aiocb_private.error;
+ if (job != NULL) {
+ MPASS(job->jobstate == JOBST_JOBFINISHED);
+ status = job->uaiocb._aiocb_private.status;
+ error = job->uaiocb._aiocb_private.error;
td->td_retval[0] = status;
- if (cb->uaiocb.aio_lio_opcode == LIO_WRITE) {
- td->td_ru.ru_oublock += cb->outputcharge;
- cb->outputcharge = 0;
- } else if (cb->uaiocb.aio_lio_opcode == LIO_READ) {
- td->td_ru.ru_inblock += cb->inputcharge;
- cb->inputcharge = 0;
+ if (job->uaiocb.aio_lio_opcode == LIO_WRITE) {
+ td->td_ru.ru_oublock += job->outputcharge;
+ job->outputcharge = 0;
+ } else if (job->uaiocb.aio_lio_opcode == LIO_READ) {
+ td->td_ru.ru_inblock += job->inputcharge;
+ job->inputcharge = 0;
}
- aio_free_entry(cb);
+ aio_free_entry(job);
AIO_UNLOCK(ki);
- ops->store_error(uaiocb, error);
- ops->store_status(uaiocb, status);
+ ops->store_error(ujob, error);
+ ops->store_status(ujob, status);
} else {
error = EINVAL;
AIO_UNLOCK(ki);
@@ -1903,7 +1903,7 @@ kern_aio_suspend(struct thread *td, int njoblist, struct aiocb **ujoblist,
struct proc *p = td->td_proc;
struct timeval atv;
struct kaioinfo *ki;
- struct aiocblist *cb, *cbfirst;
+ struct kaiocb *firstjob, *job;
int error, i, timo;
timo = 0;
@@ -1926,20 +1926,20 @@ kern_aio_suspend(struct thread *td, int njoblist, struct aiocb **ujoblist,
AIO_LOCK(ki);
for (;;) {
- cbfirst = NULL;
+ firstjob = NULL;
error = 0;
- TAILQ_FOREACH(cb, &ki->kaio_all, allist) {
+ TAILQ_FOREACH(job, &ki->kaio_all, allist) {
for (i = 0; i < njoblist; i++) {
- if (cb->uuaiocb == ujoblist[i]) {
- if (cbfirst == NULL)
- cbfirst = cb;
- if (cb->jobstate == JOBST_JOBFINISHED)
+ if (job->ujob == ujoblist[i]) {
+ if (firstjob == NULL)
+ firstjob = job;
+ if (job->jobstate == JOBST_JOBFINISHED)
goto RETURN;
}
}
}
/* All tasks were finished. */
- if (cbfirst == NULL)
+ if (firstjob == NULL)
break;
ki->kaio_flags |= KAIO_WAKEUP;
@@ -1990,7 +1990,7 @@ sys_aio_cancel(struct thread *td, struct aio_cancel_args *uap)
{
struct proc *p = td->td_proc;
struct kaioinfo *ki;
- struct aiocblist *cbe, *cbn;
+ struct kaiocb *job, *jobn;
struct file *fp;
struct socket *so;
cap_rights_t rights;
@@ -2019,32 +2019,32 @@ sys_aio_cancel(struct thread *td, struct aio_cancel_args *uap)
}
AIO_LOCK(ki);
- TAILQ_FOREACH_SAFE(cbe, &ki->kaio_jobqueue, plist, cbn) {
- if ((uap->fd == cbe->uaiocb.aio_fildes) &&
+ TAILQ_FOREACH_SAFE(job, &ki->kaio_jobqueue, plist, jobn) {
+ if ((uap->fd == job->uaiocb.aio_fildes) &&
((uap->aiocbp == NULL) ||
- (uap->aiocbp == cbe->uuaiocb))) {
+ (uap->aiocbp == job->ujob))) {
remove = 0;
mtx_lock(&aio_job_mtx);
- if (cbe->jobstate == JOBST_JOBQGLOBAL) {
- TAILQ_REMOVE(&aio_jobs, cbe, list);
+ if (job->jobstate == JOBST_JOBQGLOBAL) {
+ TAILQ_REMOVE(&aio_jobs, job, list);
remove = 1;
- } else if (cbe->jobstate == JOBST_JOBQSOCK) {
+ } else if (job->jobstate == JOBST_JOBQSOCK) {
MPASS(fp->f_type == DTYPE_SOCKET);
so = fp->f_data;
- TAILQ_REMOVE(&so->so_aiojobq, cbe, list);
+ TAILQ_REMOVE(&so->so_aiojobq, job, list);
remove = 1;
- } else if (cbe->jobstate == JOBST_JOBQSYNC) {
- TAILQ_REMOVE(&ki->kaio_syncqueue, cbe, list);
+ } else if (job->jobstate == JOBST_JOBQSYNC) {
+ TAILQ_REMOVE(&ki->kaio_syncqueue, job, list);
remove = 1;
}
mtx_unlock(&aio_job_mtx);
if (remove) {
- TAILQ_REMOVE(&ki->kaio_jobqueue, cbe, plist);
- cbe->uaiocb._aiocb_private.status = -1;
- cbe->uaiocb._aiocb_private.error = ECANCELED;
- aio_bio_done_notify(p, cbe, DONE_QUEUE);
+ TAILQ_REMOVE(&ki->kaio_jobqueue, job, plist);
+ job->uaiocb._aiocb_private.status = -1;
+ job->uaiocb._aiocb_private.error = ECANCELED;
+ aio_bio_done_notify(p, job, DONE_QUEUE);
cancelled++;
} else {
notcancelled++;
@@ -2086,10 +2086,10 @@ done:
* a userland subroutine.
*/
static int
-kern_aio_error(struct thread *td, struct aiocb *aiocbp, struct aiocb_ops *ops)
+kern_aio_error(struct thread *td, struct aiocb *ujob, struct aiocb_ops *ops)
{
struct proc *p = td->td_proc;
- struct aiocblist *cb;
+ struct kaiocb *job;
struct kaioinfo *ki;
int status;
@@ -2100,11 +2100,11 @@ kern_aio_error(struct thread *td, struct aiocb *aiocbp, struct aiocb_ops *ops)
}
AIO_LOCK(ki);
- TAILQ_FOREACH(cb, &ki->kaio_all, allist) {
- if (cb->uuaiocb == aiocbp) {
- if (cb->jobstate == JOBST_JOBFINISHED)
+ TAILQ_FOREACH(job, &ki->kaio_all, allist) {
+ if (job->ujob == ujob) {
+ if (job->jobstate == JOBST_JOBFINISHED)
td->td_retval[0] =
- cb->uaiocb._aiocb_private.error;
+ job->uaiocb._aiocb_private.error;
else
td->td_retval[0] = EINPROGRESS;
AIO_UNLOCK(ki);
@@ -2116,9 +2116,9 @@ kern_aio_error(struct thread *td, struct aiocb *aiocbp, struct aiocb_ops *ops)
/*
* Hack for failure of aio_aqueue.
*/
- status = ops->fetch_status(aiocbp);
+ status = ops->fetch_status(ujob);
if (status == -1) {
- td->td_retval[0] = ops->fetch_error(aiocbp);
+ td->td_retval[0] = ops->fetch_error(ujob);
return (0);
}
@@ -2178,7 +2178,7 @@ kern_lio_listio(struct thread *td, int mode, struct aiocb * const *uacb_list,
struct aiocb_ops *ops)
{
struct proc *p = td->td_proc;
- struct aiocb *iocb;
+ struct aiocb *job;
struct kaioinfo *ki;
struct aioliojob *lj;
struct kevent kev;
@@ -2254,9 +2254,9 @@ kern_lio_listio(struct thread *td, int mode, struct aiocb * const *uacb_list,
*/
nerror = 0;
for (i = 0; i < nent; i++) {
- iocb = acb_list[i];
- if (iocb != NULL) {
- error = aio_aqueue(td, iocb, lj, LIO_NOP, ops);
+ job = acb_list[i];
+ if (job != NULL) {
+ error = aio_aqueue(td, job, lj, LIO_NOP, ops);
if (error != 0)
nerror++;
}
@@ -2379,37 +2379,37 @@ sys_lio_listio(struct thread *td, struct lio_listio_args *uap)
static void
aio_physwakeup(struct bio *bp)
{
- struct aiocblist *aiocbe = (struct aiocblist *)bp->bio_caller1;
+ struct kaiocb *job = (struct kaiocb *)bp->bio_caller1;
struct proc *userp;
struct kaioinfo *ki;
int nblks;
/* Release mapping into kernel space. */
- if (aiocbe->pbuf) {
- pmap_qremove((vm_offset_t)aiocbe->pbuf->b_data, aiocbe->npages);
- relpbuf(aiocbe->pbuf, NULL);
- aiocbe->pbuf = NULL;
+ if (job->pbuf) {
+ pmap_qremove((vm_offset_t)job->pbuf->b_data, job->npages);
+ relpbuf(job->pbuf, NULL);
+ job->pbuf = NULL;
atomic_subtract_int(&num_buf_aio, 1);
}
- vm_page_unhold_pages(aiocbe->pages, aiocbe->npages);
+ vm_page_unhold_pages(job->pages, job->npages);
- bp = aiocbe->bp;
- aiocbe->bp = NULL;
- userp = aiocbe->userproc;
+ bp = job->bp;
+ job->bp = NULL;
+ userp = job->userproc;
ki = userp->p_aioinfo;
AIO_LOCK(ki);
- aiocbe->uaiocb._aiocb_private.status -= bp->bio_resid;
- aiocbe->uaiocb._aiocb_private.error = 0;
+ job->uaiocb._aiocb_private.status -= bp->bio_resid;
+ job->uaiocb._aiocb_private.error = 0;
if (bp->bio_flags & BIO_ERROR)
- aiocbe->uaiocb._aiocb_private.error = bp->bio_error;
- nblks = btodb(aiocbe->uaiocb.aio_nbytes);
- if (aiocbe->uaiocb.aio_lio_opcode == LIO_WRITE)
- aiocbe->outputcharge += nblks;
+ job->uaiocb._aiocb_private.error = bp->bio_error;
+ nblks = btodb(job->uaiocb.aio_nbytes);
+ if (job->uaiocb.aio_lio_opcode == LIO_WRITE)
+ job->outputcharge += nblks;
else
- aiocbe->inputcharge += nblks;
- TAILQ_REMOVE(&userp->p_aioinfo->kaio_bufqueue, aiocbe, plist);
+ job->inputcharge += nblks;
+ TAILQ_REMOVE(&userp->p_aioinfo->kaio_bufqueue, job, plist);
ki->kaio_buffer_count--;
- aio_bio_done_notify(userp, aiocbe, DONE_BUF);
+ aio_bio_done_notify(userp, job, DONE_BUF);
AIO_UNLOCK(ki);
g_destroy_bio(bp);
@@ -2417,17 +2417,17 @@ aio_physwakeup(struct bio *bp)
/* syscall - wait for the next completion of an aio request */
static int
-kern_aio_waitcomplete(struct thread *td, struct aiocb **aiocbp,
+kern_aio_waitcomplete(struct thread *td, struct aiocb **ujobp,
struct timespec *ts, struct aiocb_ops *ops)
{
struct proc *p = td->td_proc;
struct timeval atv;
struct kaioinfo *ki;
- struct aiocblist *cb;
- struct aiocb *uuaiocb;
+ struct kaiocb *job;
+ struct aiocb *ujob;
int error, status, timo;
- ops->store_aiocb(aiocbp, NULL);
+ ops->store_aiocb(ujobp, NULL);
if (ts == NULL) {
timo = 0;
@@ -2448,9 +2448,9 @@ kern_aio_waitcomplete(struct thread *td, struct aiocb **aiocbp,
ki = p->p_aioinfo;
error = 0;
- cb = NULL;
+ job = NULL;
AIO_LOCK(ki);
- while ((cb = TAILQ_FIRST(&ki->kaio_done)) == NULL) {
+ while ((job = TAILQ_FIRST(&ki->kaio_done)) == NULL) {
if (timo == -1) {
error = EWOULDBLOCK;
break;
@@ -2464,24 +2464,24 @@ kern_aio_waitcomplete(struct thread *td, struct aiocb **aiocbp,
break;
}
- if (cb != NULL) {
- MPASS(cb->jobstate == JOBST_JOBFINISHED);
- uuaiocb = cb->uuaiocb;
- status = cb->uaiocb._aiocb_private.status;
- error = cb->uaiocb._aiocb_private.error;
+ if (job != NULL) {
+ MPASS(job->jobstate == JOBST_JOBFINISHED);
+ ujob = job->ujob;
+ status = job->uaiocb._aiocb_private.status;
+ error = job->uaiocb._aiocb_private.error;
td->td_retval[0] = status;
- if (cb->uaiocb.aio_lio_opcode == LIO_WRITE) {
- td->td_ru.ru_oublock += cb->outputcharge;
- cb->outputcharge = 0;
- } else if (cb->uaiocb.aio_lio_opcode == LIO_READ) {
- td->td_ru.ru_inblock += cb->inputcharge;
- cb->inputcharge = 0;
+ if (job->uaiocb.aio_lio_opcode == LIO_WRITE) {
+ td->td_ru.ru_oublock += job->outputcharge;
+ job->outputcharge = 0;
+ } else if (job->uaiocb.aio_lio_opcode == LIO_READ) {
+ td->td_ru.ru_inblock += job->inputcharge;
+ job->inputcharge = 0;
}
- aio_free_entry(cb);
+ aio_free_entry(job);
AIO_UNLOCK(ki);
- ops->store_aiocb(aiocbp, uuaiocb);
- ops->store_error(uuaiocb, error);
- ops->store_status(uuaiocb, status);
+ ops->store_aiocb(ujobp, ujob);
+ ops->store_error(ujob, error);
+ ops->store_status(ujob, status);
} else
AIO_UNLOCK(ki);
@@ -2507,7 +2507,7 @@ sys_aio_waitcomplete(struct thread *td, struct aio_waitcomplete_args *uap)
}
static int
-kern_aio_fsync(struct thread *td, int op, struct aiocb *aiocbp,
+kern_aio_fsync(struct thread *td, int op, struct aiocb *ujob,
struct aiocb_ops *ops)
{
struct proc *p = td->td_proc;
@@ -2518,7 +2518,7 @@ kern_aio_fsync(struct thread *td, int op, struct aiocb *aiocbp,
ki = p->p_aioinfo;
if (ki == NULL)
aio_init_aioinfo(p);
- return (aio_aqueue(td, aiocbp, NULL, LIO_SYNC, ops));
+ return (aio_aqueue(td, ujob, NULL, LIO_SYNC, ops));
}
int
@@ -2532,19 +2532,19 @@ sys_aio_fsync(struct thread *td, struct aio_fsync_args *uap)
static int
filt_aioattach(struct knote *kn)
{
- struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_sdata;
+ struct kaiocb *job = (struct kaiocb *)kn->kn_sdata;
/*
- * The aiocbe pointer must be validated before using it, so
+ * The job pointer must be validated before using it, so
* registration is restricted to the kernel; the user cannot
* set EV_FLAG1.
*/
if ((kn->kn_flags & EV_FLAG1) == 0)
return (EPERM);
- kn->kn_ptr.p_aio = aiocbe;
+ kn->kn_ptr.p_aio = job;
kn->kn_flags &= ~EV_FLAG1;
- knlist_add(&aiocbe->klist, kn, 0);
+ knlist_add(&job->klist, kn, 0);
return (0);
}
@@ -2567,10 +2567,10 @@ filt_aiodetach(struct knote *kn)
static int
filt_aio(struct knote *kn, long hint)
{
- struct aiocblist *aiocbe = kn->kn_ptr.p_aio;
+ struct kaiocb *job = kn->kn_ptr.p_aio;
- kn->kn_data = aiocbe->uaiocb._aiocb_private.error;
- if (aiocbe->jobstate != JOBST_JOBFINISHED)
+ kn->kn_data = job->uaiocb._aiocb_private.error;
+ if (job->jobstate != JOBST_JOBFINISHED)
return (0);
kn->kn_flags |= EV_EOF;
return (1);
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 3ca995fea0d1..505da758ed4a 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -880,10 +880,10 @@ vfs_domount_update(
struct vfsoptlist **optlist /* Options local to the filesystem. */
)
{
- struct oexport_args oexport;
struct export_args export;
+ void *bufp;
struct mount *mp;
- int error, export_error;
+ int error, export_error, len;
uint64_t flag;
ASSERT_VOP_ELOCKED(vp, __func__);
@@ -951,23 +951,21 @@ vfs_domount_update(
error = VFS_MOUNT(mp);
export_error = 0;
- if (error == 0) {
- /* Process the export option. */
- if (vfs_copyopt(mp->mnt_optnew, "export", &export,
- sizeof(export)) == 0) {
- export_error = vfs_export(mp, &export);
- } else if (vfs_copyopt(mp->mnt_optnew, "export", &oexport,
- sizeof(oexport)) == 0) {
- export.ex_flags = oexport.ex_flags;
- export.ex_root = oexport.ex_root;
- export.ex_anon = oexport.ex_anon;
- export.ex_addr = oexport.ex_addr;
- export.ex_addrlen = oexport.ex_addrlen;
- export.ex_mask = oexport.ex_mask;
- export.ex_masklen = oexport.ex_masklen;
- export.ex_indexfile = oexport.ex_indexfile;
- export.ex_numsecflavors = 0;
+ /* Process the export option. */
+ if (error == 0 && vfs_getopt(mp->mnt_optnew, "export", &bufp,
+ &len) == 0) {
+ /* Assume that there is only 1 ABI for each length. */
+ switch (len) {
+ case (sizeof(struct oexport_args)):
+ bzero(&export, sizeof(export));
+ /* FALLTHROUGH */
+ case (sizeof(export)):
+ bcopy(bufp, &export, len);
export_error = vfs_export(mp, &export);
+ break;
+ default:
+ export_error = EINVAL;
+ break;
}
}
diff --git a/sys/kgssapi/krb5/kcrypto_aes.c b/sys/kgssapi/krb5/kcrypto_aes.c
index d2dac2158f0a..fca963c5f1c6 100644
--- a/sys/kgssapi/krb5/kcrypto_aes.c
+++ b/sys/kgssapi/krb5/kcrypto_aes.c
@@ -43,7 +43,8 @@ __FBSDID("$FreeBSD$");
struct aes_state {
struct mtx as_lock;
- uint64_t as_session;
+ uint64_t as_session_aes;
+ uint64_t as_session_sha1;
};
static void
@@ -61,8 +62,10 @@ aes_destroy(struct krb5_key_state *ks)
{
struct aes_state *as = ks->ks_priv;
- if (as->as_session)
- crypto_freesession(as->as_session);
+ if (as->as_session_aes != 0)
+ crypto_freesession(as->as_session_aes);
+ if (as->as_session_sha1 != 0)
+ crypto_freesession(as->as_session_sha1);
mtx_destroy(&as->as_lock);
free(ks->ks_priv, M_GSSAPI);
}
@@ -72,32 +75,35 @@ aes_set_key(struct krb5_key_state *ks, const void *in)
{
void *kp = ks->ks_key;
struct aes_state *as = ks->ks_priv;
- struct cryptoini cri[2];
+ struct cryptoini cri;
if (kp != in)
bcopy(in, kp, ks->ks_class->ec_keylen);
- if (as->as_session)
- crypto_freesession(as->as_session);
-
- bzero(cri, sizeof(cri));
+ if (as->as_session_aes != 0)
+ crypto_freesession(as->as_session_aes);
+ if (as->as_session_sha1 != 0)
+ crypto_freesession(as->as_session_sha1);
/*
* We only want the first 96 bits of the HMAC.
*/
- cri[0].cri_alg = CRYPTO_SHA1_HMAC;
- cri[0].cri_klen = ks->ks_class->ec_keybits;
- cri[0].cri_mlen = 12;
- cri[0].cri_key = ks->ks_key;
- cri[0].cri_next = &cri[1];
-
- cri[1].cri_alg = CRYPTO_AES_CBC;
- cri[1].cri_klen = ks->ks_class->ec_keybits;
- cri[1].cri_mlen = 0;
- cri[1].cri_key = ks->ks_key;
- cri[1].cri_next = NULL;
-
- crypto_newsession(&as->as_session, cri,
+ bzero(&cri, sizeof(cri));
+ cri.cri_alg = CRYPTO_SHA1_HMAC;
+ cri.cri_klen = ks->ks_class->ec_keybits;
+ cri.cri_mlen = 12;
+ cri.cri_key = ks->ks_key;
+ cri.cri_next = NULL;
+ crypto_newsession(&as->as_session_sha1, &cri,
+ CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE);
+
+ bzero(&cri, sizeof(cri));
+ cri.cri_alg = CRYPTO_AES_CBC;
+ cri.cri_klen = ks->ks_class->ec_keybits;
+ cri.cri_mlen = 0;
+ cri.cri_key = ks->ks_key;
+ cri.cri_next = NULL;
+ crypto_newsession(&as->as_session_aes, &cri,
CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE);
}
@@ -114,7 +120,7 @@ aes_crypto_cb(struct cryptop *crp)
int error;
struct aes_state *as = (struct aes_state *) crp->crp_opaque;
- if (CRYPTO_SESID2CAPS(as->as_session) & CRYPTOCAP_F_SYNC)
+ if (CRYPTO_SESID2CAPS(crp->crp_sid) & CRYPTOCAP_F_SYNC)
return (0);
error = crp->crp_etype;
@@ -151,7 +157,7 @@ aes_encrypt_1(const struct krb5_key_state *ks, int buftype, void *buf,
crd->crd_next = NULL;
crd->crd_alg = CRYPTO_AES_CBC;
- crp->crp_sid = as->as_session;
+ crp->crp_sid = as->as_session_aes;
crp->crp_flags = buftype | CRYPTO_F_CBIFSYNC;
crp->crp_buf = buf;
crp->crp_opaque = (void *) as;
@@ -159,7 +165,7 @@ aes_encrypt_1(const struct krb5_key_state *ks, int buftype, void *buf,
error = crypto_dispatch(crp);
- if ((CRYPTO_SESID2CAPS(as->as_session) & CRYPTOCAP_F_SYNC) == 0) {
+ if ((CRYPTO_SESID2CAPS(as->as_session_aes) & CRYPTOCAP_F_SYNC) == 0) {
mtx_lock(&as->as_lock);
if (!error && !(crp->crp_flags & CRYPTO_F_DONE))
error = msleep(crp, &as->as_lock, 0, "gssaes", 0);
@@ -326,7 +332,7 @@ aes_checksum(const struct krb5_key_state *ks, int usage,
crd->crd_next = NULL;
crd->crd_alg = CRYPTO_SHA1_HMAC;
- crp->crp_sid = as->as_session;
+ crp->crp_sid = as->as_session_sha1;
crp->crp_ilen = inlen;
crp->crp_olen = 12;
crp->crp_etype = 0;
@@ -337,7 +343,7 @@ aes_checksum(const struct krb5_key_state *ks, int usage,
error = crypto_dispatch(crp);
- if ((CRYPTO_SESID2CAPS(as->as_session) & CRYPTOCAP_F_SYNC) == 0) {
+ if ((CRYPTO_SESID2CAPS(as->as_session_sha1) & CRYPTOCAP_F_SYNC) == 0) {
mtx_lock(&as->as_lock);
if (!error && !(crp->crp_flags & CRYPTO_F_DONE))
error = msleep(crp, &as->as_lock, 0, "gssaes", 0);
diff --git a/sys/mips/atheros/ar71xx_ehci.c b/sys/mips/atheros/ar71xx_ehci.c
index 5b7b3e25b9dc..07e06b979a0b 100644
--- a/sys/mips/atheros/ar71xx_ehci.c
+++ b/sys/mips/atheros/ar71xx_ehci.c
@@ -61,6 +61,10 @@ __FBSDID("$FreeBSD$");
#define EHCI_HC_DEVSTR "AR71XX Integrated USB 2.0 controller"
+#define EHCI_USBMODE 0x68 /* USB Device mode register */
+#define EHCI_UM_CM 0x00000003 /* R/WO Controller Mode */
+#define EHCI_UM_CM_HOST 0x3 /* Host Controller */
+
struct ar71xx_ehci_softc {
ehci_softc_t base; /* storage for EHCI code */
};
@@ -71,6 +75,18 @@ static device_detach_t ar71xx_ehci_detach;
bs_r_1_proto(reversed);
bs_w_1_proto(reversed);
+static void
+ar71xx_ehci_post_reset(struct ehci_softc *ehci_softc)
+{
+ uint32_t usbmode;
+
+ /* Force HOST mode */
+ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
+ usbmode &= ~EHCI_UM_CM;
+ usbmode |= EHCI_UM_CM_HOST;
+ EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
+}
+
static int
ar71xx_ehci_probe(device_t self)
{
@@ -161,7 +177,8 @@ ar71xx_ehci_attach(device_t self)
* which means port speed must be read from the Port Status
* register following a port enable.
*/
- sc->sc_flags = EHCI_SCFLG_SETMODE;
+ sc->sc_flags = 0;
+ sc->sc_vendor_post_reset = ar71xx_ehci_post_reset;
switch (ar71xx_soc) {
case AR71XX_SOC_AR7241:
@@ -178,6 +195,8 @@ ar71xx_ehci_attach(device_t self)
case AR71XX_SOC_QCA9556:
case AR71XX_SOC_QCA9558:
sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM;
+ sc->sc_vendor_get_port_speed =
+ ehci_get_port_speed_portsc;
break;
default:
/* fallthrough */
diff --git a/sys/mips/conf/AR933X_BASE b/sys/mips/conf/AR933X_BASE
index 38f847db12eb..c5619fe4ff4a 100644
--- a/sys/mips/conf/AR933X_BASE
+++ b/sys/mips/conf/AR933X_BASE
@@ -12,7 +12,7 @@
machine mips mips
ident AR933X_BASE
-cpu CPU_MIPS4KC
+cpu CPU_MIPS24K
makeoptions KERNLOADADDR=0x80050000
options HZ=1000
diff --git a/sys/mips/conf/AR934X_BASE b/sys/mips/conf/AR934X_BASE
index 4faaf9e6be61..87bea17beac8 100644
--- a/sys/mips/conf/AR934X_BASE
+++ b/sys/mips/conf/AR934X_BASE
@@ -12,7 +12,7 @@
machine mips mips
ident AR934X_BASE
-cpu CPU_MIPS74KC
+cpu CPU_MIPS74K
makeoptions KERNLOADADDR=0x80050000
options HZ=1000
diff --git a/sys/mips/conf/QCA955X_BASE b/sys/mips/conf/QCA955X_BASE
index 45dcbb7aa837..a7b5df73dc05 100644
--- a/sys/mips/conf/QCA955X_BASE
+++ b/sys/mips/conf/QCA955X_BASE
@@ -13,7 +13,7 @@
machine mips mips
ident QCA955X_BASE
-cpu CPU_MIPS74KC
+cpu CPU_MIPS74K
makeoptions KERNLOADADDR=0x80050000
options HZ=1000
diff --git a/sys/mips/include/asm.h b/sys/mips/include/asm.h
index 9e7e7719076a..8a7d640f9e12 100644
--- a/sys/mips/include/asm.h
+++ b/sys/mips/include/asm.h
@@ -700,7 +700,7 @@ _C_LABEL(x):
#elif defined(CPU_RMI)
#define HAZARD_DELAY
#define ITLBNOPFIX
-#elif defined(CPU_MIPS74KC)
+#elif defined(CPU_MIPS74K)
#define HAZARD_DELAY sll $0,$0,3
#define ITLBNOPFIX sll $0,$0,3
#else
diff --git a/sys/mips/include/cpufunc.h b/sys/mips/include/cpufunc.h
index 6ffb0ba1c099..3ebb8c14b448 100644
--- a/sys/mips/include/cpufunc.h
+++ b/sys/mips/include/cpufunc.h
@@ -248,7 +248,7 @@ MIPS_RW32_COP0_SEL(config5, MIPS_COP_0_CONFIG, 5);
#if defined(CPU_NLM) || defined(BERI_LARGE_TLB)
MIPS_RW32_COP0_SEL(config6, MIPS_COP_0_CONFIG, 6);
#endif
-#if defined(CPU_NLM) || defined(CPU_MIPS1004KC)
+#if defined(CPU_NLM) || defined(CPU_MIPS1004K)
MIPS_RW32_COP0_SEL(config7, MIPS_COP_0_CONFIG, 7);
#endif
MIPS_RW32_COP0(count, MIPS_COP_0_COUNT);
diff --git a/sys/mips/include/cpuregs.h b/sys/mips/include/cpuregs.h
index 976321ab318b..a1d9bc0195da 100644
--- a/sys/mips/include/cpuregs.h
+++ b/sys/mips/include/cpuregs.h
@@ -110,6 +110,7 @@
* C: Cacheable, coherency unspecified.
* CNC: Cacheable non-coherent.
* CC: Cacheable coherent.
+ * CCS: Cacheable coherent, shared read.
* CCE: Cacheable coherent, exclusive read.
* CCEW: Cacheable coherent, exclusive write.
* CCUOW: Cacheable coherent, update on write.
@@ -149,14 +150,25 @@
#define MIPS_CCA_CC 0x05 /* Cacheable Coherent. */
#endif
-#if defined(CPU_MIPS74KC)
+#if defined(CPU_MIPS74K)
#define MIPS_CCA_UNCACHED 0x02
#define MIPS_CCA_CACHED 0x03
#endif
-#if defined(CPU_MIPS1004KC)
-#define MIPS_CCA_UNCACHED 0x02
-#define MIPS_CCA_CACHED 0x05
+/*
+ * 1004K and 1074K cores, as well as interAptiv and proAptiv cores, support
+ * Cacheable Coherent CCAs 0x04 and 0x05, as well as Cacheable non-Coherent
+ * CCA 0x03 and Uncached Accelerated CCA 0x07
+ */
+#if defined(CPU_MIPS1004K) || defined(CPU_MIPS1074K) || \
+ defined(CPU_INTERAPTIV) || defined(CPU_PROAPTIV)
+#define MIPS_CCA_CNC 0x03
+#define MIPS_CCA_CCE 0x04
+#define MIPS_CCA_CCS 0x05
+#define MIPS_CCA_UA 0x07
+
+/* We use shared read CCA for CACHED CCA */
+#define MIPS_CCA_CACHED MIPS_CCA_CCS
#endif
#ifndef MIPS_CCA_UNCACHED
@@ -214,8 +226,18 @@
#define COP0_SYNC .word 0xc0 /* ehb */
#elif defined(CPU_SB1)
#define COP0_SYNC ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop
-#elif defined(CPU_MIPS74KC) || defined(CPU_MIPS1004KC)
-#define COP0_SYNC .word 0xc0 /* ehb */
+#elif defined(CPU_MIPS24K) || defined(CPU_MIPS34K) || \
+ defined(CPU_MIPS74K) || defined(CPU_MIPS1004K) || \
+ defined(CPU_MIPS1074K) || defined(CPU_INTERAPTIV) || \
+ defined(CPU_PROAPTIV)
+/*
+ * According to MIPS32tm Architecture for Programmers, Vol.II, rev. 2.00:
+ * "As EHB becomes standard in MIPS implementations, the previous SSNOPs can be
+ * removed, leaving only the EHB".
+ * Also, all MIPS32 Release 2 implementations have the EHB instruction, which
+ * resolves all execution hazards. The same goes for MIPS32 Release 3.
+ */
+#define COP0_SYNC .word 0xc0 /* ehb */
#else
/*
* Pick a reasonable default based on the "typical" spacing described in the
diff --git a/sys/mips/mips/uma_machdep.c b/sys/mips/mips/uma_machdep.c
index b4006e1ead12..7014703b712a 100644
--- a/sys/mips/mips/uma_machdep.c
+++ b/sys/mips/mips/uma_machdep.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/systm.h>
+#include <sys/taskqueue.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <vm/vm_pageout.h>
diff --git a/sys/mips/mips/vm_machdep.c b/sys/mips/mips/vm_machdep.c
index f952eccbe777..03fc60e36ccc 100644
--- a/sys/mips/mips/vm_machdep.c
+++ b/sys/mips/mips/vm_machdep.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <sys/unistd.h>
+#include <sys/taskqueue.h>
#include <machine/cache.h>
#include <machine/clock.h>
diff --git a/sys/mips/rt305x/std.rt305x b/sys/mips/rt305x/std.rt305x
index c7212a2c6d3e..d0e09b3b6b07 100644
--- a/sys/mips/rt305x/std.rt305x
+++ b/sys/mips/rt305x/std.rt305x
@@ -3,5 +3,5 @@
files "../rt305x/files.rt305x"
-cpu CPU_MIPS4KC
+cpu CPU_MIPS24K
diff --git a/sys/modules/filemon/Makefile b/sys/modules/filemon/Makefile
index 80cc0a095abf..b97b2e2fbbd3 100644
--- a/sys/modules/filemon/Makefile
+++ b/sys/modules/filemon/Makefile
@@ -4,6 +4,6 @@
KMOD= filemon
SRCS= ${KMOD}.c
-SRCS+= opt_compat.h
+SRCS+= opt_compat.h vnode_if.h
.include <bsd.kmod.mk>
diff --git a/sys/net/bridgestp.c b/sys/net/bridgestp.c
index bd5ef9f906e6..d6e118cb5891 100644
--- a/sys/net/bridgestp.c
+++ b/sys/net/bridgestp.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/callout.h>
#include <sys/module.h>
#include <sys/proc.h>
diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c
index fd7a757c9f86..6c14037f3d02 100644
--- a/sys/net/if_epair.c
+++ b/sys/net/if_epair.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/refcount.h>
diff --git a/sys/net/if_mib.c b/sys/net/if_mib.c
index a9840caa68c2..590664268667 100644
--- a/sys/net/if_mib.c
+++ b/sys/net/if_mib.c
@@ -32,6 +32,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
diff --git a/sys/net/netisr.c b/sys/net/netisr.c
index 4b3576ded2ae..64efbd772b6e 100644
--- a/sys/net/netisr.c
+++ b/sys/net/netisr.c
@@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
+#include <sys/malloc.h>
#include <sys/interrupt.h>
#include <sys/lock.h>
#include <sys/mbuf.h>
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 2a7182e78b9f..ed23eb5b20a7 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -36,8 +36,10 @@
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/counter.h>
+#include <sys/malloc.h>
#include <sys/refcount.h>
#include <sys/tree.h>
+#include <vm/uma.h>
#include <net/radix.h>
#include <netinet/in.h>
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c
index ca27cb13f249..a1c70401748d 100644
--- a/sys/net80211/ieee80211.c
+++ b/sys/net80211/ieee80211.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/sbuf.h>
diff --git a/sys/net80211/ieee80211_acl.c b/sys/net80211/ieee80211_acl.c
index eeb7f0bc68da..58679b0b1765 100644
--- a/sys/net80211/ieee80211_acl.c
+++ b/sys/net80211/ieee80211_acl.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/queue.h>
diff --git a/sys/net80211/ieee80211_action.c b/sys/net80211/ieee80211_action.c
index e37863ee12fb..9c7598932970 100644
--- a/sys/net80211/ieee80211_action.c
+++ b/sys/net80211/ieee80211_action.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/systm.h>
#include <sys/socket.h>
diff --git a/sys/net80211/ieee80211_ageq.c b/sys/net80211/ieee80211_ageq.c
index b650136c05be..d282fccf9bb4 100644
--- a/sys/net80211/ieee80211_ageq.c
+++ b/sys/net80211/ieee80211_ageq.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/socket.h>
diff --git a/sys/net80211/ieee80211_amrr.c b/sys/net80211/ieee80211_amrr.c
index b7c11fd2417b..f50334e9af1b 100644
--- a/sys/net80211/ieee80211_amrr.c
+++ b/sys/net80211/ieee80211_amrr.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
diff --git a/sys/net80211/ieee80211_crypto_none.c b/sys/net80211/ieee80211_crypto_none.c
index 30f2fc38882a..fef4c0946b20 100644
--- a/sys/net80211/ieee80211_crypto_none.c
+++ b/sys/net80211/ieee80211_crypto_none.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/module.h>
diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c
index ae4910c6ee0d..de7a243098de 100644
--- a/sys/net80211/ieee80211_ddb.c
+++ b/sys/net80211/ieee80211_ddb.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/socket.h>
#include <net/if.h>
diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c
index 0ccf378fff6d..57cbbf57056e 100644
--- a/sys/net80211/ieee80211_freebsd.c
+++ b/sys/net80211/ieee80211_freebsd.c
@@ -32,10 +32,11 @@ __FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
-#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/eventhandler.h>
+#include <sys/kernel.h>
#include <sys/linker.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/proc.h>
diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c
index e6fe16e58fa5..1a217346f811 100644
--- a/sys/net80211/ieee80211_ht.c
+++ b/sys/net80211/ieee80211_ht.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/systm.h>
#include <sys/endian.h>
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index e78b86221121..bdaac4810df0 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/priv.h>
#include <sys/socket.h>
#include <sys/sockio.h>
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index 322491d25a2c..42046807abaf 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -33,8 +33,9 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/mbuf.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
#include <sys/endian.h>
#include <sys/socket.h>
diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c
index 73c1382b1218..587e48f07d3f 100644
--- a/sys/net80211/ieee80211_power.c
+++ b/sys/net80211/ieee80211_power.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/socket.h>
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index 408bf935b92c..1b8b5249946a 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -35,8 +35,9 @@ __FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
-#include <sys/kernel.h>
#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/sockio.h>
diff --git a/sys/net80211/ieee80211_scan.c b/sys/net80211/ieee80211_scan.c
index f28a9829d60d..8bc5d2eed0d1 100644
--- a/sys/net80211/ieee80211_scan.c
+++ b/sys/net80211/ieee80211_scan.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/condvar.h>
#include <sys/socket.h>
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c
index ea922d7e82a3..accf6c8cd299 100644
--- a/sys/net80211/ieee80211_scan_sta.c
+++ b/sys/net80211/ieee80211_scan_sta.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/socket.h>
diff --git a/sys/net80211/ieee80211_scan_sw.c b/sys/net80211/ieee80211_scan_sw.c
index 53e45203f10c..52f6ea7210b8 100644
--- a/sys/net80211/ieee80211_scan_sw.c
+++ b/sys/net80211/ieee80211_scan_sw.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/condvar.h>
#include <sys/socket.h>
diff --git a/sys/net80211/ieee80211_xauth.c b/sys/net80211/ieee80211_xauth.c
index 2341ffb162e9..1e57e16af646 100644
--- a/sys/net80211/ieee80211_xauth.c
+++ b/sys/net80211/ieee80211_xauth.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
diff --git a/sys/netgraph/netflow/netflow.c b/sys/netgraph/netflow/netflow.c
index 6adffc9e6072..84dee4767240 100644
--- a/sys/netgraph/netflow/netflow.c
+++ b/sys/netgraph/netflow/netflow.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mbuf.h>
#include <sys/syslog.h>
#include <sys/socket.h>
+#include <vm/uma.h>
#include <net/if.h>
#include <net/if_dl.h>
diff --git a/sys/netgraph/netflow/netflow_v9.c b/sys/netgraph/netflow/netflow_v9.c
index 2fc700d5d4f7..5124bbd48075 100644
--- a/sys/netgraph/netflow/netflow_v9.c
+++ b/sys/netgraph/netflow/netflow_v9.c
@@ -37,9 +37,11 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/limits.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/syslog.h>
#include <sys/socket.h>
+#include <vm/uma.h>
#include <net/if.h>
#include <net/route.h>
diff --git a/sys/netgraph/netflow/ng_netflow.c b/sys/netgraph/netflow/ng_netflow.c
index b524ca51fcbd..4f9f953c6f91 100644
--- a/sys/netgraph/netflow/ng_netflow.c
+++ b/sys/netgraph/netflow/ng_netflow.c
@@ -40,10 +40,12 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/limits.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/syslog.h>
#include <sys/ctype.h>
+#include <vm/uma.h>
#include <net/if.h>
#include <net/ethernet.h>
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c
index 673dc25045f6..0f48e12a8759 100644
--- a/sys/netgraph/ng_base.c
+++ b/sys/netgraph/ng_base.c
@@ -63,6 +63,7 @@
#include <sys/syslog.h>
#include <sys/unistd.h>
#include <machine/cpu.h>
+#include <vm/uma.h>
#include <net/netisr.h>
#include <net/vnet.h>
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index 0ac91c72bb88..e7569c45f740 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/domain.h>
#include <sys/proc.h>
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 9edfcf67808a..a6f625d13a11 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -85,7 +85,7 @@ static void
sctp_handle_init(struct mbuf *m, int iphlen, int offset,
struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh,
struct sctp_init_chunk *cp, struct sctp_inpcb *inp,
- struct sctp_tcb *stcb, int *abort_no_unlock,
+ struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_no_unlock,
uint8_t mflowtype, uint32_t mflowid,
uint32_t vrf_id, uint16_t port)
{
@@ -198,8 +198,8 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset,
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
} else {
SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending INIT-ACK\n");
- sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, src, dst,
- sh, cp,
+ sctp_send_initiate_ack(inp, stcb, net, m, iphlen, offset,
+ src, dst, sh, cp,
mflowtype, mflowid,
vrf_id, port,
((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED));
@@ -4840,7 +4840,7 @@ process_control_chunks:
}
sctp_handle_init(m, iphlen, *offset, src, dst, sh,
(struct sctp_init_chunk *)ch, inp,
- stcb, &abort_no_unlock,
+ stcb, *netp, &abort_no_unlock,
mflowtype, mflowid,
vrf_id, port);
*offset = length;
@@ -5684,9 +5684,18 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
stcb = sctp_findassociation_addr(m, offset, src, dst,
sh, ch, &inp, &net, vrf_id);
#if defined(INET) || defined(INET6)
- if ((net != NULL) && (port != 0)) {
+ if ((ch->chunk_type != SCTP_INITIATION) &&
+ (net != NULL) && (net->port != port)) {
if (net->port == 0) {
- sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
+ /* UDP encapsulation turned on. */
+ net->mtu -= sizeof(struct udphdr);
+ if (stcb->asoc.smallest_mtu > net->mtu) {
+ sctp_pathmtu_adjustment(stcb, net->mtu);
+ }
+ } else if (port == 0) {
+ /* UDP encapsulation turned off. */
+ net->mtu += sizeof(struct udphdr);
+ /* XXX Update smallest_mtu */
}
net->port = port;
}
@@ -5715,9 +5724,18 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
stcb = sctp_findassociation_addr(m, offset, src, dst,
sh, ch, &inp, &net, vrf_id);
#if defined(INET) || defined(INET6)
- if ((net != NULL) && (port != 0)) {
+ if ((ch->chunk_type != SCTP_INITIATION) &&
+ (net != NULL) && (net->port != port)) {
if (net->port == 0) {
- sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
+ /* UDP encapsulation turned on. */
+ net->mtu -= sizeof(struct udphdr);
+ if (stcb->asoc.smallest_mtu > net->mtu) {
+ sctp_pathmtu_adjustment(stcb, net->mtu);
+ }
+ } else if (port == 0) {
+ /* UDP encapsulation turned off. */
+ net->mtu += sizeof(struct udphdr);
+ /* XXX Update smallest_mtu */
}
net->port = port;
}
@@ -5827,9 +5845,18 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
*/
inp = stcb->sctp_ep;
#if defined(INET) || defined(INET6)
- if ((net != NULL) && (port != 0)) {
+ if ((ch->chunk_type != SCTP_INITIATION) &&
+ (net != NULL) && (net->port != port)) {
if (net->port == 0) {
- sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
+ /* UDP encapsulation turned on. */
+ net->mtu -= sizeof(struct udphdr);
+ if (stcb->asoc.smallest_mtu > net->mtu) {
+ sctp_pathmtu_adjustment(stcb, net->mtu);
+ }
+ } else if (port == 0) {
+ /* UDP encapsulation turned off. */
+ net->mtu += sizeof(struct udphdr);
+ /* XXX Update smallest_mtu */
}
net->port = port;
}
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 95ac97c903dd..017261000189 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -5307,6 +5307,7 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
uint16_t ptype, plen;
uint8_t fnd;
struct sctp_nets *net;
+ int check_src;
#ifdef INET
struct sockaddr_in sin4, *sa4;
@@ -5328,39 +5329,61 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
sin6.sin6_len = sizeof(sin6);
#endif
/* First what about the src address of the pkt ? */
- fnd = 0;
- TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- sa = (struct sockaddr *)&net->ro._l_addr;
- if (sa->sa_family == src->sa_family) {
+ check_src = 0;
+ switch (src->sa_family) {
#ifdef INET
- if (sa->sa_family == AF_INET) {
- struct sockaddr_in *src4;
+ case AF_INET:
+ if (asoc->scope.ipv4_addr_legal) {
+ check_src = 1;
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (asoc->scope.ipv6_addr_legal) {
+ check_src = 1;
+ }
+ break;
+#endif
+ default:
+ /* TSNH */
+ break;
+ }
+ if (check_src) {
+ fnd = 0;
+ TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
+ sa = (struct sockaddr *)&net->ro._l_addr;
+ if (sa->sa_family == src->sa_family) {
+#ifdef INET
+ if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *src4;
- sa4 = (struct sockaddr_in *)sa;
- src4 = (struct sockaddr_in *)src;
- if (sa4->sin_addr.s_addr == src4->sin_addr.s_addr) {
- fnd = 1;
- break;
+ sa4 = (struct sockaddr_in *)sa;
+ src4 = (struct sockaddr_in *)src;
+ if (sa4->sin_addr.s_addr == src4->sin_addr.s_addr) {
+ fnd = 1;
+ break;
+ }
}
- }
#endif
#ifdef INET6
- if (sa->sa_family == AF_INET6) {
- struct sockaddr_in6 *src6;
+ if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *src6;
- sa6 = (struct sockaddr_in6 *)sa;
- src6 = (struct sockaddr_in6 *)src;
- if (SCTP6_ARE_ADDR_EQUAL(sa6, src6)) {
- fnd = 1;
- break;
+ sa6 = (struct sockaddr_in6 *)sa;
+ src6 = (struct sockaddr_in6 *)src;
+ if (SCTP6_ARE_ADDR_EQUAL(sa6, src6)) {
+ fnd = 1;
+ break;
+ }
}
- }
#endif
+ }
+ }
+ if (fnd == 0) {
+ /* New address added! no need to look futher. */
+ return (1);
}
- }
- if (fnd == 0) {
- /* New address added! no need to look futher. */
- return (1);
}
/* Ok so far lets munge through the rest of the packet */
offset += sizeof(struct sctp_init_chunk);
@@ -5381,9 +5404,11 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
phdr == NULL) {
return (1);
}
- p4 = (struct sctp_ipv4addr_param *)phdr;
- sin4.sin_addr.s_addr = p4->addr;
- sa_touse = (struct sockaddr *)&sin4;
+ if (asoc->scope.ipv4_addr_legal) {
+ p4 = (struct sctp_ipv4addr_param *)phdr;
+ sin4.sin_addr.s_addr = p4->addr;
+ sa_touse = (struct sockaddr *)&sin4;
+ }
break;
}
#endif
@@ -5398,10 +5423,12 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
phdr == NULL) {
return (1);
}
- p6 = (struct sctp_ipv6addr_param *)phdr;
- memcpy((caddr_t)&sin6.sin6_addr, p6->addr,
- sizeof(p6->addr));
- sa_touse = (struct sockaddr *)&sin6;
+ if (asoc->scope.ipv6_addr_legal) {
+ p6 = (struct sctp_ipv6addr_param *)phdr;
+ memcpy((caddr_t)&sin6.sin6_addr, p6->addr,
+ sizeof(p6->addr));
+ sa_touse = (struct sockaddr *)&sin6;
+ }
break;
}
#endif
@@ -5457,7 +5484,8 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
*/
void
sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- struct mbuf *init_pkt, int iphlen, int offset,
+ struct sctp_nets *src_net, struct mbuf *init_pkt,
+ int iphlen, int offset,
struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, struct sctp_init_chunk *init_chk,
uint8_t mflowtype, uint32_t mflowid,
@@ -5501,20 +5529,39 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asoc = NULL;
}
if ((asoc != NULL) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) &&
- (sctp_are_there_new_addresses(asoc, init_pkt, offset, src))) {
- /* new addresses, out of here in non-cookie-wait states */
- /*
- * Send a ABORT, we don't add the new address error clause
- * though we even set the T bit and copy in the 0 tag.. this
- * looks no different than if no listener was present.
- */
- op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
- "Address added");
- sctp_send_abort(init_pkt, iphlen, src, dst, sh, 0, op_err,
- mflowtype, mflowid, inp->fibnum,
- vrf_id, port);
- return;
+ (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT)) {
+ if (sctp_are_there_new_addresses(asoc, init_pkt, offset, src)) {
+ /*
+ * new addresses, out of here in non-cookie-wait
+ * states
+ *
+ * Send an ABORT, without the new address error cause.
+ * This looks no different than if no listener was
+ * present.
+ */
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ "Address added");
+ sctp_send_abort(init_pkt, iphlen, src, dst, sh, 0, op_err,
+ mflowtype, mflowid, inp->fibnum,
+ vrf_id, port);
+ return;
+ }
+ if (src_net != NULL && (src_net->port != port)) {
+ /*
+ * change of remote encapsulation port, out of here
+ * in non-cookie-wait states
+ *
+ * Send an ABORT, without an specific error cause. This
+ * looks no different than if no listener was
+ * present.
+ */
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ "Remote encapsulation port changed");
+ sctp_send_abort(init_pkt, iphlen, src, dst, sh, 0, op_err,
+ mflowtype, mflowid, inp->fibnum,
+ vrf_id, port);
+ return;
+ }
}
abort_flag = 0;
op_err = sctp_arethere_unrecognized_parameters(init_pkt,
diff --git a/sys/netinet/sctp_output.h b/sys/netinet/sctp_output.h
index d7222c44bf51..b2441a6fe0b6 100644
--- a/sys/netinet/sctp_output.h
+++ b/sys/netinet/sctp_output.h
@@ -80,7 +80,8 @@ sctp_send_initiate(struct sctp_inpcb *, struct sctp_tcb *, int
);
void
-sctp_send_initiate_ack(struct sctp_inpcb *, struct sctp_tcb *, struct mbuf *,
+sctp_send_initiate_ack(struct sctp_inpcb *, struct sctp_tcb *,
+ struct sctp_nets *, struct mbuf *,
int, int,
struct sockaddr *, struct sockaddr *,
struct sctphdr *, struct sctp_init_chunk *,
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index d4a9dff0bb22..a3efcab0a575 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -2256,7 +2256,6 @@ sctp_findassociation_addr(struct mbuf *m, int offset,
struct sctphdr *sh, struct sctp_chunkhdr *ch,
struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id)
{
- int find_tcp_pool;
struct sctp_tcb *stcb;
struct sctp_inpcb *inp;
@@ -2268,25 +2267,13 @@ sctp_findassociation_addr(struct mbuf *m, int offset,
return (stcb);
}
}
- find_tcp_pool = 0;
- /*
- * Don't consider INIT chunks since that breaks 1-to-1 sockets: When
- * a server closes the listener, incoming INIT chunks are not
- * responsed by an INIT-ACK chunk.
- */
- if ((ch->chunk_type != SCTP_INITIATION_ACK) &&
- (ch->chunk_type != SCTP_COOKIE_ACK) &&
- (ch->chunk_type != SCTP_COOKIE_ECHO)) {
- /* Other chunk types go to the tcp pool. */
- find_tcp_pool = 1;
- }
if (inp_p) {
stcb = sctp_findassociation_addr_sa(src, dst, inp_p, netp,
- find_tcp_pool, vrf_id);
+ 1, vrf_id);
inp = *inp_p;
} else {
stcb = sctp_findassociation_addr_sa(src, dst, &inp, netp,
- find_tcp_pool, vrf_id);
+ 1, vrf_id);
}
SCTPDBG(SCTP_DEBUG_PCB1, "stcb:%p inp:%p\n", (void *)stcb, (void *)inp);
if (stcb == NULL && inp) {
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index b72e896cd223..e19793679984 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -426,7 +426,11 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS)
xinpcb.maxqlen = 0;
} else {
xinpcb.qlen = so->so_qlen;
+ xinpcb.qlen_old = so->so_qlen > USHRT_MAX ?
+ USHRT_MAX : (uint16_t) so->so_qlen;
xinpcb.maxqlen = so->so_qlimit;
+ xinpcb.maxqlen_old = so->so_qlimit > USHRT_MAX ?
+ USHRT_MAX : (uint16_t) so->so_qlimit;
}
SCTP_INP_INCR_REF(inp);
SCTP_INP_RUNLOCK(inp);
diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h
index cfc79788adda..2299f66fa51d 100644
--- a/sys/netinet/sctp_uio.h
+++ b/sys/netinet/sctp_uio.h
@@ -1170,13 +1170,15 @@ struct xsctp_inpcb {
uint32_t total_nospaces;
uint32_t fragmentation_point;
uint16_t local_port;
- uint16_t qlen;
- uint16_t maxqlen;
+ uint16_t qlen_old;
+ uint16_t maxqlen_old;
void *socket;
+ uint32_t qlen;
+ uint32_t maxqlen;
#if defined(__LP64__)
- uint32_t extra_padding[29]; /* future */
+ uint32_t extra_padding[27]; /* future */
#else
- uint32_t extra_padding[30]; /* future */
+ uint32_t extra_padding[28]; /* future */
#endif
};
diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h
index ae1b3eb3089d..7213b97684bd 100644
--- a/sys/netinet/sctp_var.h
+++ b/sys/netinet/sctp_var.h
@@ -86,7 +86,7 @@ extern struct pr_usrreqs sctp_usrreqs;
#define sctp_sbspace_failedmsgs(sb) ((long) ((sctp_maxspace(sb) > (sb)->sb_cc) ? (sctp_maxspace(sb) - (sb)->sb_cc) : 0))
-#define sctp_sbspace_sub(a,b) ((a > b) ? (a - b) : 0)
+#define sctp_sbspace_sub(a,b) (((a) > (b)) ? ((a) - (b)) : 0)
/*
* I tried to cache the readq entries at one point. But the reality
diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c
index 566334348810..d49071c50d28 100644
--- a/sys/netinet/tcp_lro.c
+++ b/sys/netinet/tcp_lro.c
@@ -38,8 +38,9 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/mbuf.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
#include <sys/socket.h>
#include <net/if.h>
diff --git a/sys/netinet/toecore.c b/sys/netinet/toecore.c
index cfa77e76a128..4bca16c09120 100644
--- a/sys/netinet/toecore.c
+++ b/sys/netinet/toecore.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/types.h>
diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c
index 4d328d282ec3..cad09316cf94 100644
--- a/sys/netinet6/in6_proto.c
+++ b/sys/netinet6/in6_proto.c
@@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
#include <sys/protosw.h>
#include <sys/jail.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/domain.h>
#include <sys/mbuf.h>
#include <sys/systm.h>
diff --git a/sys/netinet6/send.c b/sys/netinet6/send.c
index b946ded155d1..66b36db7827b 100644
--- a/sys/netinet6/send.c
+++ b/sys/netinet6/send.c
@@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/priv.h>
diff --git a/sys/netipsec/ipsec_mbuf.c b/sys/netipsec/ipsec_mbuf.c
index 8e68ffb41c6f..b3df0e01cc50 100644
--- a/sys/netipsec/ipsec_mbuf.c
+++ b/sys/netipsec/ipsec_mbuf.c
@@ -34,6 +34,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
diff --git a/sys/netipsec/key_debug.c b/sys/netipsec/key_debug.c
index b5bdb0ed42ca..4aad7433ee7a 100644
--- a/sys/netipsec/key_debug.c
+++ b/sys/netipsec/key_debug.c
@@ -36,10 +36,10 @@
#include "opt_ipsec.h"
#endif
-#include <sys/types.h>
#include <sys/param.h>
#ifdef _KERNEL
#include <sys/systm.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/queue.h>
#endif
diff --git a/sys/netpfil/ipfw/ip_fw_log.c b/sys/netpfil/ipfw/ip_fw_log.c
index 29374f949015..236c4f1f19d7 100644
--- a/sys/netpfil/ipfw/ip_fw_log.c
+++ b/sys/netpfil/ipfw/ip_fw_log.c
@@ -39,8 +39,9 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/mbuf.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
diff --git a/sys/powerpc/fpu/fpu_emu.c b/sys/powerpc/fpu/fpu_emu.c
index 82074aab868f..011b9999db99 100644
--- a/sys/powerpc/fpu/fpu_emu.c
+++ b/sys/powerpc/fpu/fpu_emu.c
@@ -183,7 +183,7 @@ fpu_dumpfpn(struct fpn *fp)
* (Typically: zero, SIGFPE, SIGILL, SIGSEGV)
*/
int
-fpu_emulate(struct trapframe *frame, struct fpreg *fpf)
+fpu_emulate(struct trapframe *frame, struct fpu *fpf)
{
static union instr insn;
static struct fpemu fe;
@@ -275,7 +275,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
vm_offset_t addr;
int ra, rb, rc, rt, type, mask, fsr, cx, bf, setcr;
unsigned int cond;
- struct fpreg *fs;
+ struct fpu *fs;
/* Setup work. */
fp = NULL;
@@ -335,7 +335,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
if (ra != 0)
addr += tf->fixreg[ra];
rt = instr.i_x.i_rt;
- a = (int *)&fs->fpreg[rt].fpr;
+ a = (int *)&fs->fpr[rt].fpr;
DPRINTF(FPE_INSN,
("fpu_execute: Store INT %x at %p\n",
a[1], (void *)addr));
@@ -402,7 +402,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
DPRINTF(FPE_INSN,
("fpu_execute: Store DBL at %p\n",
(void *)addr));
- if (copyout(&fs->fpreg[rt].fpr, (void *)addr,
+ if (copyout(&fs->fpr[rt].fpr, (void *)addr,
size))
return (FAULT);
}
@@ -411,13 +411,13 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
FPU_EMU_EVCNT_INCR(fpload);
DPRINTF(FPE_INSN, ("fpu_execute: Load from %p\n",
(void *)addr));
- if (copyin((const void *)addr, &fs->fpreg[rt].fpr,
+ if (copyin((const void *)addr, &fs->fpr[rt].fpr,
size))
return (FAULT);
if (type != FTYPE_DBL) {
fpu_explode(fe, fp = &fe->fe_f1, type, rt);
fpu_implode(fe, fp, FTYPE_DBL,
- (u_int *)&fs->fpreg[rt].fpr);
+ (u_int *)&fs->fpr[rt].fpr);
}
}
if (update)
@@ -470,7 +470,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
DPRINTF(FPE_INSN, ("fpu_execute: FRSP\n"));
fpu_explode(fe, fp = &fe->fe_f1, FTYPE_DBL, rb);
fpu_implode(fe, fp, FTYPE_SNG,
- (u_int *)&fs->fpreg[rt].fpr);
+ (u_int *)&fs->fpr[rt].fpr);
fpu_explode(fe, fp = &fe->fe_f1, FTYPE_SNG, rt);
type = FTYPE_DBL;
break;
@@ -503,9 +503,9 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
case OPC63_FNEG:
FPU_EMU_EVCNT_INCR(fnegabs);
DPRINTF(FPE_INSN, ("fpu_execute: FNEGABS\n"));
- memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr,
+ memcpy(&fs->fpr[rt].fpr, &fs->fpr[rb].fpr,
sizeof(double));
- a = (int *)&fs->fpreg[rt].fpr;
+ a = (int *)&fs->fpr[rt].fpr;
*a ^= (1U << 31);
break;
case OPC63_MCRFS:
@@ -533,7 +533,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
case OPC63_FMR:
FPU_EMU_EVCNT_INCR(fmr);
DPRINTF(FPE_INSN, ("fpu_execute: FMR\n"));
- memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr,
+ memcpy(&fs->fpr[rt].fpr, &fs->fpr[rb].fpr,
sizeof(double));
break;
case OPC63_MTFSFI:
@@ -550,23 +550,23 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
case OPC63_FNABS:
FPU_EMU_EVCNT_INCR(fnabs);
DPRINTF(FPE_INSN, ("fpu_execute: FABS\n"));
- memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr,
+ memcpy(&fs->fpr[rt].fpr, &fs->fpr[rb].fpr,
sizeof(double));
- a = (int *)&fs->fpreg[rt].fpr;
+ a = (int *)&fs->fpr[rt].fpr;
*a |= (1U << 31);
break;
case OPC63_FABS:
FPU_EMU_EVCNT_INCR(fabs);
DPRINTF(FPE_INSN, ("fpu_execute: FABS\n"));
- memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr,
+ memcpy(&fs->fpr[rt].fpr, &fs->fpr[rb].fpr,
sizeof(double));
- a = (int *)&fs->fpreg[rt].fpr;
+ a = (int *)&fs->fpr[rt].fpr;
*a &= ~(1U << 31);
break;
case OPC63_MFFS:
FPU_EMU_EVCNT_INCR(mffs);
DPRINTF(FPE_INSN, ("fpu_execute: MFFS\n"));
- memcpy(&fs->fpreg[rt].fpr, &fs->fpscr,
+ memcpy(&fs->fpr[rt].fpr, &fs->fpscr,
sizeof(fs->fpscr));
break;
case OPC63_MTFSF:
@@ -581,7 +581,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
if (rt & (1<<ra))
mask |= (0xf<<(4*ra));
}
- a = (int *)&fs->fpreg[rt].fpr;
+ a = (int *)&fs->fpr[rt].fpr;
fe->fe_cx = mask & a[1];
fe->fe_fpscr = (fe->fe_fpscr&~mask) |
(fe->fe_cx);
@@ -648,12 +648,12 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
case OPC63M_FSEL:
FPU_EMU_EVCNT_INCR(fsel);
DPRINTF(FPE_INSN, ("fpu_execute: FSEL\n"));
- a = (int *)&fe->fe_fpstate->fpreg[ra].fpr;
+ a = (int *)&fe->fe_fpstate->fpr[ra].fpr;
if ((*a & 0x80000000) && (*a & 0x7fffffff))
/* fra < 0 */
rc = rb;
DPRINTF(FPE_INSN, ("f%d => f%d\n", rc, rt));
- memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rc].fpr,
+ memcpy(&fs->fpr[rt].fpr, &fs->fpr[rc].fpr,
sizeof(double));
break;
case OPC59_FRES:
@@ -662,7 +662,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
fpu_explode(fe, &fe->fe_f1, type, rb);
fp = fpu_sqrt(fe);
/* now we've gotta overwrite the dest reg */
- *((int *)&fe->fe_fpstate->fpreg[rt].fpr) = 1;
+ *((int *)&fe->fe_fpstate->fpr[rt].fpr) = 1;
fpu_explode(fe, &fe->fe_f1, FTYPE_INT, rt);
fpu_div(fe);
break;
@@ -681,7 +681,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
fp = fpu_sqrt(fe);
fe->fe_f2 = *fp;
/* now we've gotta overwrite the dest reg */
- *((int *)&fe->fe_fpstate->fpreg[rt].fpr) = 1;
+ *((int *)&fe->fe_fpstate->fpr[rt].fpr) = 1;
fpu_explode(fe, &fe->fe_f1, FTYPE_INT, rt);
fpu_div(fe);
break;
@@ -737,7 +737,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
/* If the instruction was single precision, round */
if (!(instr.i_any.i_opcd & 0x4)) {
fpu_implode(fe, fp, FTYPE_SNG,
- (u_int *)&fs->fpreg[rt].fpr);
+ (u_int *)&fs->fpr[rt].fpr);
fpu_explode(fe, fp = &fe->fe_f1, FTYPE_SNG, rt);
}
}
@@ -752,7 +752,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
* Otherwise set new current exceptions and accrue.
*/
if (fp)
- fpu_implode(fe, fp, type, (u_int *)&fs->fpreg[rt].fpr);
+ fpu_implode(fe, fp, type, (u_int *)&fs->fpr[rt].fpr);
cx = fe->fe_cx;
fsr = fe->fe_fpscr;
if (cx != 0) {
diff --git a/sys/powerpc/fpu/fpu_emu.h b/sys/powerpc/fpu/fpu_emu.h
index 89ccc3611528..30e617e474ec 100644
--- a/sys/powerpc/fpu/fpu_emu.h
+++ b/sys/powerpc/fpu/fpu_emu.h
@@ -138,7 +138,7 @@ struct fpn {
* Emulator state.
*/
struct fpemu {
- struct fpreg *fe_fpstate; /* registers, etc */
+ struct fpu *fe_fpstate; /* registers, etc */
int fe_fpscr; /* fpscr copy (modified during op) */
int fe_cx; /* keep track of exceptions */
struct fpn fe_f1; /* operand 1 */
diff --git a/sys/powerpc/fpu/fpu_explode.c b/sys/powerpc/fpu/fpu_explode.c
index 1ebd96eccdc4..84073a4edb26 100644
--- a/sys/powerpc/fpu/fpu_explode.c
+++ b/sys/powerpc/fpu/fpu_explode.c
@@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$");
#include <machine/fpu.h>
#include <machine/ieee.h>
-#include <machine/reg.h>
+#include <machine/pcb.h>
#include <powerpc/fpu/fpu_arith.h>
#include <powerpc/fpu/fpu_emu.h>
@@ -211,9 +211,9 @@ fpu_explode(struct fpemu *fe, struct fpn *fp, int type, int reg)
u_int s, *space;
u_int64_t l, *xspace;
- xspace = (u_int64_t *)&fe->fe_fpstate->fpreg[reg].fpr;
+ xspace = (u_int64_t *)&fe->fe_fpstate->fpr[reg].fpr;
l = xspace[0];
- space = (u_int *)&fe->fe_fpstate->fpreg[reg].fpr;
+ space = (u_int *)&fe->fe_fpstate->fpr[reg].fpr;
s = space[0];
fp->fp_sign = s >> 31;
fp->fp_sticky = 0;
diff --git a/sys/powerpc/fpu/fpu_extern.h b/sys/powerpc/fpu/fpu_extern.h
index 9c24f1dab038..9f4b0132dc18 100644
--- a/sys/powerpc/fpu/fpu_extern.h
+++ b/sys/powerpc/fpu/fpu_extern.h
@@ -31,14 +31,14 @@
*/
struct proc;
-struct fpreg;
+struct fpu;
struct trapframe;
union instr;
struct fpemu;
struct fpn;
/* fpu.c */
-int fpu_emulate(struct trapframe *, struct fpreg *);
+int fpu_emulate(struct trapframe *, struct fpu *);
int fpu_execute(struct trapframe *, struct fpemu *, union instr *);
/* fpu_explode.c */
diff --git a/sys/powerpc/include/reg.h b/sys/powerpc/include/reg.h
index e77625ab8ddf..0eff51e5451e 100644
--- a/sys/powerpc/include/reg.h
+++ b/sys/powerpc/include/reg.h
@@ -18,12 +18,8 @@ struct reg {
register_t pc;
};
-/* Must match pcb.pcb_fpu */
struct fpreg {
- union {
- double fpr;
- uint64_t vsr[2];
- } fpreg[32];
+ double fpreg[32];
double fpscr;
};
diff --git a/sys/powerpc/mpc85xx/lbc.c b/sys/powerpc/mpc85xx/lbc.c
index f9a1718635a0..7dfaa06ed966 100644
--- a/sys/powerpc/mpc85xx/lbc.c
+++ b/sys/powerpc/mpc85xx/lbc.c
@@ -113,7 +113,8 @@ static driver_t lbc_driver = {
devclass_t lbc_devclass;
-DRIVER_MODULE(lbc, ofwbus, lbc_driver, lbc_devclass, 0, 0);
+EARLY_DRIVER_MODULE(lbc, ofwbus, lbc_driver, lbc_devclass,
+ 0, 0, BUS_PASS_BUS);
/*
* Calculate address mask used by OR(n) registers. Use memory region size to
diff --git a/sys/powerpc/powerpc/exec_machdep.c b/sys/powerpc/powerpc/exec_machdep.c
index d657244ffe56..4e56429ea0bb 100644
--- a/sys/powerpc/powerpc/exec_machdep.c
+++ b/sys/powerpc/powerpc/exec_machdep.c
@@ -219,10 +219,10 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
*/
if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
SIGISMEMBER(psp->ps_sigonstack, sig)) {
- usfp = (void *)((uintptr_t)td->td_sigstk.ss_sp +
- td->td_sigstk.ss_size - rndfsize);
+ usfp = (void *)(((uintptr_t)td->td_sigstk.ss_sp +
+ td->td_sigstk.ss_size - rndfsize) & ~0xFul);
} else {
- usfp = (void *)(tf->fixreg[1] - rndfsize);
+ usfp = (void *)((tf->fixreg[1] - rndfsize) & ~0xFul);
}
/*
@@ -608,13 +608,18 @@ int
fill_fpregs(struct thread *td, struct fpreg *fpregs)
{
struct pcb *pcb;
+ int i;
pcb = td->td_pcb;
if ((pcb->pcb_flags & PCB_FPREGS) == 0)
memset(fpregs, 0, sizeof(struct fpreg));
- else
- memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg));
+ else {
+ memcpy(&fpregs->fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
+ for (i = 0; i < 32; i++)
+ memcpy(&fpregs->fpreg[i], &pcb->pcb_fpu.fpr[i].fpr,
+ sizeof(double));
+ }
return (0);
}
@@ -641,10 +646,15 @@ int
set_fpregs(struct thread *td, struct fpreg *fpregs)
{
struct pcb *pcb;
+ int i;
pcb = td->td_pcb;
pcb->pcb_flags |= PCB_FPREGS;
- memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg));
+ memcpy(&pcb->pcb_fpu.fpscr, &fpregs->fpscr, sizeof(double));
+ for (i = 0; i < 32; i++) {
+ memcpy(&pcb->pcb_fpu.fpr[i].fpr, &fpregs->fpreg[i],
+ sizeof(double));
+ }
return (0);
}
@@ -1060,7 +1070,7 @@ ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb)
bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu));
pcb->pcb_flags |= PCB_FPREGS;
}
- sig = fpu_emulate(frame, (struct fpreg *)&pcb->pcb_fpu);
+ sig = fpu_emulate(frame, &pcb->pcb_fpu);
#endif
return (sig);
diff --git a/sys/powerpc/powerpc/nexus.c b/sys/powerpc/powerpc/nexus.c
index 8a4d81583f67..dff21f804146 100644
--- a/sys/powerpc/powerpc/nexus.c
+++ b/sys/powerpc/powerpc/nexus.c
@@ -189,13 +189,13 @@ nexus_activate_resource(device_t bus __unused, device_t child __unused,
{
if (type == SYS_RES_MEMORY) {
- vm_offset_t start;
+ vm_paddr_t start;
void *p;
- start = (vm_offset_t) rman_get_start(r);
+ start = (vm_paddr_t) rman_get_start(r);
if (bootverbose)
- printf("nexus mapdev: start %zx, len %ld\n", start,
- rman_get_size(r));
+ printf("nexus mapdev: start %jx, len %ld\n",
+ (uintmax_t)start, rman_get_size(r));
p = pmap_mapdev(start, (vm_size_t) rman_get_size(r));
if (p == NULL)
diff --git a/sys/powerpc/powerpc/sigcode32.S b/sys/powerpc/powerpc/sigcode32.S
index 023618215d32..cd4c3cf72f9e 100644
--- a/sys/powerpc/powerpc/sigcode32.S
+++ b/sys/powerpc/powerpc/sigcode32.S
@@ -45,9 +45,9 @@
*/
.globl CNAME(sigcode32),CNAME(szsigcode32)
CNAME(sigcode32):
- addi 1,1,-20 /* reserved space for callee */
+ addi 1,1,-32 /* reserved space for callee */
blrl
- addi 3,1,20+SF_UC /* restore sp, and get &frame->sf_uc */
+ addi 3,1,32+SF_UC /* restore sp, and get &frame->sf_uc */
li 0,SYS_sigreturn
sc /* sigreturn(scp) */
li 0,SYS_exit
diff --git a/sys/powerpc/powerpc/uma_machdep.c b/sys/powerpc/powerpc/uma_machdep.c
index d5a458f37fa2..2e023965c95d 100644
--- a/sys/powerpc/powerpc/uma_machdep.c
+++ b/sys/powerpc/powerpc/uma_machdep.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <vm/vm_kern.h>
diff --git a/sys/powerpc/ps3/ehci_ps3.c b/sys/powerpc/ps3/ehci_ps3.c
index 2d57943a422c..63c31a5de063 100644
--- a/sys/powerpc/ps3/ehci_ps3.c
+++ b/sys/powerpc/ps3/ehci_ps3.c
@@ -69,6 +69,17 @@ struct ps3_ehci_softc {
struct bus_space tag;
};
+static void
+ehci_ps3_post_reset(struct ehci_softc *ehci_softc)
+{
+ uint32_t usbmode;
+
+ /* Select big-endian mode */
+ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
+ usbmode |= EHCI_UM_ES_BE;
+ EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
+}
+
static int
ehci_ps3_probe(device_t dev)
{
@@ -135,7 +146,7 @@ ehci_ps3_attach(device_t dev)
goto error;
}
- sc->sc_flags |= EHCI_SCFLG_BIGEMMIO;
+ sc->sc_vendor_post_reset = ehci_ps3_post_reset;
err = ehci_init(sc);
if (err) {
device_printf(dev, "USB init failed err=%d\n", err);
diff --git a/sys/riscv/conf/DEFAULTS b/sys/riscv/conf/DEFAULTS
new file mode 100644
index 000000000000..5451decf822d
--- /dev/null
+++ b/sys/riscv/conf/DEFAULTS
@@ -0,0 +1,13 @@
+#
+# DEFAULTS -- Default kernel configuration file for FreeBSD/RISC-V
+#
+# $FreeBSD$
+
+machine riscv riscv64
+
+# Pseudo devices.
+device mem # Memory and kernel memory devices
+
+# Default partitioning schemes
+options GEOM_PART_BSD
+options GEOM_PART_MBR
diff --git a/sys/riscv/conf/GENERIC b/sys/riscv/conf/GENERIC
new file mode 100644
index 000000000000..a32a1f24ecfb
--- /dev/null
+++ b/sys/riscv/conf/GENERIC
@@ -0,0 +1,104 @@
+#
+# GENERIC -- Generic kernel configuration file for FreeBSD/RISC-V
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD$
+
+cpu RISCV
+ident GENERIC
+
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+# makeoptions WITH_CTF=1 # Run ctfconvert(1) for DTrace support
+makeoptions NO_MODULES=1 # We don't yet support modules on RISC-V
+
+options SCHED_ULE # ULE scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options IPSEC # IP (v4/v6) security
+options TCP_OFFLOAD # TCP offload
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options MD_ROOT # MD is a potential root device
+options NFSCL # Network Filesystem Client
+options NFSD # Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options GEOM_PART_GPT # GUID Partition Tables.
+# options GEOM_RAID # Soft RAID functionality.
+options GEOM_LABEL # Provides labelization
+options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
+options KTRACE # ktrace(1) support
+# options STACK # stack(9) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed.
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+# options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4)
+options AUDIT # Security event auditing
+options CAPABILITY_MODE # Capsicum capability mode
+options CAPABILITIES # Capsicum capabilities
+options MAC # TrustedBSD MAC Framework
+# options KDTRACE_FRAME # Ensure frames are compiled in
+# options KDTRACE_HOOKS # Kernel DTrace hooks
+# options VFP # Floating-point support
+options RACCT # Resource accounting framework
+options RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
+options RCTL # Resource limits
+# options SMP
+
+# Debugging support. Always need this:
+# options KDB # Enable kernel debugger support.
+# options KDB_TRACE # Print a stack trace for a panic.
+# For full debugger support use (turn off in stable branch):
+# options DDB # Support DDB.
+# options GDB # Support remote GDB.
+options DEADLKRES # Enable the deadlock resolver
+options INVARIANTS # Enable calls of extra sanity checking
+options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+# options WITNESS # Enable checks to detect deadlocks and cycles
+# options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones
+
+options ROOTDEVNAME=\"ufs:/dev/htif_blk0\"
+# options EARLY_PRINTF
+
+# Pseudo devices.
+device loop # Network loopback
+device random # Entropy device
+device ether # Ethernet support
+device vlan # 802.1Q VLAN support
+device tun # Packet tunnel.
+device md # Memory "disks"
+device gif # IPv6 and IPv4 tunneling
+device firmware # firmware assist module
+
+# RISCVTODO: This needs to be done via loader (when it's available).
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=spike.dts
diff --git a/sys/riscv/htif/htif.c b/sys/riscv/htif/htif.c
new file mode 100644
index 000000000000..08e6a43c2b94
--- /dev/null
+++ b/sys/riscv/htif/htif.c
@@ -0,0 +1,284 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/asm.h>
+#include <machine/trap.h>
+#include <machine/vmparam.h>
+
+#include "htif.h"
+
+static struct resource_spec htif_spec[] = {
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+struct intr_entry {
+ void (*func) (void *, uint64_t);
+ void *arg;
+};
+
+struct intr_entry intrs[HTIF_NDEV];
+
+uint64_t
+htif_command(uint64_t arg)
+{
+
+ return (machine_command(ECALL_HTIF_CMD, arg));
+}
+
+int
+htif_setup_intr(int id, void *func, void *arg)
+{
+
+ if (id >= HTIF_NDEV)
+ return (-1);
+
+ intrs[id].func = func;
+ intrs[id].arg = arg;
+
+ return (0);
+}
+
+static void
+htif_handle_entry(struct htif_softc *sc)
+{
+ uint64_t entry;
+ uint8_t devcmd;
+ uint8_t devid;
+
+ entry = machine_command(ECALL_HTIF_GET_ENTRY, 0);
+ while (entry) {
+ devid = HTIF_DEV_ID(entry);
+ devcmd = HTIF_DEV_CMD(entry);
+
+ if (devcmd == HTIF_CMD_IDENTIFY) {
+ /* Enumeration interrupt */
+ if (devid == sc->identify_id)
+ sc->identify_done = 1;
+ } else {
+ /* Device interrupt */
+ if (intrs[devid].func != NULL)
+ intrs[devid].func(intrs[devid].arg, entry);
+ }
+
+ entry = machine_command(ECALL_HTIF_GET_ENTRY, 0);
+ }
+}
+
+static int
+htif_intr(void *arg)
+{
+ struct htif_softc *sc;
+
+ sc = arg;
+
+ htif_handle_entry(sc);
+
+ csr_clear(sip, SIE_SSIE);
+
+ return (FILTER_HANDLED);
+}
+
+static int
+htif_add_device(struct htif_softc *sc, int i, char *id, char *name)
+{
+ struct htif_dev_ivars *di;
+
+ di = malloc(sizeof(struct htif_dev_ivars), M_DEVBUF, M_WAITOK | M_ZERO);
+ di->sc = sc;
+ di->index = i;
+ di->id = malloc(HTIF_ID_LEN, M_DEVBUF, M_WAITOK | M_ZERO);
+ memcpy(di->id, id, HTIF_ID_LEN);
+
+ di->dev = device_add_child(sc->dev, name, -1);
+ device_set_ivars(di->dev, di);
+
+ return (0);
+}
+
+static int
+htif_enumerate(struct htif_softc *sc)
+{
+ char id[HTIF_ID_LEN] __aligned(HTIF_ALIGN);
+ uint64_t paddr;
+ uint64_t data;
+ uint64_t cmd;
+ int len;
+ int i;
+
+ device_printf(sc->dev, "Enumerating devices\n");
+
+ for (i = 0; i < HTIF_NDEV; i++) {
+ paddr = pmap_kextract((vm_offset_t)&id);
+ data = (paddr << IDENTIFY_PADDR_SHIFT);
+ data |= IDENTIFY_IDENT;
+
+ sc->identify_id = i;
+ sc->identify_done = 0;
+
+ cmd = i;
+ cmd <<= HTIF_DEV_ID_SHIFT;
+ cmd |= (HTIF_CMD_IDENTIFY << HTIF_CMD_SHIFT);
+ cmd |= data;
+
+ htif_command(cmd);
+
+ /* Do poll as interrupts are disabled yet */
+ while (sc->identify_done == 0) {
+ htif_handle_entry(sc);
+ }
+
+ len = strnlen(id, sizeof(id));
+ if (len <= 0) {
+ continue;
+ }
+
+ if (bootverbose)
+ printf(" %d %s\n", i, id);
+
+ if (strncmp(id, "disk", 4) == 0)
+ htif_add_device(sc, i, id, "htif_blk");
+ else if (strncmp(id, "bcd", 3) == 0)
+ htif_add_device(sc, i, id, "htif_console");
+ else if (strncmp(id, "syscall_proxy", 13) == 0)
+ htif_add_device(sc, i, id, "htif_syscall_proxy");
+ }
+
+ return (bus_generic_attach(sc->dev));
+}
+
+int
+htif_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct htif_dev_ivars *ivars;
+
+ ivars = device_get_ivars(child);
+
+ switch (which) {
+ case HTIF_IVAR_INDEX:
+ *result = ivars->index;
+ break;
+ case HTIF_IVAR_ID:
+ *result = (uintptr_t)ivars->id;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+static int
+htif_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "riscv,htif"))
+ return (ENXIO);
+
+ device_set_desc(dev, "HTIF bus device");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+htif_attach(device_t dev)
+{
+ struct htif_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ if (bus_alloc_resources(dev, htif_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Setup IRQs handler */
+ error = bus_setup_intr(dev, sc->res[0], INTR_TYPE_CLK,
+ htif_intr, NULL, sc, &sc->ihl[0]);
+ if (error) {
+ device_printf(dev, "Unable to alloc int resource.\n");
+ return (ENXIO);
+ }
+
+ csr_set(sie, SIE_SSIE);
+
+ return (htif_enumerate(sc));
+}
+
+static device_method_t htif_methods[] = {
+ DEVMETHOD(device_probe, htif_probe),
+ DEVMETHOD(device_attach, htif_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, htif_read_ivar),
+
+ DEVMETHOD_END
+};
+
+static driver_t htif_driver = {
+ "htif",
+ htif_methods,
+ sizeof(struct htif_softc)
+};
+
+static devclass_t htif_devclass;
+
+DRIVER_MODULE(htif, simplebus, htif_driver,
+ htif_devclass, 0, 0);
diff --git a/sys/riscv/htif/htif.h b/sys/riscv/htif/htif.h
new file mode 100644
index 000000000000..a1183d97c08e
--- /dev/null
+++ b/sys/riscv/htif/htif.h
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define HTIF_DEV_ID_SHIFT (56)
+#define HTIF_DEV_ID_MASK (0xfful << HTIF_DEV_ID_SHIFT)
+#define HTIF_CMD_SHIFT (48)
+#define HTIF_CMD_MASK (0xfful << HTIF_CMD_SHIFT)
+#define HTIF_DATA_SHIFT (0)
+#define HTIF_DATA_MASK (0xffffffff << HTIF_DATA_SHIFT)
+
+#define HTIF_CMD_READ (0x00ul)
+#define HTIF_CMD_WRITE (0x01ul)
+#define HTIF_CMD_READ_CONTROL_REG (0x02ul)
+#define HTIF_CMD_WRITE_CONTROL_REG (0x03ul)
+#define HTIF_CMD_IDENTIFY (0xfful)
+#define IDENTIFY_PADDR_SHIFT 8
+#define IDENTIFY_IDENT 0xff
+
+#define HTIF_NDEV (256)
+#define HTIF_ID_LEN (64)
+#define HTIF_ALIGN (64)
+
+#define HTIF_DEV_CMD(entry) ((entry & HTIF_CMD_MASK) >> HTIF_CMD_SHIFT)
+#define HTIF_DEV_ID(entry) ((entry & HTIF_DEV_ID_MASK) >> HTIF_DEV_ID_SHIFT)
+#define HTIF_DEV_DATA(entry) ((entry & HTIF_DATA_MASK) >> HTIF_DATA_SHIFT)
+
+/* bus softc */
+struct htif_softc {
+ struct resource *res[1];
+ void *ihl[1];
+ device_t dev;
+ uint64_t identify_id;
+ uint64_t identify_done;
+};
+
+/* device private data */
+struct htif_dev_ivars {
+ char *id;
+ int index;
+ device_t dev;
+ struct htif_softc *sc;
+};
+
+uint64_t htif_command(uint64_t);
+int htif_setup_intr(int id, void *func, void *arg);
+int htif_read_ivar(device_t dev, device_t child, int which, uintptr_t *result);
+
+enum htif_device_ivars {
+ HTIF_IVAR_INDEX,
+ HTIF_IVAR_ID,
+};
+
+/*
+ * Simplified accessors for HTIF devices
+ */
+#define HTIF_ACCESSOR(var, ivar, type) \
+ __BUS_ACCESSOR(htif, var, HTIF, ivar, type)
+
+HTIF_ACCESSOR(index, INDEX, int);
+HTIF_ACCESSOR(id, ID, char *);
diff --git a/sys/riscv/htif/htif_block.c b/sys/riscv/htif/htif_block.c
new file mode 100644
index 000000000000..58804d7aeb88
--- /dev/null
+++ b/sys/riscv/htif/htif_block.c
@@ -0,0 +1,289 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/selinfo.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/malloc.h>
+#include <sys/sysctl.h>
+#include <sys/uio.h>
+
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/disk.h>
+#include <geom/geom_disk.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/md_var.h>
+#include <machine/bus.h>
+#include <machine/trap.h>
+#include <sys/rman.h>
+
+#include "htif.h"
+
+#define SECTOR_SIZE_SHIFT (9)
+#define SECTOR_SIZE (1 << SECTOR_SIZE_SHIFT)
+
+#define HTIF_BLK_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define HTIF_BLK_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define HTIF_BLK_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
+ "htif_blk", MTX_DEF)
+#define HTIF_BLK_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define HTIF_BLK_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define HTIF_BLK_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+static void htif_blk_task(void *arg);
+
+static disk_open_t htif_blk_open;
+static disk_close_t htif_blk_close;
+static disk_strategy_t htif_blk_strategy;
+
+struct htif_blk_softc {
+ device_t dev;
+ struct disk *disk;
+ struct mtx htif_io_mtx;
+ struct mtx sc_mtx;
+ struct proc *p;
+ struct bio_queue_head bio_queue;
+ int running;
+ int intr_chan;
+ int cmd_done;
+ int index;
+ uint16_t curtag;
+};
+
+struct htif_blk_request {
+ uint64_t addr;
+ uint64_t offset; /* offset in bytes */
+ uint64_t size; /* length in bytes */
+ uint64_t tag;
+};
+
+static void
+htif_blk_intr(void *arg, uint64_t entry)
+{
+ struct htif_blk_softc *sc;
+ uint64_t devcmd;
+ uint64_t data;
+
+ sc = arg;
+
+ devcmd = HTIF_DEV_CMD(entry);
+ data = HTIF_DEV_DATA(entry);
+
+ if (sc->curtag == data) {
+ sc->cmd_done = 1;
+ wakeup(&sc->intr_chan);
+ }
+}
+
+static int
+htif_blk_probe(device_t dev)
+{
+
+ return (0);
+}
+
+static int
+htif_blk_attach(device_t dev)
+{
+ struct htif_blk_softc *sc;
+ char prefix[] = " size=";
+ char *str;
+ long size;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ mtx_init(&sc->htif_io_mtx, device_get_nameunit(dev), "htif_blk", MTX_DEF);
+ HTIF_BLK_LOCK_INIT(sc);
+
+ str = strstr(htif_get_id(dev), prefix);
+
+ size = strtol((str + 6), NULL, 10);
+ if (size == 0) {
+ return (ENXIO);
+ }
+
+ sc->index = htif_get_index(dev);
+ if (sc->index < 0)
+ return (EINVAL);
+ htif_setup_intr(sc->index, htif_blk_intr, sc);
+
+ sc->disk = disk_alloc();
+ sc->disk->d_drv1 = sc;
+
+ sc->disk->d_maxsize = 4096; /* Max transfer */
+ sc->disk->d_name = "htif_blk";
+ sc->disk->d_open = htif_blk_open;
+ sc->disk->d_close = htif_blk_close;
+ sc->disk->d_strategy = htif_blk_strategy;
+ sc->disk->d_unit = 0;
+ sc->disk->d_sectorsize = SECTOR_SIZE;
+ sc->disk->d_mediasize = size;
+ disk_create(sc->disk, DISK_VERSION);
+
+ bioq_init(&sc->bio_queue);
+
+ sc->running = 1;
+
+ kproc_create(&htif_blk_task, sc, &sc->p, 0, 0, "%s: transfer",
+ device_get_nameunit(dev));
+
+ return (0);
+}
+
+static int
+htif_blk_open(struct disk *dp)
+{
+
+ return (0);
+}
+
+static int
+htif_blk_close(struct disk *dp)
+{
+
+ return (0);
+}
+
+static void
+htif_blk_task(void *arg)
+{
+ struct htif_blk_request req __aligned(HTIF_ALIGN);
+ struct htif_blk_softc *sc;
+ struct bio *bp;
+ uint64_t paddr;
+ uint64_t cmd;
+ int i;
+
+ sc = (struct htif_blk_softc *)arg;
+
+ while (1) {
+ HTIF_BLK_LOCK(sc);
+ do {
+ bp = bioq_takefirst(&sc->bio_queue);
+ if (bp == NULL)
+ msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0);
+ } while (bp == NULL);
+ HTIF_BLK_UNLOCK(sc);
+
+ if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
+ req.offset = (bp->bio_pblkno * sc->disk->d_sectorsize);
+ req.size = bp->bio_bcount;
+ paddr = vtophys(bp->bio_data);
+ KASSERT(paddr != 0, ("paddr is 0"));
+ req.addr = paddr;
+ req.tag = sc->curtag;
+
+ cmd = sc->index;
+ cmd <<= HTIF_DEV_ID_SHIFT;
+ if (bp->bio_cmd == BIO_READ)
+ cmd |= (HTIF_CMD_READ << HTIF_CMD_SHIFT);
+ else
+ cmd |= (HTIF_CMD_WRITE << HTIF_CMD_SHIFT);
+ paddr = vtophys(&req);
+ KASSERT(paddr != 0, ("paddr is 0"));
+ cmd |= paddr;
+
+ sc->cmd_done = 0;
+ htif_command(cmd);
+
+ /* Wait for interrupt */
+ HTIF_BLK_LOCK(sc);
+ i = 0;
+ while (sc->cmd_done == 0) {
+ msleep(&sc->intr_chan, &sc->sc_mtx, PRIBIO, "intr", hz/2);
+
+ if (i++ > 2) {
+ /* TODO: try to re-issue operation on timeout ? */
+ bp->bio_error = EIO;
+ bp->bio_flags |= BIO_ERROR;
+ disk_err(bp, "hard error", -1, 1);
+ break;
+ }
+ }
+ HTIF_BLK_UNLOCK(sc);
+
+ biodone(bp);
+ } else {
+ printf("unknown op %d\n", bp->bio_cmd);
+ }
+ }
+}
+
+static void
+htif_blk_strategy(struct bio *bp)
+{
+ struct htif_blk_softc *sc;
+
+ sc = bp->bio_disk->d_drv1;
+
+ HTIF_BLK_LOCK(sc);
+ if (sc->running > 0) {
+ bioq_disksort(&sc->bio_queue, bp);
+ HTIF_BLK_UNLOCK(sc);
+ wakeup(sc);
+ } else {
+ HTIF_BLK_UNLOCK(sc);
+ biofinish(bp, NULL, ENXIO);
+ }
+}
+
+static device_method_t htif_blk_methods[] = {
+ DEVMETHOD(device_probe, htif_blk_probe),
+ DEVMETHOD(device_attach, htif_blk_attach),
+};
+
+static driver_t htif_blk_driver = {
+ "htif_blk",
+ htif_blk_methods,
+ sizeof(struct htif_blk_softc)
+};
+
+static devclass_t htif_blk_devclass;
+
+DRIVER_MODULE(htif_blk, htif, htif_blk_driver, htif_blk_devclass, 0, 0);
diff --git a/sys/riscv/htif/htif_console.c b/sys/riscv/htif/htif_console.c
new file mode 100644
index 000000000000..b4a46766949e
--- /dev/null
+++ b/sys/riscv/htif/htif_console.c
@@ -0,0 +1,361 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/priv.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/consio.h>
+#include <sys/tty.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+#include <machine/trap.h>
+
+#include "htif.h"
+
+#include <dev/ofw/openfirm.h>
+
+#include <ddb/ddb.h>
+
+extern uint64_t console_intr;
+
+static tsw_outwakeup_t riscvtty_outwakeup;
+
+static struct ttydevsw riscv_ttydevsw = {
+ .tsw_flags = TF_NOPREFIX,
+ .tsw_outwakeup = riscvtty_outwakeup,
+};
+
+static int polltime;
+static struct callout riscv_callout;
+static struct tty *tp = NULL;
+
+#if defined(KDB)
+static int alt_break_state;
+#endif
+
+static void riscv_timeout(void *);
+
+static cn_probe_t riscv_cnprobe;
+static cn_init_t riscv_cninit;
+static cn_term_t riscv_cnterm;
+static cn_getc_t riscv_cngetc;
+static cn_putc_t riscv_cnputc;
+static cn_grab_t riscv_cngrab;
+static cn_ungrab_t riscv_cnungrab;
+
+CONSOLE_DRIVER(riscv);
+
+#define MAX_BURST_LEN 1
+#define QUEUE_SIZE 256
+#define CONSOLE_DEFAULT_ID 1ul
+
+struct queue_entry {
+ uint64_t data;
+ uint64_t used;
+ struct queue_entry *next;
+};
+
+struct queue_entry cnqueue[QUEUE_SIZE];
+struct queue_entry *entry_last;
+struct queue_entry *entry_served;
+
+static void
+htif_putc(int c)
+{
+ uint64_t cmd;
+
+ cmd = (HTIF_CMD_WRITE << HTIF_CMD_SHIFT);
+ cmd |= (CONSOLE_DEFAULT_ID << HTIF_DEV_ID_SHIFT);
+ cmd |= c;
+
+ htif_command(cmd);
+}
+
+static uint8_t
+htif_getc(void)
+{
+ uint64_t cmd;
+ uint8_t res;
+
+ cmd = (HTIF_CMD_READ << HTIF_CMD_SHIFT);
+ cmd |= (CONSOLE_DEFAULT_ID << HTIF_DEV_ID_SHIFT);
+
+ res = htif_command(cmd);
+
+ return (res);
+}
+
+static void
+riscv_putc(int c)
+{
+ uint64_t counter;
+ uint64_t *cc;
+ uint64_t val;
+
+ val = 0;
+ counter = 0;
+
+ cc = (uint64_t*)&console_intr;
+ *cc = 0;
+
+ htif_putc(c);
+
+ /* Wait for an interrupt */
+ __asm __volatile(
+ "li %0, 1\n" /* counter = 1 */
+ "slli %0, %0, 12\n" /* counter <<= 12 */
+ "1:"
+ "addi %0, %0, -1\n" /* counter -= 1 */
+ "beqz %0, 2f\n" /* counter == 0 ? finish */
+ "ld %1, 0(%2)\n" /* val = *cc */
+ "beqz %1, 1b\n" /* val == 0 ? repeat */
+ "2:"
+ : "=&r"(counter), "=&r"(val) : "r"(cc)
+ );
+}
+
+#ifdef EARLY_PRINTF
+early_putc_t *early_putc = riscv_putc;
+#endif
+
+static void
+cn_drvinit(void *unused)
+{
+
+ if (riscv_consdev.cn_pri != CN_DEAD &&
+ riscv_consdev.cn_name[0] != '\0') {
+ tp = tty_alloc(&riscv_ttydevsw, NULL);
+ tty_init_console(tp, 0);
+ tty_makedev(tp, NULL, "%s", "rcons");
+
+ polltime = 1;
+
+ callout_init(&riscv_callout, 1);
+ callout_reset(&riscv_callout, polltime, riscv_timeout, NULL);
+ }
+}
+
+SYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL);
+
+static void
+riscvtty_outwakeup(struct tty *tp)
+{
+ u_char buf[MAX_BURST_LEN];
+ int len;
+ int i;
+
+ for (;;) {
+ len = ttydisc_getc(tp, buf, sizeof(buf));
+ if (len == 0)
+ break;
+
+ KASSERT(len == 1, ("tty error"));
+
+ for (i = 0; i < len; i++)
+ riscv_putc(buf[i]);
+ }
+}
+
+static void
+riscv_timeout(void *v)
+{
+ int c;
+
+ tty_lock(tp);
+ while ((c = riscv_cngetc(NULL)) != -1)
+ ttydisc_rint(tp, c, 0);
+ ttydisc_rint_done(tp);
+ tty_unlock(tp);
+
+ callout_reset(&riscv_callout, polltime, riscv_timeout, NULL);
+}
+
+static void
+riscv_cnprobe(struct consdev *cp)
+{
+
+ cp->cn_pri = CN_NORMAL;
+}
+
+static void
+riscv_cninit(struct consdev *cp)
+{
+ int i;
+
+ strcpy(cp->cn_name, "rcons");
+
+ for (i = 0; i < QUEUE_SIZE; i++) {
+ if (i == (QUEUE_SIZE - 1))
+ cnqueue[i].next = &cnqueue[0];
+ else
+ cnqueue[i].next = &cnqueue[i+1];
+ cnqueue[i].data = 0;
+ cnqueue[i].used = 0;
+ }
+
+ entry_last = &cnqueue[0];
+ entry_served = &cnqueue[0];
+}
+
+static void
+riscv_cnterm(struct consdev *cp)
+{
+
+}
+
+static void
+riscv_cngrab(struct consdev *cp)
+{
+
+}
+
+static void
+riscv_cnungrab(struct consdev *cp)
+{
+
+}
+
+static int
+riscv_cngetc(struct consdev *cp)
+{
+ uint8_t data;
+ int ch;
+
+ ch = htif_getc();
+
+ if (entry_served->used == 1) {
+ data = entry_served->data;
+ entry_served->used = 0;
+ entry_served = entry_served->next;
+ ch = (data & 0xff);
+ if (ch > 0 && ch < 0xff) {
+#if defined(KDB)
+ kdb_alt_break(ch, &alt_break_state);
+#endif
+ return (ch);
+ }
+ }
+
+ return (-1);
+}
+
+static void
+riscv_cnputc(struct consdev *cp, int c)
+{
+
+ riscv_putc(c);
+}
+
+/*
+ * Bus interface.
+ */
+
+struct htif_console_softc {
+ device_t dev;
+ int running;
+ int intr_chan;
+ int cmd_done;
+ int curtag;
+ int index;
+};
+
+static void
+htif_console_intr(void *arg, uint64_t entry)
+{
+ struct htif_console_softc *sc;
+ uint8_t devcmd;
+ uint64_t data;
+
+ sc = arg;
+
+ devcmd = HTIF_DEV_CMD(entry);
+ data = HTIF_DEV_DATA(entry);
+
+ if (devcmd == 0) {
+ entry_last->data = data;
+ entry_last->used = 1;
+ entry_last = entry_last->next;
+ }
+}
+
+static int
+htif_console_probe(device_t dev)
+{
+
+ return (0);
+}
+
+static int
+htif_console_attach(device_t dev)
+{
+ struct htif_console_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ sc->index = htif_get_index(dev);
+ if (sc->index < 0)
+ return (EINVAL);
+
+ htif_setup_intr(sc->index, htif_console_intr, sc);
+
+ return (0);
+}
+
+static device_method_t htif_console_methods[] = {
+ DEVMETHOD(device_probe, htif_console_probe),
+ DEVMETHOD(device_attach, htif_console_attach),
+ DEVMETHOD_END
+};
+
+static driver_t htif_console_driver = {
+ "htif_console",
+ htif_console_methods,
+ sizeof(struct htif_console_softc)
+};
+
+static devclass_t htif_console_devclass;
+
+DRIVER_MODULE(htif_console, htif, htif_console_driver,
+ htif_console_devclass, 0, 0);
diff --git a/sys/riscv/include/asm.h b/sys/riscv/include/asm.h
index fb0c8442fc4f..adcc23aa9501 100644
--- a/sys/riscv/include/asm.h
+++ b/sys/riscv/include/asm.h
@@ -59,9 +59,7 @@
.set alias,sym
#define SET_FAULT_HANDLER(handler, tmp) \
- la tmp, pcpup; \
- ld tmp, 0(tmp); \
- ld tmp, PC_CURTHREAD(tmp); \
+ ld tmp, PC_CURTHREAD(gp); \
ld tmp, TD_PCB(tmp); /* Load the pcb */ \
sd handler, PCB_ONFAULT(tmp) /* Set the handler */
diff --git a/sys/riscv/include/pcpu.h b/sys/riscv/include/pcpu.h
index c60a95428fe1..7dfe23d991bf 100644
--- a/sys/riscv/include/pcpu.h
+++ b/sys/riscv/include/pcpu.h
@@ -47,8 +47,11 @@ extern struct pcpu *pcpup;
static inline struct pcpu *
get_pcpu(void)
{
+ struct pcpu *pcpu;
- return (pcpup);
+ __asm __volatile("mv %0, gp" : "=&r"(pcpu));
+
+ return (pcpu);
}
static inline struct thread *
@@ -56,7 +59,7 @@ get_curthread(void)
{
struct thread *td;
- td = (struct thread *)*(uint64_t *)pcpup;
+ __asm __volatile("ld %0, 0(gp)" : "=&r"(td));
return (td);
}
diff --git a/sys/riscv/riscv/autoconf.c b/sys/riscv/riscv/autoconf.c
new file mode 100644
index 000000000000..d6afb42754d1
--- /dev/null
+++ b/sys/riscv/riscv/autoconf.c
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Setup the system to run on the current machine.
+ *
+ * Configure() is called at boot time and initializes the vba
+ * device tables and the memory controller monitoring. Available
+ * devices are determined (from possibilities mentioned in ioconf.c),
+ * and the drivers are initialized.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/cons.h>
+
+static void configure_first(void *);
+static void configure(void *);
+static void configure_final(void *);
+
+SYSINIT(configure1, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure_first, NULL);
+/* SI_ORDER_SECOND is hookable */
+SYSINIT(configure2, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL);
+/* SI_ORDER_MIDDLE is hookable */
+SYSINIT(configure3, SI_SUB_CONFIGURE, SI_ORDER_ANY, configure_final, NULL);
+
+/*
+ * Determine i/o configuration for a machine.
+ */
+static void
+configure_first(void *dummy)
+{
+
+ /* nexus0 is the top of the riscv device tree */
+ device_add_child(root_bus, "nexus", 0);
+}
+
+static void
+configure(void *dummy)
+{
+
+ /* initialize new bus architecture */
+ root_bus_configure();
+}
+
+static void
+configure_final(void *dummy)
+{
+
+ intr_enable();
+
+ cninit_finish();
+
+ if (bootverbose)
+ printf("Device configuration finished.\n");
+
+ cold = 0;
+}
diff --git a/sys/riscv/riscv/bcopy.c b/sys/riscv/riscv/bcopy.c
new file mode 100644
index 000000000000..613ca97e5430
--- /dev/null
+++ b/sys/riscv/riscv/bcopy.c
@@ -0,0 +1,139 @@
+/*-
+ * Copyright (c) 1990 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.
+ * 3. 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: sys/powerpc/powerpc/bcopy.c
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+/*
+ * sizeof(word) MUST BE A POWER OF TWO
+ * SO THAT wmask BELOW IS ALL ONES
+ */
+typedef long word; /* "word" used for optimal copy speed */
+
+#define wsize sizeof(word)
+#define wmask (wsize - 1)
+
+/*
+ * Copy a block of memory, handling overlap.
+ * This is the routine that actually implements
+ * (the portable versions of) bcopy, memcpy, and memmove.
+ */
+void *
+memcpy(void *dst0, const void *src0, size_t length)
+{
+ char *dst;
+ const char *src;
+ size_t t;
+
+ dst = dst0;
+ src = src0;
+
+ if (length == 0 || dst == src) { /* nothing to do */
+ goto done;
+ }
+
+ /*
+ * Macros: loop-t-times; and loop-t-times, t>0
+ */
+#define TLOOP(s) if (t) TLOOP1(s)
+#define TLOOP1(s) do { s; } while (--t)
+
+ if ((unsigned long)dst < (unsigned long)src) {
+ /*
+ * Copy forward.
+ */
+ t = (size_t)src; /* only need low bits */
+
+ if ((t | (uintptr_t)dst) & wmask) {
+ /*
+ * Try to align operands. This cannot be done
+ * unless the low bits match.
+ */
+ if ((t ^ (uintptr_t)dst) & wmask || length < wsize) {
+ t = length;
+ } else {
+ t = wsize - (t & wmask);
+ }
+
+ length -= t;
+ TLOOP1(*dst++ = *src++);
+ }
+ /*
+ * Copy whole words, then mop up any trailing bytes.
+ */
+ t = length / wsize;
+ TLOOP(*(word *)dst = *(const word *)src; src += wsize;
+ dst += wsize);
+ t = length & wmask;
+ TLOOP(*dst++ = *src++);
+ } else {
+ /*
+ * Copy backwards. Otherwise essentially the same.
+ * Alignment works as before, except that it takes
+ * (t&wmask) bytes to align, not wsize-(t&wmask).
+ */
+ src += length;
+ dst += length;
+ t = (uintptr_t)src;
+
+ if ((t | (uintptr_t)dst) & wmask) {
+ if ((t ^ (uintptr_t)dst) & wmask || length <= wsize) {
+ t = length;
+ } else {
+ t &= wmask;
+ }
+
+ length -= t;
+ TLOOP1(*--dst = *--src);
+ }
+ t = length / wsize;
+ TLOOP(src -= wsize; dst -= wsize;
+ *(word *)dst = *(const word *)src);
+ t = length & wmask;
+ TLOOP(*--dst = *--src);
+ }
+done:
+ return (dst0);
+}
+
+void
+bcopy(const void *src0, void *dst0, size_t length)
+{
+
+ memcpy(dst0, src0, length);
+}
+
diff --git a/sys/riscv/riscv/bus_machdep.c b/sys/riscv/riscv/bus_machdep.c
new file mode 100644
index 000000000000..54e3419be5ee
--- /dev/null
+++ b/sys/riscv/riscv/bus_machdep.c
@@ -0,0 +1,144 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/param.h>
+__FBSDID("$FreeBSD$");
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+
+struct bus_space memmap_bus = {
+ /* cookie */
+ .bs_cookie = NULL,
+
+ /* mapping/unmapping */
+ .bs_map = NULL,
+ .bs_unmap = NULL,
+ .bs_subregion = NULL,
+
+ /* allocation/deallocation */
+ .bs_alloc = NULL,
+ .bs_free = NULL,
+
+ /* barrier */
+ .bs_barrier = NULL,
+
+ /* read single */
+ .bs_r_1 = NULL,
+ .bs_r_2 = NULL,
+ .bs_r_4 = NULL,
+ .bs_r_8 = NULL,
+
+ /* read multiple */
+ .bs_rm_1 = NULL,
+ .bs_rm_2 = NULL,
+ .bs_rm_4 = NULL,
+ .bs_rm_8 = NULL,
+
+ /* write single */
+ .bs_w_1 = NULL,
+ .bs_w_2 = NULL,
+ .bs_w_4 = NULL,
+ .bs_w_8 = NULL,
+
+ /* write multiple */
+ .bs_wm_1 = NULL,
+ .bs_wm_2 = NULL,
+ .bs_wm_4 = NULL,
+ .bs_wm_8 = NULL,
+
+ /* write region */
+ .bs_wr_1 = NULL,
+ .bs_wr_2 = NULL,
+ .bs_wr_4 = NULL,
+ .bs_wr_8 = NULL,
+
+ /* set multiple */
+ .bs_sm_1 = NULL,
+ .bs_sm_2 = NULL,
+ .bs_sm_4 = NULL,
+ .bs_sm_8 = NULL,
+
+ /* set region */
+ .bs_sr_1 = NULL,
+ .bs_sr_2 = NULL,
+ .bs_sr_4 = NULL,
+ .bs_sr_8 = NULL,
+
+ /* copy */
+ .bs_c_1 = NULL,
+ .bs_c_2 = NULL,
+ .bs_c_4 = NULL,
+ .bs_c_8 = NULL,
+
+ /* read single stream */
+ .bs_r_1_s = NULL,
+ .bs_r_2_s = NULL,
+ .bs_r_4_s = NULL,
+ .bs_r_8_s = NULL,
+
+ /* read multiple stream */
+ .bs_rm_1_s = NULL,
+ .bs_rm_2_s = NULL,
+ .bs_rm_4_s = NULL,
+ .bs_rm_8_s = NULL,
+
+ /* read region stream */
+ .bs_rr_1_s = NULL,
+ .bs_rr_2_s = NULL,
+ .bs_rr_4_s = NULL,
+ .bs_rr_8_s = NULL,
+
+ /* write single stream */
+ .bs_w_1_s = NULL,
+ .bs_w_2_s = NULL,
+ .bs_w_4_s = NULL,
+ .bs_w_8_s = NULL,
+
+ /* write multiple stream */
+ .bs_wm_1_s = NULL,
+ .bs_wm_2_s = NULL,
+ .bs_wm_4_s = NULL,
+ .bs_wm_8_s = NULL,
+
+ /* write region stream */
+ .bs_wr_1_s = NULL,
+ .bs_wr_2_s = NULL,
+ .bs_wr_4_s = NULL,
+ .bs_wr_8_s = NULL,
+};
diff --git a/sys/riscv/riscv/busdma_machdep.c b/sys/riscv/riscv/busdma_machdep.c
new file mode 100644
index 000000000000..ec0fea91252f
--- /dev/null
+++ b/sys/riscv/riscv/busdma_machdep.c
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 1997, 1998 Justin T. Gibbs.
+ *
+ * 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,
+ * without modification, immediately at the beginning of the file.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/memdesc.h>
+#include <sys/mutex.h>
+#include <sys/uio.h>
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+
+int
+_bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf,
+ bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp)
+{
+
+ panic("busdma");
+}
+
+int
+_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map, struct vm_page **ma,
+ bus_size_t tlen, int ma_offs, int flags, bus_dma_segment_t *segs,
+ int *segp)
+{
+
+ panic("busdma");
+}
+
+int
+_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
+ bus_size_t buflen, pmap_t pmap, int flags, bus_dma_segment_t *segs,
+ int *segp)
+{
+
+ panic("busdma");
+}
+
+void
+__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg)
+{
+
+ panic("busdma");
+}
+
+bus_dma_segment_t *
+_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map,
+ bus_dma_segment_t *segs, int nsegs, int error)
+{
+
+ panic("busdma");
+}
+
+/*
+ * Release the mapping held by map.
+ */
+void
+_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+
+ panic("busdma");
+}
+
+void
+_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
+{
+
+ panic("busdma");
+}
diff --git a/sys/riscv/riscv/clock.c b/sys/riscv/riscv/clock.c
new file mode 100644
index 000000000000..e0c2d4ba3c0b
--- /dev/null
+++ b/sys/riscv/riscv/clock.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+void
+cpu_initclocks(void)
+{
+
+ cpu_initclocks_bsp();
+}
diff --git a/sys/riscv/riscv/copyinout.S b/sys/riscv/riscv/copyinout.S
new file mode 100644
index 000000000000..44d68390d7b6
--- /dev/null
+++ b/sys/riscv/riscv/copyinout.S
@@ -0,0 +1,137 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/errno.h>
+
+#include "assym.s"
+
+/*
+ * Fault handler for the copy{in,out} functions below.
+ */
+ENTRY(copyio_fault)
+ SET_FAULT_HANDLER(x0, a1) /* Clear the handler */
+copyio_fault_nopcb:
+ li a0, EFAULT
+ ret
+END(copyio_fault)
+
+/*
+ * Copies from a kernel to user address
+ *
+ * int copyout(const void *kaddr, void *udaddr, size_t len)
+ */
+ENTRY(copyout)
+ beqz a2, 2f /* If len == 0 then skip loop */
+ add a3, a1, a2
+ li a4, VM_MAXUSER_ADDRESS
+ bgt a3, a4, copyio_fault_nopcb
+
+ la a6, copyio_fault /* Get the handler address */
+ SET_FAULT_HANDLER(a6, a7) /* Set the handler */
+
+1: lb a4, 0(a0) /* Load from kaddr */
+ addi a0, a0, 1
+ sb a4, 0(a1) /* Store in uaddr */
+ addi a1, a1, 1
+ addi a2, a2, -1 /* len-- */
+ bnez a2, 1b
+
+ SET_FAULT_HANDLER(x0, a7) /* Clear the handler */
+
+2: li a0, 0 /* return 0 */
+ ret
+END(copyout)
+
+/*
+ * Copies from a user to kernel address
+ *
+ * int copyin(const void *uaddr, void *kdaddr, size_t len)
+ */
+ENTRY(copyin)
+ beqz a2, 2f /* If len == 0 then skip loop */
+ add a3, a0, a2
+ li a4, VM_MAXUSER_ADDRESS
+ bgt a3, a4, copyio_fault_nopcb
+
+ la a6, copyio_fault /* Get the handler address */
+ SET_FAULT_HANDLER(a6, a7) /* Set the handler */
+
+1: lb a4, 0(a0) /* Load from uaddr */
+ addi a0, a0, 1
+ sb a4, 0(a1) /* Store in kaddr */
+ addi a1, a1, 1
+ addi a2, a2, -1 /* len-- */
+ bnez a2, 1b
+
+ SET_FAULT_HANDLER(x0, a7) /* Clear the handler */
+
+2: li a0, 0 /* return 0 */
+ ret
+END(copyin)
+
+/*
+ * Copies a string from a user to kernel address
+ *
+ * int copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
+ */
+ENTRY(copyinstr)
+ mv a5, x0 /* count = 0 */
+ beqz a2, 3f /* If len == 0 then skip loop */
+ li a7, VM_MAXUSER_ADDRESS
+
+ la a6, copyio_fault /* Get the handler address */
+ SET_FAULT_HANDLER(a6, a7) /* Set the handler */
+
+1: bgt a7, a0, copyio_fault
+ lb a4, 0(a0) /* Load from uaddr */
+ addi a0, a0, 1
+ sb a4, 0(a1) /* Store in kaddr */
+ addi a1, a1, 1
+ beqz a4, 2f
+ addi a2, a2, -1 /* len-- */
+ addi a5, a5, 1 /* count++ */
+ bnez a2, 1b
+
+2: SET_FAULT_HANDLER(x0, a7) /* Clear the handler */
+
+3: beqz a3, 4f /* Check if done != NULL */
+ addi a5, a5, 1 /* count++ */
+ sd a5, 0(a3) /* done = count */
+
+4: mv a0, x0 /* return 0 */
+ ret
+END(copyinstr)
diff --git a/sys/riscv/riscv/copystr.c b/sys/riscv/riscv/copystr.c
new file mode 100644
index 000000000000..261dbc81ef76
--- /dev/null
+++ b/sys/riscv/riscv/copystr.c
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2014 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+int
+copystr(const void * __restrict kfaddr, void * __restrict kdaddr, size_t len,
+ size_t * __restrict lencopied)
+{
+ const char *src;
+ size_t pos;
+ char *dst;
+ int error;
+
+ error = ENAMETOOLONG;
+ src = kfaddr;
+ dst = kdaddr;
+ for (pos = 0; pos < len; pos++) {
+ dst[pos] = src[pos];
+ if (src[pos] == '\0') {
+ /* Increment pos to hold the number of bytes copied */
+ pos++;
+ error = 0;
+ break;
+ }
+ }
+
+ if (lencopied != NULL)
+ *lencopied = pos;
+
+ return (error);
+}
diff --git a/sys/riscv/riscv/cpufunc_asm.S b/sys/riscv/riscv/cpufunc_asm.S
new file mode 100644
index 000000000000..21bce533187a
--- /dev/null
+++ b/sys/riscv/riscv/cpufunc_asm.S
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+#include <machine/param.h>
+__FBSDID("$FreeBSD$");
+
+ .text
+ .align 2
+
+.Lpage_mask:
+ .word PAGE_MASK
+
+ENTRY(riscv_nullop)
+ ret
+END(riscv_nullop)
+
+/*
+ * Generic functions to read/modify/write the internal coprocessor registers
+ */
+
+ENTRY(riscv_tlb_flushID)
+ sfence.vm
+ ret
+END(riscv_tlb_flushID)
+
+ENTRY(riscv_tlb_flushID_SE)
+ sfence.vm
+ ret
+END(riscv_tlb_flushID_SE)
+
+/*
+ * void riscv_dcache_wb_range(vm_offset_t, vm_size_t)
+ */
+ENTRY(riscv_dcache_wb_range)
+ /* RISCVTODO */
+ ret
+END(riscv_dcache_wb_range)
+
+/*
+ * void riscv_dcache_wbinv_range(vm_offset_t, vm_size_t)
+ */
+ENTRY(riscv_dcache_wbinv_range)
+ /* RISCVTODO */
+ ret
+END(riscv_dcache_wbinv_range)
+
+/*
+ * void riscv_dcache_inv_range(vm_offset_t, vm_size_t)
+ */
+ENTRY(riscv_dcache_inv_range)
+ /* RISCVTODO */
+ ret
+END(riscv_dcache_inv_range)
+
+/*
+ * void riscv_idcache_wbinv_range(vm_offset_t, vm_size_t)
+ */
+ENTRY(riscv_idcache_wbinv_range)
+ /* RISCVTODO */
+ ret
+END(riscv_idcache_wbinv_range)
+
+/*
+ * void riscv_icache_sync_range(vm_offset_t, vm_size_t)
+ */
+ENTRY(riscv_icache_sync_range)
+ /* RISCVTODO */
+ ret
+END(riscv_icache_sync_range)
diff --git a/sys/riscv/riscv/devmap.c b/sys/riscv/riscv/devmap.c
new file mode 100644
index 000000000000..092532aa7bf4
--- /dev/null
+++ b/sys/riscv/riscv/devmap.c
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* RISC-V doesn't provide memory-mapped devices yet */
+
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/pmap.h>
+#include <machine/riscvreg.h>
+#include <machine/vmparam.h>
+
+void *
+pmap_mapdev(vm_offset_t pa, vm_size_t size)
+{
+
+ return (NULL);
+}
+
+void
+pmap_unmapdev(vm_offset_t va, vm_size_t size)
+{
+
+}
diff --git a/sys/riscv/riscv/dump_machdep.c b/sys/riscv/riscv/dump_machdep.c
new file mode 100644
index 000000000000..b8473314e27b
--- /dev/null
+++ b/sys/riscv/riscv/dump_machdep.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_watchdog.h"
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/kerneldump.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+int do_minidump = 1;
+SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RWTUN, &do_minidump, 0,
+ "Enable mini crash dumps");
+
+void
+dumpsys_map_chunk(vm_paddr_t pa, size_t chunk, void **va)
+{
+
+ printf("dumpsys_map_chunk\n");
+}
diff --git a/sys/riscv/riscv/elf_machdep.c b/sys/riscv/riscv/elf_machdep.c
new file mode 100644
index 000000000000..1e4480121d1b
--- /dev/null
+++ b/sys/riscv/riscv/elf_machdep.c
@@ -0,0 +1,169 @@
+/*-
+ * Copyright 1996-1998 John D. Polstra.
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/imgact.h>
+#include <sys/linker.h>
+#include <sys/proc.h>
+#include <sys/sysent.h>
+#include <sys/imgact_elf.h>
+#include <sys/syscall.h>
+#include <sys/signalvar.h>
+#include <sys/vnode.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_param.h>
+
+#include <machine/elf.h>
+#include <machine/md_var.h>
+
+struct sysentvec elf64_freebsd_sysvec = {
+ .sv_size = SYS_MAXSYSCALL,
+ .sv_table = sysent,
+ .sv_mask = 0,
+ .sv_errsize = 0,
+ .sv_errtbl = NULL,
+ .sv_transtrap = NULL,
+ .sv_fixup = __elfN(freebsd_fixup),
+ .sv_sendsig = sendsig,
+ .sv_sigcode = sigcode,
+ .sv_szsigcode = &szsigcode,
+ .sv_name = "FreeBSD ELF64",
+ .sv_coredump = __elfN(coredump),
+ .sv_imgact_try = NULL,
+ .sv_minsigstksz = MINSIGSTKSZ,
+ .sv_pagesize = PAGE_SIZE,
+ .sv_minuser = VM_MIN_ADDRESS,
+ .sv_maxuser = VM_MAXUSER_ADDRESS,
+ .sv_usrstack = USRSTACK,
+ .sv_psstrings = PS_STRINGS,
+ .sv_stackprot = VM_PROT_ALL,
+ .sv_copyout_strings = exec_copyout_strings,
+ .sv_setregs = exec_setregs,
+ .sv_fixlimit = NULL,
+ .sv_maxssiz = NULL,
+ .sv_flags = SV_ABI_FREEBSD | SV_LP64,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = cpu_fetch_syscall_args,
+ .sv_syscallnames = syscallnames,
+ .sv_schedtail = NULL,
+ .sv_thread_detach = NULL,
+ .sv_trap = NULL,
+};
+INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
+
+static Elf64_Brandinfo freebsd_brand_info = {
+ .brand = ELFOSABI_FREEBSD,
+ .machine = EM_RISCV,
+ .compat_3_brand = "FreeBSD",
+ .emul_path = NULL,
+ .interp_path = "/libexec/ld-elf.so.1",
+ .sysvec = &elf64_freebsd_sysvec,
+ .interp_newpath = NULL,
+ .brand_note = &elf64_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_FIRST,
+ (sysinit_cfunc_t) elf64_insert_brand_entry,
+ &freebsd_brand_info);
+
+static Elf64_Brandinfo freebsd_brand_oinfo = {
+ .brand = ELFOSABI_FREEBSD,
+ .machine = EM_RISCV,
+ .compat_3_brand = "FreeBSD",
+ .emul_path = NULL,
+ .interp_path = "/usr/libexec/ld-elf.so.1",
+ .sysvec = &elf64_freebsd_sysvec,
+ .interp_newpath = NULL,
+ .brand_note = &elf64_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf64_insert_brand_entry,
+ &freebsd_brand_oinfo);
+
+void
+elf64_dump_thread(struct thread *td, void *dst, size_t *off)
+{
+
+}
+
+/* Process one elf relocation with addend. */
+static int
+elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
+ int type, int local, elf_lookup_fn lookup)
+{
+
+ panic("elf_reloc_internal");
+}
+
+int
+elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
+ elf_lookup_fn lookup)
+{
+
+ return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
+}
+
+int
+elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
+ int type, elf_lookup_fn lookup)
+{
+
+ return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
+}
+
+int
+elf_cpu_load_file(linker_file_t lf __unused)
+{
+
+ return (0);
+}
+
+int
+elf_cpu_unload_file(linker_file_t lf __unused)
+{
+
+ return (0);
+}
diff --git a/sys/riscv/riscv/exception.S b/sys/riscv/riscv/exception.S
new file mode 100644
index 000000000000..814fcf67b9d8
--- /dev/null
+++ b/sys/riscv/riscv/exception.S
@@ -0,0 +1,461 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "assym.s"
+
+#include <machine/trap.h>
+#include <machine/riscvreg.h>
+
+.macro save_registers el
+ addi sp, sp, -(TF_SIZE)
+
+ sd ra, (TF_RA)(sp)
+ sd tp, (TF_TP)(sp)
+
+.if \el == 0 /* We came from userspace. Load our pcpu */
+ sd gp, (TF_GP)(sp)
+ ld gp, (TF_SIZE)(sp)
+.endif
+
+ sd t0, (TF_T + 0 * 8)(sp)
+ sd t1, (TF_T + 1 * 8)(sp)
+ sd t2, (TF_T + 2 * 8)(sp)
+ sd t3, (TF_T + 3 * 8)(sp)
+ sd t4, (TF_T + 4 * 8)(sp)
+ sd t5, (TF_T + 5 * 8)(sp)
+ sd t6, (TF_T + 6 * 8)(sp)
+
+ sd s0, (TF_S + 0 * 8)(sp)
+ sd s1, (TF_S + 1 * 8)(sp)
+ sd s2, (TF_S + 2 * 8)(sp)
+ sd s3, (TF_S + 3 * 8)(sp)
+ sd s4, (TF_S + 4 * 8)(sp)
+ sd s5, (TF_S + 5 * 8)(sp)
+ sd s6, (TF_S + 6 * 8)(sp)
+ sd s7, (TF_S + 7 * 8)(sp)
+ sd s8, (TF_S + 8 * 8)(sp)
+ sd s9, (TF_S + 9 * 8)(sp)
+ sd s10, (TF_S + 10 * 8)(sp)
+ sd s11, (TF_S + 11 * 8)(sp)
+
+ sd a0, (TF_A + 0 * 8)(sp)
+ sd a1, (TF_A + 1 * 8)(sp)
+ sd a2, (TF_A + 2 * 8)(sp)
+ sd a3, (TF_A + 3 * 8)(sp)
+ sd a4, (TF_A + 4 * 8)(sp)
+ sd a5, (TF_A + 5 * 8)(sp)
+ sd a6, (TF_A + 6 * 8)(sp)
+ sd a7, (TF_A + 7 * 8)(sp)
+
+#if 0
+ /* XXX: temporary test: spin if stack is not kernel one */
+.if \el == 1 /* kernel */
+ mv t0, sp
+ srli t0, t0, 63
+1:
+ beqz t0, 1b
+.endif
+#endif
+
+.if \el == 1
+ /* Store kernel sp */
+ sd sp, (TF_SP)(sp)
+.else
+ /* Store user sp */
+ csrr t0, sscratch
+ sd t0, (TF_SP)(sp)
+.endif
+ li t0, 0
+ csrw sscratch, t0
+ csrr t0, sepc
+ sd t0, (TF_SEPC)(sp)
+ csrr t0, sstatus
+ sd t0, (TF_SSTATUS)(sp)
+ csrr t0, sbadaddr
+ sd t0, (TF_SBADADDR)(sp)
+ csrr t0, scause
+ sd t0, (TF_SCAUSE)(sp)
+.endm
+
+.macro load_registers el
+ ld t0, (TF_SSTATUS)(sp)
+.if \el == 0
+ /* Ensure user interrupts will be enabled on eret. */
+ ori t0, t0, SSTATUS_PIE
+.else
+ /*
+ * Disable interrupts for supervisor mode exceptions.
+ * For user mode exceptions we have already done this
+ * in do_ast.
+ */
+ li t1, ~SSTATUS_IE
+ and t0, t0, t1
+.endif
+ csrw sstatus, t0
+
+ ld t0, (TF_SEPC)(sp)
+ csrw sepc, t0
+
+.if \el == 0
+ /* We go to userspace. Load user sp */
+ ld t0, (TF_SP)(sp)
+ csrw sscratch, t0
+
+ /* And store our pcpu */
+ sd gp, (TF_SIZE)(sp)
+ ld gp, (TF_GP)(sp)
+.endif
+
+ ld ra, (TF_RA)(sp)
+ ld tp, (TF_TP)(sp)
+
+ ld t0, (TF_T + 0 * 8)(sp)
+ ld t1, (TF_T + 1 * 8)(sp)
+ ld t2, (TF_T + 2 * 8)(sp)
+ ld t3, (TF_T + 3 * 8)(sp)
+ ld t4, (TF_T + 4 * 8)(sp)
+ ld t5, (TF_T + 5 * 8)(sp)
+ ld t6, (TF_T + 6 * 8)(sp)
+
+ ld s0, (TF_S + 0 * 8)(sp)
+ ld s1, (TF_S + 1 * 8)(sp)
+ ld s2, (TF_S + 2 * 8)(sp)
+ ld s3, (TF_S + 3 * 8)(sp)
+ ld s4, (TF_S + 4 * 8)(sp)
+ ld s5, (TF_S + 5 * 8)(sp)
+ ld s6, (TF_S + 6 * 8)(sp)
+ ld s7, (TF_S + 7 * 8)(sp)
+ ld s8, (TF_S + 8 * 8)(sp)
+ ld s9, (TF_S + 9 * 8)(sp)
+ ld s10, (TF_S + 10 * 8)(sp)
+ ld s11, (TF_S + 11 * 8)(sp)
+
+ ld a0, (TF_A + 0 * 8)(sp)
+ ld a1, (TF_A + 1 * 8)(sp)
+ ld a2, (TF_A + 2 * 8)(sp)
+ ld a3, (TF_A + 3 * 8)(sp)
+ ld a4, (TF_A + 4 * 8)(sp)
+ ld a5, (TF_A + 5 * 8)(sp)
+ ld a6, (TF_A + 6 * 8)(sp)
+ ld a7, (TF_A + 7 * 8)(sp)
+
+ addi sp, sp, (TF_SIZE)
+.endm
+
+.macro do_ast
+ /* Disable interrupts */
+ csrr a4, sstatus
+1:
+ csrci sstatus, SSTATUS_IE
+
+ ld a1, PC_CURTHREAD(gp)
+ lw a2, TD_FLAGS(a1)
+
+ li a3, (TDF_ASTPENDING|TDF_NEEDRESCHED)
+ and a2, a2, a3
+ beqz a2, 2f
+
+ /* Restore interrupts */
+ andi a4, a4, SSTATUS_IE
+ csrs sstatus, a4
+
+ /* Handle the ast */
+ mv a0, sp
+ call _C_LABEL(ast)
+
+ /* Re-check for new ast scheduled */
+ j 1b
+2:
+.endm
+
+ENTRY(cpu_exception_handler_supervisor)
+ save_registers 1
+ mv a0, sp
+ call _C_LABEL(do_trap_supervisor)
+ load_registers 1
+ eret
+END(cpu_exception_handler_supervisor)
+
+ENTRY(cpu_exception_handler_user)
+ csrrw sp, sscratch, sp
+ save_registers 0
+ mv a0, sp
+ call _C_LABEL(do_trap_user)
+ do_ast
+ load_registers 0
+ csrrw sp, sscratch, sp
+ eret
+END(cpu_exception_handler_user)
+
+/*
+ * Trap handlers
+ */
+ .text
+bad_trap:
+ j bad_trap
+
+user_trap:
+ csrrw sp, mscratch, sp
+ addi sp, sp, -64
+ sd t0, (8 * 0)(sp)
+ sd t1, (8 * 1)(sp)
+ sd t2, (8 * 2)(sp)
+ sd t3, (8 * 3)(sp)
+ sd t4, (8 * 4)(sp)
+ sd t5, (8 * 5)(sp)
+ sd a0, (8 * 7)(sp)
+
+ la t2, _C_LABEL(cpu_exception_handler_user)
+
+ csrr t0, mcause
+ bltz t0, machine_interrupt
+ j exit_mrts
+
+supervisor_trap:
+ /* Save state */
+ csrrw sp, mscratch, sp
+ addi sp, sp, -64
+ sd t0, (8 * 0)(sp)
+ sd t1, (8 * 1)(sp)
+ sd t2, (8 * 2)(sp)
+ sd t3, (8 * 3)(sp)
+ sd t4, (8 * 4)(sp)
+ sd t5, (8 * 5)(sp)
+ sd a0, (8 * 7)(sp)
+
+ la t2, _C_LABEL(cpu_exception_handler_supervisor)
+
+ csrr t0, mcause
+ bltz t0, machine_interrupt
+
+ li t1, EXCP_SMODE_ENV_CALL
+ beq t0, t1, supervisor_call
+ j exit_mrts
+
+machine_interrupt:
+ /* Type of interrupt ? */
+ csrr t0, mcause
+ andi t0, t0, 3
+ li t1, 0
+ beq t1, t0, software_interrupt
+ li t1, 1
+ beq t1, t0, timer_interrupt
+ li t1, 2
+ beq t1, t0, htif_interrupt
+
+ /* not reached */
+1:
+ j 1b
+
+software_interrupt:
+ /* Redirect to supervisor */
+ j exit_mrts
+
+timer_interrupt:
+ /* Disable machine timer interrupts */
+ li t0, MIE_MTIE
+ csrc mie, t0
+
+ /* Clear machine pending */
+ li t0, MIP_MTIP
+ csrc mip, t0
+
+ /* Post supervisor software interrupt */
+ li t0, MIP_STIP
+ csrs mip, t0
+
+ /* If PRV1 is PRV_U (user) then serve a trap */
+ csrr t0, mstatus
+ li t1, (MSTATUS_PRV_M << MSTATUS_PRV1_SHIFT)
+ and t0, t0, t1
+ beqz t0, 1f
+
+ /* If PRV1 is supervisor and interrupts were enabled, then serve a trap */
+ csrr t0, mstatus
+ li t1, (SR_IE1 | (MSTATUS_PRV_M << MSTATUS_PRV1_SHIFT))
+ and t0, t0, t1
+ li t1, (SR_IE1 | (MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT))
+ beq t0, t1, 1f
+
+ j exit
+
+1:
+ /* Serve a trap in supervisor mode */
+ j exit_mrts
+
+htif_interrupt:
+1:
+ li t5, 0
+ csrrw t5, mfromhost, t5
+ beqz t5, 3f
+
+ /* Console PUT intr ? */
+ mv t1, t5
+ li t0, 0x101
+ srli t1, t1, 48
+ bne t1, t0, 2f
+ /* Yes */
+ la t0, console_intr
+ li t1, 1
+ sd t1, 0(t0)
+ j 3f
+
+2:
+ /* Save entry */
+ la t0, htif_ring_cursor
+ beqz t0, 3f /* not initialized */
+ ld t0, 0(t0) /* load struct */
+ sd t5, 0(t0) /* put entry */
+ li t4, 1
+ sd t4, 8(t0) /* mark used */
+ ld t4, 16(t0) /* take next */
+ /* Update cursor */
+ la t0, htif_ring_cursor
+ sd t4, 0(t0)
+
+ /* Post supervisor software interrupt */
+ li t0, MIP_SSIP
+ csrs mip, t0
+
+3:
+ j exit
+
+supervisor_call:
+ csrr t1, mepc
+ addi t1, t1, 4 /* Next instruction in t1 */
+ li t4, ECALL_HTIF_CMD
+ beq t5, t4, htif_cmd
+ li t4, ECALL_HTIF_GET_ENTRY
+ beq t5, t4, htif_get_entry
+ li t4, ECALL_MTIMECMP
+ beq t5, t4, set_mtimecmp
+ li t4, ECALL_CLEAR_PENDING
+ beq t5, t4, clear_pending
+ li t4, ECALL_MCPUID_GET
+ beq t5, t4, mcpuid_get
+ li t4, ECALL_MIMPID_GET
+ beq t5, t4, mimpid_get
+ j exit_next_instr
+
+mcpuid_get:
+ csrr t6, mcpuid
+ j exit_next_instr
+
+mimpid_get:
+ csrr t6, mimpid
+ j exit_next_instr
+
+htif_get_entry:
+ li t6, 0 /* preset return value */
+ la t0, htif_ring_last
+ ld t0, 0(t0) /* load struct */
+ ld t4, 8(t0) /* get used */
+ beqz t4, 1f
+ ld t6, 0(t0) /* get entry */
+ li t4, 0
+ sd t4, 8(t0) /* mark free */
+ sd t4, 0(t0) /* free entry, just in case */
+ ld t4, 16(t0) /* take next */
+ la t0, htif_ring_last
+ sd t4, 0(t0)
+1:
+ /* Exit. Result is stored in t6 */
+ j exit_next_instr
+
+htif_cmd:
+ mv t0, t6
+1:
+ csrrw t0, mtohost, t0
+ bnez t0, 1b
+ j exit_next_instr
+
+set_mtimecmp:
+ csrr t2, stime
+ add t6, t6, t2
+ csrw mtimecmp, t6
+
+ /* Enable interrupts */
+ li t0, (MIE_MTIE | MIE_STIE)
+ csrs mie, t0
+ j exit_next_instr
+
+clear_pending:
+ li t0, MIP_STIP
+ csrc mip, t0
+ j exit_next_instr
+
+/*
+ * Trap exit functions
+ */
+exit_next_instr:
+ /* Next instruction is in t1 */
+ csrw mepc, t1
+exit:
+ /* Restore state */
+ ld t0, (8 * 0)(sp)
+ ld t1, (8 * 1)(sp)
+ ld t2, (8 * 2)(sp)
+ ld t3, (8 * 3)(sp)
+ ld t4, (8 * 4)(sp)
+ ld t5, (8 * 5)(sp)
+ ld a0, (8 * 7)(sp)
+ addi sp, sp, 64
+ csrrw sp, mscratch, sp
+ eret
+
+/*
+ * Redirect to supervisor
+ */
+exit_mrts:
+ /* Setup exception handler */
+ li t1, KERNBASE
+ add t2, t2, t1
+ csrw stvec, t2
+
+ /* Restore state */
+ ld t0, (8 * 0)(sp)
+ ld t1, (8 * 1)(sp)
+ ld t2, (8 * 2)(sp)
+ ld t3, (8 * 3)(sp)
+ ld t4, (8 * 4)(sp)
+ ld t5, (8 * 5)(sp)
+ ld a0, (8 * 7)(sp)
+ addi sp, sp, 64
+ csrrw sp, mscratch, sp
+
+ /* Redirect to supervisor */
+ mrts
diff --git a/sys/riscv/riscv/genassym.c b/sys/riscv/riscv/genassym.c
new file mode 100644
index 000000000000..bf6c8fb4c851
--- /dev/null
+++ b/sys/riscv/riscv/genassym.c
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/assym.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <sys/vmmeter.h>
+#include <sys/bus.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+
+#include <machine/vmparam.h>
+#include <machine/riscvreg.h>
+#include <machine/frame.h>
+#include <machine/pcb.h>
+#include <machine/cpu.h>
+#include <machine/proc.h>
+#include <machine/cpufunc.h>
+#include <machine/pte.h>
+#include <machine/intr.h>
+
+ASSYM(KERNBASE, KERNBASE);
+ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS);
+ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);
+ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
+
+ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
+ASSYM(PCB_L1ADDR, offsetof(struct pcb, pcb_l1addr));
+ASSYM(PCB_SIZE, sizeof(struct pcb));
+ASSYM(PCB_RA, offsetof(struct pcb, pcb_ra));
+ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp));
+ASSYM(PCB_GP, offsetof(struct pcb, pcb_gp));
+ASSYM(PCB_TP, offsetof(struct pcb, pcb_tp));
+ASSYM(PCB_T, offsetof(struct pcb, pcb_t));
+ASSYM(PCB_S, offsetof(struct pcb, pcb_s));
+ASSYM(PCB_A, offsetof(struct pcb, pcb_a));
+
+ASSYM(SF_UC, offsetof(struct sigframe, sf_uc));
+
+ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb));
+ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
+
+ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
+ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
+ASSYM(TD_PROC, offsetof(struct thread, td_proc));
+ASSYM(TD_FRAME, offsetof(struct thread, td_frame));
+ASSYM(TD_MD, offsetof(struct thread, td_md));
+ASSYM(TD_LOCK, offsetof(struct thread, td_lock));
+
+ASSYM(TF_SIZE, sizeof(struct trapframe));
+ASSYM(TF_RA, offsetof(struct trapframe, tf_ra));
+ASSYM(TF_SP, offsetof(struct trapframe, tf_sp));
+ASSYM(TF_GP, offsetof(struct trapframe, tf_gp));
+ASSYM(TF_TP, offsetof(struct trapframe, tf_tp));
+ASSYM(TF_T, offsetof(struct trapframe, tf_t));
+ASSYM(TF_S, offsetof(struct trapframe, tf_s));
+ASSYM(TF_A, offsetof(struct trapframe, tf_a));
+ASSYM(TF_SEPC, offsetof(struct trapframe, tf_sepc));
+ASSYM(TF_SBADADDR, offsetof(struct trapframe, tf_sbadaddr));
+ASSYM(TF_SCAUSE, offsetof(struct trapframe, tf_scause));
+ASSYM(TF_SSTATUS, offsetof(struct trapframe, tf_sstatus));
diff --git a/sys/riscv/riscv/identcpu.c b/sys/riscv/riscv/identcpu.c
new file mode 100644
index 000000000000..dd1f2ba13382
--- /dev/null
+++ b/sys/riscv/riscv/identcpu.c
@@ -0,0 +1,149 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/pcpu.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/trap.h>
+
+char machine[] = "riscv";
+
+SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0,
+ "Machine class");
+
+struct cpu_desc {
+ u_int cpu_impl;
+ u_int cpu_part_num;
+ const char *cpu_impl_name;
+ const char *cpu_part_name;
+};
+
+struct cpu_desc cpu_desc[MAXCPU];
+
+struct cpu_parts {
+ u_int part_id;
+ const char *part_name;
+};
+#define CPU_PART_NONE { -1, "Unknown Processor" }
+
+struct cpu_implementers {
+ u_int impl_id;
+ const char *impl_name;
+ /*
+ * Part number is implementation defined
+ * so each vendor will have its own set of values and names.
+ */
+ const struct cpu_parts *cpu_parts;
+};
+#define CPU_IMPLEMENTER_NONE { 0, "Unknown Implementer", cpu_parts_none }
+
+/*
+ * Per-implementer table of (PartNum, CPU Name) pairs.
+ */
+/* UC Berkeley */
+static const struct cpu_parts cpu_parts_ucb[] = {
+ { CPU_PART_RV32I, "RV32I" },
+ { CPU_PART_RV32E, "RV32E" },
+ { CPU_PART_RV64I, "RV64I" },
+ { CPU_PART_RV128I, "RV128I" },
+ CPU_PART_NONE,
+};
+
+/* Unknown */
+static const struct cpu_parts cpu_parts_none[] = {
+ CPU_PART_NONE,
+};
+
+/*
+ * Implementers table.
+ */
+const struct cpu_implementers cpu_implementers[] = {
+ { CPU_IMPL_UCB_ROCKET, "UC Berkeley Rocket", cpu_parts_ucb },
+ CPU_IMPLEMENTER_NONE,
+};
+
+void
+identify_cpu(void)
+{
+ const struct cpu_parts *cpu_partsp;
+ uint32_t part_id;
+ uint32_t impl_id;
+ uint64_t mimpid;
+ uint64_t mcpuid;
+ u_int cpu;
+ size_t i;
+
+ cpu_partsp = NULL;
+
+ mimpid = machine_command(ECALL_MIMPID_GET, 0);
+ mcpuid = machine_command(ECALL_MCPUID_GET, 0);
+
+ /* SMPTODO: use mhartid ? */
+ cpu = PCPU_GET(cpuid);
+
+ impl_id = CPU_IMPL(mimpid);
+ for (i = 0; i < nitems(cpu_implementers); i++) {
+ if (impl_id == cpu_implementers[i].impl_id ||
+ cpu_implementers[i].impl_id == 0) {
+ cpu_desc[cpu].cpu_impl = impl_id;
+ cpu_desc[cpu].cpu_impl_name = cpu_implementers[i].impl_name;
+ cpu_partsp = cpu_implementers[i].cpu_parts;
+ break;
+ }
+ }
+
+ part_id = CPU_PART(mcpuid);
+ for (i = 0; &cpu_partsp[i] != NULL; i++) {
+ if (part_id == cpu_partsp[i].part_id ||
+ cpu_partsp[i].part_id == -1) {
+ cpu_desc[cpu].cpu_part_num = part_id;
+ cpu_desc[cpu].cpu_part_name = cpu_partsp[i].part_name;
+ break;
+ }
+ }
+
+ /* Print details for boot CPU or if we want verbose output */
+ if (cpu == 0 || bootverbose) {
+ printf("CPU(%d): %s %s\n", cpu,
+ cpu_desc[cpu].cpu_impl_name,
+ cpu_desc[cpu].cpu_part_name);
+ }
+}
diff --git a/sys/riscv/riscv/in_cksum.c b/sys/riscv/riscv/in_cksum.c
new file mode 100644
index 000000000000..ae02e91d9203
--- /dev/null
+++ b/sys/riscv/riscv/in_cksum.c
@@ -0,0 +1,241 @@
+/* $NetBSD: in_cksum.c,v 1.7 1997/09/02 13:18:15 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1988, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1996
+ * Matt Thomas <matt@3am-software.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/systm.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <machine/in_cksum.h>
+
+/*
+ * Checksum routine for Internet Protocol family headers
+ * (Portable Alpha version).
+ *
+ * This routine is very heavily used in the network
+ * code and should be modified for each CPU to be as fast as possible.
+ */
+
+#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
+#define REDUCE32 \
+ { \
+ q_util.q = sum; \
+ sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
+ }
+#define REDUCE16 \
+ { \
+ q_util.q = sum; \
+ l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
+ sum = l_util.s[0] + l_util.s[1]; \
+ ADDCARRY(sum); \
+ }
+
+static const u_int32_t in_masks[] = {
+ /*0 bytes*/ /*1 byte*/ /*2 bytes*/ /*3 bytes*/
+ 0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF, /* offset 0 */
+ 0x00000000, 0x0000FF00, 0x00FFFF00, 0xFFFFFF00, /* offset 1 */
+ 0x00000000, 0x00FF0000, 0xFFFF0000, 0xFFFF0000, /* offset 2 */
+ 0x00000000, 0xFF000000, 0xFF000000, 0xFF000000, /* offset 3 */
+};
+
+union l_util {
+ u_int16_t s[2];
+ u_int32_t l;
+};
+union q_util {
+ u_int16_t s[4];
+ u_int32_t l[2];
+ u_int64_t q;
+};
+
+static u_int64_t
+in_cksumdata(const void *buf, int len)
+{
+ const u_int32_t *lw = (const u_int32_t *) buf;
+ u_int64_t sum = 0;
+ u_int64_t prefilled;
+ int offset;
+ union q_util q_util;
+
+ if ((3 & (long) lw) == 0 && len == 20) {
+ sum = (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3] + lw[4];
+ REDUCE32;
+ return sum;
+ }
+
+ if ((offset = 3 & (long) lw) != 0) {
+ const u_int32_t *masks = in_masks + (offset << 2);
+ lw = (u_int32_t *) (((long) lw) - offset);
+ sum = *lw++ & masks[len >= 3 ? 3 : len];
+ len -= 4 - offset;
+ if (len <= 0) {
+ REDUCE32;
+ return sum;
+ }
+ }
+#if 0
+ /*
+ * Force to cache line boundary.
+ */
+ offset = 32 - (0x1f & (long) lw);
+ if (offset < 32 && len > offset) {
+ len -= offset;
+ if (4 & offset) {
+ sum += (u_int64_t) lw[0];
+ lw += 1;
+ }
+ if (8 & offset) {
+ sum += (u_int64_t) lw[0] + lw[1];
+ lw += 2;
+ }
+ if (16 & offset) {
+ sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3];
+ lw += 4;
+ }
+ }
+#endif
+ /*
+ * access prefilling to start load of next cache line.
+ * then add current cache line
+ * save result of prefilling for loop iteration.
+ */
+ prefilled = lw[0];
+ while ((len -= 32) >= 4) {
+ u_int64_t prefilling = lw[8];
+ sum += prefilled + lw[1] + lw[2] + lw[3]
+ + lw[4] + lw[5] + lw[6] + lw[7];
+ lw += 8;
+ prefilled = prefilling;
+ }
+ if (len >= 0) {
+ sum += prefilled + lw[1] + lw[2] + lw[3]
+ + lw[4] + lw[5] + lw[6] + lw[7];
+ lw += 8;
+ } else {
+ len += 32;
+ }
+ while ((len -= 16) >= 0) {
+ sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3];
+ lw += 4;
+ }
+ len += 16;
+ while ((len -= 4) >= 0) {
+ sum += (u_int64_t) *lw++;
+ }
+ len += 4;
+ if (len > 0)
+ sum += (u_int64_t) (in_masks[len] & *lw);
+ REDUCE32;
+ return sum;
+}
+
+u_short
+in_addword(u_short a, u_short b)
+{
+ u_int64_t sum = a + b;
+
+ ADDCARRY(sum);
+ return (sum);
+}
+
+u_short
+in_pseudo(u_int32_t a, u_int32_t b, u_int32_t c)
+{
+ u_int64_t sum;
+ union q_util q_util;
+ union l_util l_util;
+
+ sum = (u_int64_t) a + b + c;
+ REDUCE16;
+ return (sum);
+}
+
+u_short
+in_cksum_skip(struct mbuf *m, int len, int skip)
+{
+ u_int64_t sum = 0;
+ int mlen = 0;
+ int clen = 0;
+ caddr_t addr;
+ union q_util q_util;
+ union l_util l_util;
+
+ len -= skip;
+ for (; skip && m; m = m->m_next) {
+ if (m->m_len > skip) {
+ mlen = m->m_len - skip;
+ addr = mtod(m, caddr_t) + skip;
+ goto skip_start;
+ } else {
+ skip -= m->m_len;
+ }
+ }
+
+ for (; m && len; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ mlen = m->m_len;
+ addr = mtod(m, caddr_t);
+skip_start:
+ if (len < mlen)
+ mlen = len;
+ if ((clen ^ (long) addr) & 1)
+ sum += in_cksumdata(addr, mlen) << 8;
+ else
+ sum += in_cksumdata(addr, mlen);
+
+ clen += mlen;
+ len -= mlen;
+ }
+ REDUCE16;
+ return (~sum & 0xffff);
+}
+
+u_int in_cksum_hdr(const struct ip *ip)
+{
+ u_int64_t sum = in_cksumdata(ip, sizeof(struct ip));
+ union q_util q_util;
+ union l_util l_util;
+ REDUCE16;
+ return (~sum & 0xffff);
+}
diff --git a/sys/riscv/riscv/intr_machdep.c b/sys/riscv/riscv/intr_machdep.c
new file mode 100644
index 000000000000..c51075c8a24b
--- /dev/null
+++ b/sys/riscv/riscv/intr_machdep.c
@@ -0,0 +1,223 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+
+#include <machine/clock.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+
+enum {
+ IRQ_SOFTWARE,
+ IRQ_TIMER,
+ IRQ_HTIF,
+ NIRQS
+};
+
+u_long intrcnt[NIRQS];
+size_t sintrcnt = sizeof(intrcnt);
+
+char intrnames[NIRQS * (MAXCOMLEN + 1) * 2];
+size_t sintrnames = sizeof(intrnames);
+
+static struct intr_event *intr_events[NIRQS];
+static riscv_intrcnt_t riscv_intr_counters[NIRQS];
+
+static int intrcnt_index;
+
+riscv_intrcnt_t
+riscv_intrcnt_create(const char* name)
+{
+ riscv_intrcnt_t counter;
+
+ counter = &intrcnt[intrcnt_index++];
+ riscv_intrcnt_setname(counter, name);
+
+ return (counter);
+}
+
+void
+riscv_intrcnt_setname(riscv_intrcnt_t counter, const char *name)
+{
+ int i;
+
+ i = (counter - intrcnt);
+
+ KASSERT(counter != NULL, ("riscv_intrcnt_setname: NULL counter"));
+
+ snprintf(intrnames + (MAXCOMLEN + 1) * i,
+ MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name);
+}
+
+static void
+riscv_mask_irq(void *source)
+{
+ uintptr_t irq;
+
+ irq = (uintptr_t)source;
+
+ switch (irq) {
+ case IRQ_TIMER:
+ csr_clear(sie, SIE_STIE);
+ break;
+ case IRQ_SOFTWARE:
+ csr_clear(sie, SIE_SSIE);
+ break;
+ default:
+ panic("Unknown irq %d\n", irq);
+ }
+}
+
+static void
+riscv_unmask_irq(void *source)
+{
+ uintptr_t irq;
+
+ irq = (uintptr_t)source;
+
+ switch (irq) {
+ case IRQ_TIMER:
+ csr_set(sie, SIE_STIE);
+ break;
+ case IRQ_SOFTWARE:
+ csr_set(sie, SIE_SSIE);
+ break;
+ default:
+ panic("Unknown irq %d\n", irq);
+ }
+}
+
+void
+riscv_init_interrupts(void)
+{
+ char name[MAXCOMLEN + 1];
+ int i;
+
+ for (i = 0; i < NIRQS; i++) {
+ snprintf(name, MAXCOMLEN + 1, "int%d:", i);
+ riscv_intr_counters[i] = riscv_intrcnt_create(name);
+ }
+}
+
+int
+riscv_setup_intr(const char *name, driver_filter_t *filt,
+ void (*handler)(void*), void *arg, int irq, int flags, void **cookiep)
+{
+ struct intr_event *event;
+ int error;
+
+ if (irq < 0 || irq >= NIRQS)
+ panic("%s: unknown intr %d", __func__, irq);
+
+ event = intr_events[irq];
+ if (event == NULL) {
+ error = intr_event_create(&event, (void *)(uintptr_t)irq, 0,
+ irq, riscv_mask_irq, riscv_unmask_irq,
+ NULL, NULL, "int%d", irq);
+ if (error)
+ return (error);
+ intr_events[irq] = event;
+ riscv_unmask_irq((void*)(uintptr_t)irq);
+ }
+
+ intr_event_add_handler(event, name, filt, handler, arg,
+ intr_priority(flags), flags, cookiep);
+
+ riscv_intrcnt_setname(riscv_intr_counters[irq],
+ event->ie_fullname);
+
+ return (0);
+}
+
+int
+riscv_teardown_intr(void *ih)
+{
+
+ /* TODO */
+
+ return (0);
+}
+
+int
+riscv_config_intr(u_int irq, enum intr_trigger trig, enum intr_polarity pol)
+{
+
+ /* There is no configuration for interrupts */
+
+ return (0);
+}
+
+void
+riscv_cpu_intr(struct trapframe *frame)
+{
+ struct intr_event *event;
+ int active_irq;
+
+ critical_enter();
+
+ KASSERT(frame->tf_scause & EXCP_INTR,
+ ("riscv_cpu_intr: wrong frame passed"));
+
+ active_irq = (frame->tf_scause & EXCP_MASK);
+
+ switch (active_irq) {
+ case IRQ_SOFTWARE:
+ case IRQ_TIMER:
+ event = intr_events[active_irq];
+ /* Update counters */
+ atomic_add_long(riscv_intr_counters[active_irq], 1);
+ PCPU_INC(cnt.v_intr);
+ break;
+ case IRQ_HTIF:
+ /* HTIF interrupts are only handled in machine mode */
+ panic("%s: HTIF interrupt", __func__);
+ break;
+ default:
+ event = NULL;
+ }
+
+ if (!event || TAILQ_EMPTY(&event->ie_handlers) ||
+ (intr_event_handle(event, frame) != 0))
+ printf("stray interrupt %d\n", active_irq);
+
+ critical_exit();
+}
diff --git a/sys/riscv/riscv/locore.S b/sys/riscv/riscv/locore.S
new file mode 100644
index 000000000000..8dc424e7fc4e
--- /dev/null
+++ b/sys/riscv/riscv/locore.S
@@ -0,0 +1,274 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "assym.s"
+
+#include <sys/syscall.h>
+#include <machine/asm.h>
+#include <machine/param.h>
+#include <machine/trap.h>
+#include <machine/riscvreg.h>
+#include <machine/pte.h>
+
+#define HTIF_RING_SIZE (64)
+#define HTIF_RING_LAST (24 * (HTIF_RING_SIZE - 1))
+
+ .globl kernbase
+ .set kernbase, KERNBASE
+
+ /* Trap entries */
+ .text
+
+mentry:
+ /* User mode entry point (mtvec + 0x000) */
+ .align 6
+ j user_trap
+
+ /* Supervisor mode entry point (mtvec + 0x040) */
+ .align 6
+ j supervisor_trap
+
+ /* Hypervisor mode entry point (mtvec + 0x080) */
+ .align 6
+ j bad_trap
+
+ /* Machine mode entry point (mtvec + 0x0C0) */
+ .align 6
+ j bad_trap
+
+ /* Reset vector */
+ .text
+ .align 8
+ .globl _start
+_start:
+ li s11, KERNBASE
+
+ /* Build ring */
+ la t0, htif_ring
+ li t1, 0
+ sd t1, 0(t0) /* zero data */
+ sd t1, 8(t0) /* zero used */
+ mv t2, t0
+ mv t3, t0
+ li t5, HTIF_RING_LAST
+ li t6, 0
+ add t4, t0, t5
+1:
+ addi t3, t3, 24 /* pointer to next */
+ beq t3, t4, 2f /* finish */
+ sd t3, 16(t2) /* store pointer */
+ addi t2, t2, 24 /* next entry */
+ addi t6, t6, 1 /* counter */
+ j 1b
+2:
+ sd t0, 16(t3) /* last -> first */
+ la t1, htif_ring_cursor
+ sd t0, 0(t1)
+ la t1, htif_ring_last
+ sd t0, 0(t1)
+ /* finish building ring */
+
+ la t0, hardstack_end
+ sub t0, t0, s11
+ csrw mscratch, t0
+
+ la t0, mentry
+ csrw mtvec, t0
+
+ li t0, 0
+ csrw sscratch, t0
+
+ li s10, PAGE_SIZE
+ li s9, (PAGE_SIZE * KSTACK_PAGES)
+
+ /* Page tables */
+
+ /* Level 0 */
+ la s1, pagetable_l0
+ la s2, pagetable_l1 /* Link to next level PN */
+ srli s2, s2, PAGE_SHIFT
+
+ li t4, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S))
+ slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
+ or t6, t4, t5
+
+ /* Store single level0 PTE entry to position */
+ li a5, 0x1ff
+ li a6, PTE_SIZE
+ mulw a5, a5, a6
+ add t0, s1, a5
+ sd t6, 0(t0)
+
+ /* Level 1 */
+ la s1, pagetable_l1
+ la s2, pagetable_l2 /* Link to next level PN */
+ srli s2, s2, PAGE_SHIFT
+
+ li a5, KERNBASE
+ srli a5, a5, 0x1e /* >> 30 */
+ andi a5, a5, 0x1ff /* & 0x1ff */
+ li t4, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S))
+ slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
+ or t6, t4, t5
+
+ /* Store single level1 PTE entry to position */
+ li a6, PTE_SIZE
+ mulw a5, a5, a6
+ add t0, s1, a5
+ sd t6, (t0)
+
+ /* Level 2 superpages (512 x 2MiB) */
+ la s1, pagetable_l2
+ li t3, 512 /* Build 512 entries */
+ li t4, 0 /* Counter */
+ li t5, 0
+2:
+ li t0, (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S))
+ slli t2, t4, PTE_PPN1_S /* << PTE_PPN1_S */
+ or t5, t0, t2
+ sd t5, (s1) /* Store PTE entry to position */
+ addi s1, s1, PTE_SIZE
+
+ addi t4, t4, 1
+ bltu t4, t3, 2b
+
+ /* Set page tables base register */
+ la s1, pagetable_l0
+ csrw sptbr, s1
+
+ /* Page tables END */
+
+ /* Enter supervisor mode */
+ li s0, ((MSTATUS_VM_SV48 << MSTATUS_VM_SHIFT) | \
+ (MSTATUS_PRV_M << MSTATUS_PRV_SHIFT) | \
+ (MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT) | \
+ (MSTATUS_PRV_U << MSTATUS_PRV2_SHIFT));
+ csrw mstatus, s0
+
+ /* Exit from machine mode */
+ la t0, .Lmmu_on
+ add t0, t0, s11
+ csrw mepc, t0
+ eret
+
+.Lmmu_on:
+ /* Initialize stack pointer */
+ la s3, initstack_end
+ mv sp, s3
+ addi sp, sp, -PCB_SIZE
+
+ /* Clear BSS */
+ la a0, _C_LABEL(__bss_start)
+ la s1, _C_LABEL(_end)
+1:
+ sd zero, 0(a0)
+ addi a0, a0, 8
+ bltu a0, s1, 1b
+
+ /* Fill riscv_bootparams */
+ addi sp, sp, -16
+ la t0, pagetable_l1
+ sd t0, 0(sp) /* kern_l1pt */
+ la t0, initstack_end
+ sd t0, 8(sp) /* kern_stack */
+
+ mv a0, sp
+ call _C_LABEL(initriscv) /* Off we go */
+ call _C_LABEL(mi_startup)
+
+ .align 4
+initstack:
+ .space (PAGE_SIZE * KSTACK_PAGES)
+initstack_end:
+hardstack:
+ .space (PAGE_SIZE)
+hardstack_end:
+
+ .globl htif_ring
+htif_ring:
+ .space (24 * 1024)
+
+ .globl htif_ring_cursor
+htif_ring_cursor:
+ .space (8)
+
+ .globl htif_ring_last
+htif_ring_last:
+ .space (8)
+
+ .globl console_intr
+console_intr:
+ .space (8)
+
+ENTRY(sigcode)
+ mv a0, sp
+ addi a0, a0, SF_UC
+
+1:
+ li t0, SYS_sigreturn
+ ecall
+
+ /* sigreturn failed, exit */
+ li t0, SYS_exit
+ ecall
+
+ j 1b
+END(sigcode)
+ /* This may be copied to the stack, keep it 16-byte aligned */
+ .align 3
+esigcode:
+
+ .data
+ .align 3
+ .global szsigcode
+szsigcode:
+ .quad esigcode - sigcode
+
+ .align 12
+ .globl pagetable_l0
+pagetable_l0:
+ .space PAGE_SIZE
+pagetable_l1:
+ .space PAGE_SIZE
+pagetable_l2:
+ .space PAGE_SIZE
+pagetable_end:
+
+ .globl init_pt_va
+init_pt_va:
+ .quad pagetable_l2 /* XXX: Keep page tables VA */
+
+#include "exception.S"
diff --git a/sys/riscv/riscv/machdep.c b/sys/riscv/riscv/machdep.c
new file mode 100644
index 000000000000..79688e6f3009
--- /dev/null
+++ b/sys/riscv/riscv/machdep.c
@@ -0,0 +1,794 @@
+/*-
+ * Copyright (c) 2014 Andrew Turner
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <sys/cpu.h>
+#include <sys/exec.h>
+#include <sys/imgact.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/linker.h>
+#include <sys/msgbuf.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <sys/reboot.h>
+#include <sys/rwlock.h>
+#include <sys/sched.h>
+#include <sys/signalvar.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/ucontext.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_pager.h>
+
+#include <machine/riscvreg.h>
+#include <machine/cpu.h>
+#include <machine/kdb.h>
+#include <machine/machdep.h>
+#include <machine/pcb.h>
+#include <machine/reg.h>
+#include <machine/trap.h>
+#include <machine/vmparam.h>
+#include <machine/intr.h>
+
+#include <machine/asm.h>
+
+#ifdef VFP
+#include <machine/vfp.h>
+#endif
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#endif
+
+struct pcpu __pcpu[MAXCPU];
+
+static struct trapframe proc0_tf;
+
+vm_paddr_t phys_avail[PHYS_AVAIL_SIZE + 2];
+vm_paddr_t dump_avail[PHYS_AVAIL_SIZE + 2];
+
+int early_boot = 1;
+int cold = 1;
+long realmem = 0;
+long Maxmem = 0;
+
+#define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1))
+vm_paddr_t physmap[PHYSMAP_SIZE];
+u_int physmap_idx;
+
+struct kva_md_info kmi;
+
+int64_t dcache_line_size; /* The minimum D cache line size */
+int64_t icache_line_size; /* The minimum I cache line size */
+int64_t idcache_line_size; /* The minimum cache line size */
+
+extern int *end;
+extern int *initstack_end;
+
+struct pcpu *pcpup;
+
+uintptr_t mcall_trap(uintptr_t mcause, uintptr_t* regs);
+
+uintptr_t
+mcall_trap(uintptr_t mcause, uintptr_t* regs)
+{
+
+ return (0);
+}
+
+static void
+cpu_startup(void *dummy)
+{
+
+ identify_cpu();
+
+ vm_ksubmap_init(&kmi);
+ bufinit();
+ vm_pager_bufferinit();
+}
+
+SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
+
+int
+cpu_idle_wakeup(int cpu)
+{
+
+ return (0);
+}
+
+void
+bzero(void *buf, size_t len)
+{
+ uint8_t *p;
+
+ p = buf;
+ while(len-- > 0)
+ *p++ = 0;
+}
+
+int
+fill_regs(struct thread *td, struct reg *regs)
+{
+ struct trapframe *frame;
+
+ frame = td->td_frame;
+ regs->sepc = frame->tf_sepc;
+ regs->sstatus = frame->tf_sstatus;
+ regs->ra = frame->tf_ra;
+ regs->sp = frame->tf_sp;
+ regs->gp = frame->tf_gp;
+ regs->tp = frame->tf_tp;
+
+ memcpy(regs->t, frame->tf_t, sizeof(regs->t));
+ memcpy(regs->s, frame->tf_s, sizeof(regs->s));
+ memcpy(regs->a, frame->tf_a, sizeof(regs->a));
+
+ return (0);
+}
+
+int
+set_regs(struct thread *td, struct reg *regs)
+{
+ struct trapframe *frame;
+
+ frame = td->td_frame;
+ frame->tf_sepc = regs->sepc;
+ frame->tf_sstatus = regs->sstatus;
+ frame->tf_ra = regs->ra;
+ frame->tf_sp = regs->sp;
+ frame->tf_gp = regs->gp;
+ frame->tf_tp = regs->tp;
+
+ memcpy(frame->tf_t, regs->t, sizeof(frame->tf_t));
+ memcpy(frame->tf_s, regs->s, sizeof(frame->tf_s));
+ memcpy(frame->tf_a, regs->a, sizeof(frame->tf_a));
+
+ return (0);
+}
+
+int
+fill_fpregs(struct thread *td, struct fpreg *regs)
+{
+
+ /* TODO */
+ bzero(regs, sizeof(*regs));
+ return (0);
+}
+
+int
+set_fpregs(struct thread *td, struct fpreg *regs)
+{
+
+ /* TODO */
+ return (0);
+}
+
+int
+fill_dbregs(struct thread *td, struct dbreg *regs)
+{
+
+ panic("fill_dbregs");
+}
+
+int
+set_dbregs(struct thread *td, struct dbreg *regs)
+{
+
+ panic("set_dbregs");
+}
+
+int
+ptrace_set_pc(struct thread *td, u_long addr)
+{
+
+ panic("ptrace_set_pc");
+ return (0);
+}
+
+int
+ptrace_single_step(struct thread *td)
+{
+
+ /* TODO; */
+ return (0);
+}
+
+int
+ptrace_clear_single_step(struct thread *td)
+{
+
+ /* TODO; */
+ return (0);
+}
+
+void
+exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
+{
+ struct trapframe *tf;
+
+ tf = td->td_frame;
+
+ memset(tf, 0, sizeof(struct trapframe));
+
+ /*
+ * We need to set a0 for init as it doesn't call
+ * cpu_set_syscall_retval to copy the value. We also
+ * need to set td_retval for the cases where we do.
+ */
+ tf->tf_a[0] = td->td_retval[0] = stack;
+ tf->tf_sp = STACKALIGN(stack);
+ tf->tf_ra = imgp->entry_addr;
+ tf->tf_sepc = imgp->entry_addr;
+}
+
+/* Sanity check these are the same size, they will be memcpy'd to and fro */
+CTASSERT(sizeof(((struct trapframe *)0)->tf_a) ==
+ sizeof((struct gpregs *)0)->gp_a);
+CTASSERT(sizeof(((struct trapframe *)0)->tf_s) ==
+ sizeof((struct gpregs *)0)->gp_s);
+CTASSERT(sizeof(((struct trapframe *)0)->tf_t) ==
+ sizeof((struct gpregs *)0)->gp_t);
+CTASSERT(sizeof(((struct trapframe *)0)->tf_a) ==
+ sizeof((struct reg *)0)->a);
+CTASSERT(sizeof(((struct trapframe *)0)->tf_s) ==
+ sizeof((struct reg *)0)->s);
+CTASSERT(sizeof(((struct trapframe *)0)->tf_t) ==
+ sizeof((struct reg *)0)->t);
+
+int
+get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
+{
+ struct trapframe *tf = td->td_frame;
+
+ memcpy(mcp->mc_gpregs.gp_t, tf->tf_t, sizeof(mcp->mc_gpregs.gp_t));
+ memcpy(mcp->mc_gpregs.gp_s, tf->tf_s, sizeof(mcp->mc_gpregs.gp_s));
+ memcpy(mcp->mc_gpregs.gp_a, tf->tf_a, sizeof(mcp->mc_gpregs.gp_a));
+
+ if (clear_ret & GET_MC_CLEAR_RET) {
+ mcp->mc_gpregs.gp_a[0] = 0;
+ mcp->mc_gpregs.gp_t[0] = 0; /* clear syscall error */
+ }
+
+ mcp->mc_gpregs.gp_ra = tf->tf_ra;
+ mcp->mc_gpregs.gp_sp = tf->tf_sp;
+ mcp->mc_gpregs.gp_gp = tf->tf_gp;
+ mcp->mc_gpregs.gp_tp = tf->tf_tp;
+ mcp->mc_gpregs.gp_sepc = tf->tf_sepc;
+ mcp->mc_gpregs.gp_sstatus = tf->tf_sstatus;
+
+ return (0);
+}
+
+int
+set_mcontext(struct thread *td, mcontext_t *mcp)
+{
+ struct trapframe *tf;
+
+ tf = td->td_frame;
+
+ memcpy(tf->tf_t, mcp->mc_gpregs.gp_t, sizeof(tf->tf_t));
+ memcpy(tf->tf_s, mcp->mc_gpregs.gp_s, sizeof(tf->tf_s));
+ memcpy(tf->tf_a, mcp->mc_gpregs.gp_a, sizeof(tf->tf_a));
+
+ tf->tf_ra = mcp->mc_gpregs.gp_ra;
+ tf->tf_sp = mcp->mc_gpregs.gp_sp;
+ tf->tf_gp = mcp->mc_gpregs.gp_gp;
+ tf->tf_tp = mcp->mc_gpregs.gp_tp;
+ tf->tf_sepc = mcp->mc_gpregs.gp_sepc;
+ tf->tf_sstatus = mcp->mc_gpregs.gp_sstatus;
+
+ return (0);
+}
+
+static void
+get_fpcontext(struct thread *td, mcontext_t *mcp)
+{
+ /* TODO */
+}
+
+static void
+set_fpcontext(struct thread *td, mcontext_t *mcp)
+{
+ /* TODO */
+}
+
+void
+cpu_idle(int busy)
+{
+
+ spinlock_enter();
+ if (!busy)
+ cpu_idleclock();
+ if (!sched_runnable())
+ __asm __volatile(
+ "fence \n"
+ "wfi \n");
+ if (!busy)
+ cpu_activeclock();
+ spinlock_exit();
+}
+
+void
+cpu_halt(void)
+{
+
+ panic("cpu_halt");
+}
+
+/*
+ * Flush the D-cache for non-DMA I/O so that the I-cache can
+ * be made coherent later.
+ */
+void
+cpu_flush_dcache(void *ptr, size_t len)
+{
+
+ /* TBD */
+}
+
+/* Get current clock frequency for the given CPU ID. */
+int
+cpu_est_clockrate(int cpu_id, uint64_t *rate)
+{
+
+ panic("cpu_est_clockrate");
+}
+
+void
+cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
+{
+
+}
+
+void
+spinlock_enter(void)
+{
+ struct thread *td;
+
+ td = curthread;
+ if (td->td_md.md_spinlock_count == 0) {
+ td->td_md.md_spinlock_count = 1;
+ td->td_md.md_saved_sstatus_ie = intr_disable();
+ } else
+ td->td_md.md_spinlock_count++;
+ critical_enter();
+}
+
+void
+spinlock_exit(void)
+{
+ struct thread *td;
+ register_t sstatus_ie;
+
+ td = curthread;
+ critical_exit();
+ sstatus_ie = td->td_md.md_saved_sstatus_ie;
+ td->td_md.md_spinlock_count--;
+ if (td->td_md.md_spinlock_count == 0)
+ intr_restore(sstatus_ie);
+}
+
+#ifndef _SYS_SYSPROTO_H_
+struct sigreturn_args {
+ ucontext_t *ucp;
+};
+#endif
+
+int
+sys_sigreturn(struct thread *td, struct sigreturn_args *uap)
+{
+ uint64_t sstatus;
+ ucontext_t uc;
+ int error;
+
+ if (uap == NULL)
+ return (EFAULT);
+ if (copyin(uap->sigcntxp, &uc, sizeof(uc)))
+ return (EFAULT);
+
+ /*
+ * Make sure the processor mode has not been tampered with and
+ * interrupts have not been disabled.
+ */
+ sstatus = uc.uc_mcontext.mc_gpregs.gp_sstatus;
+ if ((sstatus & SSTATUS_PS) != 0 ||
+ (sstatus & SSTATUS_PIE) == 0)
+ return (EINVAL);
+
+ error = set_mcontext(td, &uc.uc_mcontext);
+ if (error != 0)
+ return (error);
+
+ set_fpcontext(td, &uc.uc_mcontext);
+
+ /* Restore signal mask. */
+ kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
+
+ return (EJUSTRETURN);
+}
+
+/*
+ * Construct a PCB from a trapframe. This is called from kdb_trap() where
+ * we want to start a backtrace from the function that caused us to enter
+ * the debugger. We have the context in the trapframe, but base the trace
+ * on the PCB. The PCB doesn't have to be perfect, as long as it contains
+ * enough for a backtrace.
+ */
+void
+makectx(struct trapframe *tf, struct pcb *pcb)
+{
+
+ memcpy(pcb->pcb_t, tf->tf_t, sizeof(tf->tf_t));
+ memcpy(pcb->pcb_s, tf->tf_s, sizeof(tf->tf_s));
+ memcpy(pcb->pcb_a, tf->tf_a, sizeof(tf->tf_a));
+
+ pcb->pcb_ra = tf->tf_ra;
+ pcb->pcb_sp = tf->tf_sp;
+ pcb->pcb_gp = tf->tf_gp;
+ pcb->pcb_tp = tf->tf_tp;
+ pcb->pcb_sepc = tf->tf_sepc;
+}
+
+void
+sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
+{
+ struct sigframe *fp, frame;
+ struct sysentvec *sysent;
+ struct trapframe *tf;
+ struct sigacts *psp;
+ struct thread *td;
+ struct proc *p;
+ int onstack;
+ int code;
+ int sig;
+
+ td = curthread;
+ p = td->td_proc;
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+
+ sig = ksi->ksi_signo;
+ code = ksi->ksi_code;
+ psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
+
+ tf = td->td_frame;
+ onstack = sigonstack(tf->tf_sp);
+
+ CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
+ catcher, sig);
+
+ /* Allocate and validate space for the signal handler context. */
+ if ((td->td_pflags & TDP_ALTSTACK) != 0 && !onstack &&
+ SIGISMEMBER(psp->ps_sigonstack, sig)) {
+ fp = (struct sigframe *)((uintptr_t)td->td_sigstk.ss_sp +
+ td->td_sigstk.ss_size);
+ } else {
+ fp = (struct sigframe *)td->td_frame->tf_sp;
+ }
+
+ /* Make room, keeping the stack aligned */
+ fp--;
+ fp = (struct sigframe *)STACKALIGN(fp);
+
+ /* Fill in the frame to copy out */
+ get_mcontext(td, &frame.sf_uc.uc_mcontext, 0);
+ get_fpcontext(td, &frame.sf_uc.uc_mcontext);
+ frame.sf_si = ksi->ksi_info;
+ frame.sf_uc.uc_sigmask = *mask;
+ frame.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ?
+ ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE;
+ frame.sf_uc.uc_stack = td->td_sigstk;
+ mtx_unlock(&psp->ps_mtx);
+ PROC_UNLOCK(td->td_proc);
+
+ /* Copy the sigframe out to the user's stack. */
+ if (copyout(&frame, fp, sizeof(*fp)) != 0) {
+ /* Process has trashed its stack. Kill it. */
+ CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%p", td, fp);
+ PROC_LOCK(p);
+ sigexit(td, SIGILL);
+ }
+
+ tf->tf_a[0] = sig;
+ tf->tf_a[1] = (register_t)&fp->sf_si;
+ tf->tf_a[2] = (register_t)&fp->sf_uc;
+
+ tf->tf_sepc = (register_t)catcher;
+ tf->tf_sp = (register_t)fp;
+
+ sysent = p->p_sysent;
+ if (sysent->sv_sigcode_base != 0)
+ tf->tf_ra = (register_t)sysent->sv_sigcode_base;
+ else
+ tf->tf_ra = (register_t)(sysent->sv_psstrings -
+ *(sysent->sv_szsigcode));
+
+ CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_elr,
+ tf->tf_sp);
+
+ PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
+}
+
+static void
+init_proc0(vm_offset_t kstack)
+{
+
+ pcpup = &__pcpu[0];
+
+ proc_linkup0(&proc0, &thread0);
+ thread0.td_kstack = kstack;
+ thread0.td_pcb = (struct pcb *)(thread0.td_kstack) - 1;
+ thread0.td_frame = &proc0_tf;
+ pcpup->pc_curpcb = thread0.td_pcb;
+}
+
+static int
+add_physmap_entry(uint64_t base, uint64_t length, vm_paddr_t *physmap,
+ u_int *physmap_idxp)
+{
+ u_int i, insert_idx, _physmap_idx;
+
+ _physmap_idx = *physmap_idxp;
+
+ if (length == 0)
+ return (1);
+
+ /*
+ * Find insertion point while checking for overlap. Start off by
+ * assuming the new entry will be added to the end.
+ */
+ insert_idx = _physmap_idx;
+ for (i = 0; i <= _physmap_idx; i += 2) {
+ if (base < physmap[i + 1]) {
+ if (base + length <= physmap[i]) {
+ insert_idx = i;
+ break;
+ }
+ if (boothowto & RB_VERBOSE)
+ printf(
+ "Overlapping memory regions, ignoring second region\n");
+ return (1);
+ }
+ }
+
+ /* See if we can prepend to the next entry. */
+ if (insert_idx <= _physmap_idx &&
+ base + length == physmap[insert_idx]) {
+ physmap[insert_idx] = base;
+ return (1);
+ }
+
+ /* See if we can append to the previous entry. */
+ if (insert_idx > 0 && base == physmap[insert_idx - 1]) {
+ physmap[insert_idx - 1] += length;
+ return (1);
+ }
+
+ _physmap_idx += 2;
+ *physmap_idxp = _physmap_idx;
+ if (_physmap_idx == PHYSMAP_SIZE) {
+ printf(
+ "Too many segments in the physical address map, giving up\n");
+ return (0);
+ }
+
+ /*
+ * Move the last 'N' entries down to make room for the new
+ * entry if needed.
+ */
+ for (i = _physmap_idx; i > insert_idx; i -= 2) {
+ physmap[i] = physmap[i - 2];
+ physmap[i + 1] = physmap[i - 1];
+ }
+
+ /* Insert the new entry. */
+ physmap[insert_idx] = base;
+ physmap[insert_idx + 1] = base + length;
+
+ printf("physmap[%d] = 0x%016lx\n", insert_idx, base);
+ printf("physmap[%d] = 0x%016lx\n", insert_idx + 1, base + length);
+ return (1);
+}
+
+#ifdef FDT
+static void
+try_load_dtb(caddr_t kmdp)
+{
+ vm_offset_t dtbp;
+
+ dtbp = (vm_offset_t)&fdt_static_dtb;
+ if (dtbp == (vm_offset_t)NULL) {
+ printf("ERROR loading DTB\n");
+ return;
+ }
+
+ if (OF_install(OFW_FDT, 0) == FALSE)
+ panic("Cannot install FDT");
+
+ if (OF_init((void *)dtbp) != 0)
+ panic("OF_init failed with the found device tree");
+}
+#endif
+
+static void
+cache_setup(void)
+{
+
+ /* TODO */
+}
+
+/*
+ * Fake up a boot descriptor table.
+ * RISCVTODO: This needs to be done via loader (when it's available).
+ */
+vm_offset_t
+fake_preload_metadata(struct riscv_bootparams *rvbp __unused)
+{
+#ifdef DDB
+ vm_offset_t zstart = 0, zend = 0;
+#endif
+ vm_offset_t lastaddr;
+ int i = 0;
+ static uint32_t fake_preload[35];
+
+ fake_preload[i++] = MODINFO_NAME;
+ fake_preload[i++] = strlen("kernel") + 1;
+ strcpy((char*)&fake_preload[i++], "kernel");
+ i += 1;
+ fake_preload[i++] = MODINFO_TYPE;
+ fake_preload[i++] = strlen("elf64 kernel") + 1;
+ strcpy((char*)&fake_preload[i++], "elf64 kernel");
+ i += 3;
+ fake_preload[i++] = MODINFO_ADDR;
+ fake_preload[i++] = sizeof(vm_offset_t);
+ fake_preload[i++] = (uint64_t)(KERNBASE + KERNENTRY);
+ i += 1;
+ fake_preload[i++] = MODINFO_SIZE;
+ fake_preload[i++] = sizeof(uint64_t);
+ printf("end is 0x%016lx\n", (uint64_t)&end);
+ fake_preload[i++] = (uint64_t)&end - (uint64_t)(KERNBASE + KERNENTRY);
+ i += 1;
+#ifdef DDB
+#if 0
+ /* RISCVTODO */
+ if (*(uint32_t *)KERNVIRTADDR == MAGIC_TRAMP_NUMBER) {
+ fake_preload[i++] = MODINFO_METADATA|MODINFOMD_SSYM;
+ fake_preload[i++] = sizeof(vm_offset_t);
+ fake_preload[i++] = *(uint32_t *)(KERNVIRTADDR + 4);
+ fake_preload[i++] = MODINFO_METADATA|MODINFOMD_ESYM;
+ fake_preload[i++] = sizeof(vm_offset_t);
+ fake_preload[i++] = *(uint32_t *)(KERNVIRTADDR + 8);
+ lastaddr = *(uint32_t *)(KERNVIRTADDR + 8);
+ zend = lastaddr;
+ zstart = *(uint32_t *)(KERNVIRTADDR + 4);
+ db_fetch_ksymtab(zstart, zend);
+ } else
+#endif
+#endif
+ lastaddr = (vm_offset_t)&end;
+ fake_preload[i++] = 0;
+ fake_preload[i] = 0;
+ preload_metadata = (void *)fake_preload;
+
+ return (lastaddr);
+}
+
+void
+initriscv(struct riscv_bootparams *rvbp)
+{
+ vm_offset_t lastaddr;
+ vm_size_t kernlen;
+ caddr_t kmdp;
+
+ /* Set the module data location */
+ lastaddr = fake_preload_metadata(rvbp);
+
+ /* Find the kernel address */
+ kmdp = preload_search_by_type("elf kernel");
+ if (kmdp == NULL)
+ kmdp = preload_search_by_type("elf64 kernel");
+
+ boothowto = 0;
+
+ kern_envp = NULL;
+
+#ifdef FDT
+ try_load_dtb(kmdp);
+#endif
+
+ /* Load the physical memory ranges */
+ physmap_idx = 0;
+
+ /*
+ * RISCVTODO: figure out whether platform provides ranges,
+ * or grab from FDT.
+ */
+ add_physmap_entry(0, 0x8000000, physmap, &physmap_idx);
+
+ /* Set the pcpu data, this is needed by pmap_bootstrap */
+ pcpup = &__pcpu[0];
+ pcpu_init(pcpup, 0, sizeof(struct pcpu));
+
+ /* Set the pcpu pointer */
+ __asm __volatile("mv gp, %0" :: "r"(pcpup));
+
+ PCPU_SET(curthread, &thread0);
+
+ /* Do basic tuning, hz etc */
+ init_param1();
+
+ cache_setup();
+
+ /* Bootstrap enough of pmap to enter the kernel proper */
+ kernlen = (lastaddr - KERNBASE);
+ pmap_bootstrap(rvbp->kern_l1pt, KERNENTRY, kernlen);
+
+ cninit();
+
+ init_proc0(rvbp->kern_stack);
+
+ /* set page table base register for thread0 */
+ thread0.td_pcb->pcb_l1addr = (rvbp->kern_l1pt - KERNBASE);
+
+ msgbufinit(msgbufp, msgbufsize);
+ mutex_init();
+ init_param2(physmem);
+ kdb_init();
+
+ riscv_init_interrupts();
+
+ early_boot = 0;
+}
diff --git a/sys/riscv/riscv/mem.c b/sys/riscv/riscv/mem.c
new file mode 100644
index 000000000000..38488a2c9a87
--- /dev/null
+++ b/sys/riscv/riscv/mem.c
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 2014 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/memrange.h>
+#include <sys/uio.h>
+
+#include <machine/memdev.h>
+#include <machine/vmparam.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_page.h>
+
+struct mem_range_softc mem_range_softc;
+
+int
+memrw(struct cdev *dev, struct uio *uio, int flags)
+{
+ ssize_t orig_resid;
+ vm_offset_t off, v;
+ struct iovec *iov;
+ struct vm_page m;
+ vm_page_t marr;
+ u_int cnt;
+ int error;
+
+ error = 0;
+ orig_resid = uio->uio_resid;
+ while (uio->uio_resid > 0 && error == 0) {
+ iov = uio->uio_iov;
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ if (uio->uio_iovcnt < 0)
+ panic("memrw");
+ continue;
+ }
+
+ v = uio->uio_offset;
+ off = v & PAGE_MASK;
+ cnt = ulmin(iov->iov_len, PAGE_SIZE - (u_int)off);
+ if (cnt == 0)
+ continue;
+
+ switch(dev2unit(dev)) {
+ case CDEV_MINOR_KMEM:
+ /* If the address is in the DMAP just copy it */
+ if (VIRT_IN_DMAP(v)) {
+ error = uiomove((void *)v, cnt, uio);
+ break;
+ }
+
+ if (!kernacc((void *)v, cnt, uio->uio_rw == UIO_READ ?
+ VM_PROT_READ : VM_PROT_WRITE)) {
+ error = EFAULT;
+ break;
+ }
+
+ /* Get the physical address to read */
+ v = pmap_extract(kernel_pmap, v);
+ if (v == 0) {
+ error = EFAULT;
+ break;
+ }
+
+ /* FALLTHROUGH */
+ case CDEV_MINOR_MEM:
+ /* If within the DMAP use this to copy from */
+ if (PHYS_IN_DMAP(v)) {
+ v = PHYS_TO_DMAP(v);
+ error = uiomove((void *)v, cnt, uio);
+ break;
+ }
+
+ /* Have uiomove_fromphys handle the data */
+ m.phys_addr = trunc_page(v);
+ marr = &m;
+ uiomove_fromphys(&marr, off, cnt, uio);
+ break;
+ }
+ }
+
+ /*
+ * Don't return error if any byte was written. Read and write
+ * can return error only if no i/o was performed.
+ */
+ if (uio->uio_resid != orig_resid)
+ error = 0;
+
+ return (error);
+}
+
diff --git a/sys/arm/xscale/i80321/uart_cpu_i80321.c b/sys/riscv/riscv/minidump_machdep.c
index a3faec7289df..ca51cfc77e50 100644
--- a/sys/arm/xscale/i80321/uart_cpu_i80321.c
+++ b/sys/riscv/riscv/minidump_machdep.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003 Marcel Moolenaar
+ * Copyright (c) 2006 Peter Wemm
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,41 +27,33 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_watchdog.h"
+
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/bus.h>
+#include <sys/conf.h>
#include <sys/cons.h>
-#include <machine/bus.h>
-
-#include <dev/uart/uart.h>
-#include <dev/uart/uart_cpu.h>
-
-#include <arm/xscale/i80321/i80321var.h>
-#include <arm/xscale/i80321/obiovar.h>
+#include <sys/kernel.h>
+#include <sys/kerneldump.h>
+#include <sys/msgbuf.h>
+#include <sys/watchdog.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_page.h>
+#include <vm/vm_phys.h>
+#include <vm/pmap.h>
+#include <machine/atomic.h>
+#include <machine/elf.h>
+#include <machine/md_var.h>
+#include <machine/vmparam.h>
+#include <machine/minidump.h>
-bus_space_tag_t uart_bus_space_io;
-bus_space_tag_t uart_bus_space_mem;
+CTASSERT(sizeof(struct kerneldumpheader) == 512);
+CTASSERT(sizeof(*vm_page_dump) == 8);
int
-uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
+minidumpsys(struct dumperinfo *di)
{
- return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
-}
-int
-uart_cpu_getdev(int devtype, struct uart_devinfo *di)
-{
- di->ops = uart_getops(&uart_ns8250_class);
- di->bas.chan = 0;
- di->bas.bst = obio_bs_tag;
- di->bas.regshft = 0;
- di->bas.rclk = 0;
- di->baudrate = 115200;
- di->databits = 8;
- di->stopbits = 1;
- di->parity = UART_PARITY_NONE;
- uart_bus_space_io = obio_bs_tag;
- uart_bus_space_mem = NULL;
- di->bas.bsh = 0xfe800000;
- return (0);
+ panic("minidumpsys");
}
diff --git a/sys/riscv/riscv/nexus.c b/sys/riscv/riscv/nexus.c
new file mode 100644
index 000000000000..83b57959edab
--- /dev/null
+++ b/sys/riscv/riscv/nexus.c
@@ -0,0 +1,387 @@
+/*-
+ * Copyright 1998 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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.
+ *
+ */
+
+/*
+ * This code implements a `root nexus' for RISC-V Architecture
+ * machines. The function of the root nexus is to serve as an
+ * attachment point for both processors and buses, and to manage
+ * resources which are common to all of them. In particular,
+ * this code implements the core resource managers for interrupt
+ * requests, DMA requests (which rightfully should be a part of the
+ * ISA code but it's easier to do it here for now), I/O port addresses,
+ * and I/O memory address space.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <sys/interrupt.h>
+
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include "opt_platform.h"
+
+#include <dev/fdt/fdt_common.h>
+#include "ofw_bus_if.h"
+
+extern struct bus_space memmap_bus;
+
+static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
+
+struct nexus_device {
+ struct resource_list nx_resources;
+};
+
+#define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev))
+
+static struct rman mem_rman;
+static struct rman irq_rman;
+
+static device_probe_t nexus_fdt_probe;
+static int nexus_attach(device_t);
+
+static int nexus_print_child(device_t, device_t);
+static device_t nexus_add_child(device_t, u_int, const char *, int);
+static struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
+ u_long, u_long, u_long, u_int);
+static int nexus_activate_resource(device_t, device_t, int, int,
+ struct resource *);
+static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
+ enum intr_polarity pol);
+static struct resource_list *nexus_get_reslist(device_t, device_t);
+static int nexus_set_resource(device_t, device_t, int, int, u_long, u_long);
+static int nexus_deactivate_resource(device_t, device_t, int, int,
+ struct resource *);
+
+static int nexus_setup_intr(device_t dev, device_t child, struct resource *res,
+ int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep);
+static int nexus_teardown_intr(device_t, device_t, struct resource *, void *);
+
+static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent,
+ int icells, pcell_t *intr);
+
+static device_method_t nexus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, nexus_fdt_probe),
+ DEVMETHOD(device_attach, nexus_attach),
+
+ /* OFW interface */
+ DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, nexus_print_child),
+ DEVMETHOD(bus_add_child, nexus_add_child),
+ DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
+ DEVMETHOD(bus_activate_resource, nexus_activate_resource),
+ DEVMETHOD(bus_config_intr, nexus_config_intr),
+ DEVMETHOD(bus_get_resource_list, nexus_get_reslist),
+ DEVMETHOD(bus_set_resource, nexus_set_resource),
+ DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, nexus_setup_intr),
+ DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
+
+ { 0, 0 }
+};
+
+static driver_t nexus_fdt_driver = {
+ "nexus",
+ nexus_methods,
+ 1 /* no softc */
+};
+
+static int
+nexus_fdt_probe(device_t dev)
+{
+
+ device_quiet(dev);
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+nexus_attach(device_t dev)
+{
+
+ mem_rman.rm_start = 0;
+ mem_rman.rm_end = ~0ul;
+ mem_rman.rm_type = RMAN_ARRAY;
+ mem_rman.rm_descr = "I/O memory addresses";
+ if (rman_init(&mem_rman) || rman_manage_region(&mem_rman, 0, ~0))
+ panic("nexus_attach mem_rman");
+ irq_rman.rm_start = 0;
+ irq_rman.rm_end = ~0ul;
+ irq_rman.rm_type = RMAN_ARRAY;
+ irq_rman.rm_descr = "Interrupts";
+ if (rman_init(&irq_rman) || rman_manage_region(&irq_rman, 0, ~0))
+ panic("nexus_attach irq_rman");
+
+ nexus_add_child(dev, 10, "ofwbus", 0);
+
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+
+ return (0);
+}
+
+static int
+nexus_print_child(device_t bus, device_t child)
+{
+ int retval = 0;
+
+ retval += bus_print_child_header(bus, child);
+ retval += printf("\n");
+
+ return (retval);
+}
+
+static device_t
+nexus_add_child(device_t bus, u_int order, const char *name, int unit)
+{
+ device_t child;
+ struct nexus_device *ndev;
+
+ ndev = malloc(sizeof(struct nexus_device), M_NEXUSDEV, M_NOWAIT|M_ZERO);
+ if (!ndev)
+ return (0);
+ resource_list_init(&ndev->nx_resources);
+
+ child = device_add_child_ordered(bus, order, name, unit);
+
+ /* should we free this in nexus_child_detached? */
+ device_set_ivars(child, ndev);
+
+ return (child);
+}
+
+
+/*
+ * Allocate a resource on behalf of child. NB: child is usually going to be a
+ * child of one of our descendants, not a direct child of nexus0.
+ * (Exceptions include footbridge.)
+ */
+static struct resource *
+nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct nexus_device *ndev = DEVTONX(child);
+ struct resource *rv;
+ struct resource_list_entry *rle;
+ struct rman *rm;
+ int needactivate = flags & RF_ACTIVE;
+
+ /*
+ * If this is an allocation of the "default" range for a given
+ * RID, and we know what the resources for this device are
+ * (ie. they aren't maintained by a child bus), then work out
+ * the start/end values.
+ */
+ if ((start == 0UL) && (end == ~0UL) && (count == 1)) {
+ if (device_get_parent(child) != bus || ndev == NULL)
+ return(NULL);
+ rle = resource_list_find(&ndev->nx_resources, type, *rid);
+ if (rle == NULL)
+ return(NULL);
+ start = rle->start;
+ end = rle->end;
+ count = rle->count;
+ }
+
+ switch (type) {
+ case SYS_RES_IRQ:
+ rm = &irq_rman;
+ break;
+
+ case SYS_RES_MEMORY:
+ case SYS_RES_IOPORT:
+ rm = &mem_rman;
+ break;
+
+ default:
+ return (NULL);
+ }
+
+ rv = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (rv == 0)
+ return (NULL);
+
+ rman_set_rid(rv, *rid);
+ rman_set_bushandle(rv, rman_get_start(rv));
+
+ if (needactivate) {
+ if (bus_activate_resource(child, type, *rid, rv)) {
+ rman_release_resource(rv);
+ return (NULL);
+ }
+ }
+
+ return (rv);
+}
+
+static int
+nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
+ enum intr_polarity pol)
+{
+
+ return (riscv_config_intr(irq, trig, pol));
+}
+
+static int
+nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
+ driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
+{
+ int error;
+
+ if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
+ flags |= INTR_EXCL;
+
+ /* We depend here on rman_activate_resource() being idempotent. */
+ error = rman_activate_resource(res);
+ if (error)
+ return (error);
+
+ error = riscv_setup_intr(device_get_nameunit(child), filt, intr,
+ arg, rman_get_start(res), flags, cookiep);
+
+ return (error);
+}
+
+static int
+nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
+{
+
+ return (riscv_teardown_intr(ih));
+}
+
+static int
+nexus_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ int err;
+ bus_addr_t paddr;
+ bus_size_t psize;
+ bus_space_handle_t vaddr;
+
+ if ((err = rman_activate_resource(r)) != 0)
+ return (err);
+
+ /*
+ * If this is a memory resource, map it into the kernel.
+ */
+ if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
+ paddr = (bus_addr_t)rman_get_start(r);
+ psize = (bus_size_t)rman_get_size(r);
+ err = bus_space_map(&memmap_bus, paddr, psize, 0, &vaddr);
+ if (err != 0) {
+ rman_deactivate_resource(r);
+ return (err);
+ }
+ rman_set_bustag(r, &memmap_bus);
+ rman_set_virtual(r, (void *)vaddr);
+ rman_set_bushandle(r, vaddr);
+ }
+ return (0);
+}
+
+static struct resource_list *
+nexus_get_reslist(device_t dev, device_t child)
+{
+ struct nexus_device *ndev = DEVTONX(child);
+
+ return (&ndev->nx_resources);
+}
+
+static int
+nexus_set_resource(device_t dev, device_t child, int type, int rid,
+ u_long start, u_long count)
+{
+ struct nexus_device *ndev = DEVTONX(child);
+ struct resource_list *rl = &ndev->nx_resources;
+
+ /* XXX this should return a success/failure indicator */
+ resource_list_add(rl, type, rid, start, start + count - 1, count);
+
+ return(0);
+}
+
+
+static int
+nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ bus_size_t psize;
+ bus_space_handle_t vaddr;
+
+ psize = (bus_size_t)rman_get_size(r);
+ vaddr = rman_get_bushandle(r);
+
+ if (vaddr != 0) {
+ bus_space_unmap(&memmap_bus, vaddr, psize);
+ rman_set_virtual(r, NULL);
+ rman_set_bushandle(r, 0);
+ }
+
+ return (rman_deactivate_resource(r));
+}
+
+static devclass_t nexus_fdt_devclass;
+
+EARLY_DRIVER_MODULE(nexus_fdt, root, nexus_fdt_driver, nexus_fdt_devclass,
+ 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST);
+
+static int
+nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
+ pcell_t *intr)
+{
+ int irq;
+
+ if (icells == 3) {
+ irq = intr[1];
+ if (intr[0] == 0)
+ irq += 32; /* SPI */
+ else
+ irq += 16; /* PPI */
+ } else
+ irq = intr[0];
+
+ return (irq);
+}
diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c
new file mode 100644
index 000000000000..e4ca19fff330
--- /dev/null
+++ b/sys/riscv/riscv/pmap.c
@@ -0,0 +1,3197 @@
+/*-
+ * Copyright (c) 1991 Regents of the University of California.
+ * All rights reserved.
+ * Copyright (c) 1994 John S. Dyson
+ * All rights reserved.
+ * Copyright (c) 1994 David Greenman
+ * All rights reserved.
+ * Copyright (c) 2003 Peter Wemm
+ * All rights reserved.
+ * Copyright (c) 2005-2010 Alan L. Cox <alc@cs.rice.edu>
+ * All rights reserved.
+ * Copyright (c) 2014 Andrew Turner
+ * All rights reserved.
+ * Copyright (c) 2014 The FreeBSD Foundation
+ * All rights reserved.
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and William Jolitz of UUNET Technologies Inc.
+ *
+ * Portions of this software were developed by Andrew Turner under
+ * sponsorship from The FreeBSD Foundation.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91
+ */
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Jake Burkholder,
+ * Safeport Network Services, and Network Associates Laboratories, the
+ * Security Research Division of Network Associates, Inc. under
+ * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
+ * CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Manages physical address maps.
+ *
+ * Since the information managed by this module is
+ * also stored by the logical address mapping module,
+ * this module may throw away valid virtual-to-physical
+ * mappings at almost any time. However, invalidations
+ * of virtual-to-physical mappings must be done as
+ * requested.
+ *
+ * In order to cope with hardware architectures which
+ * make virtual-to-physical map invalidates expensive,
+ * this module may delay invalidate or reduced protection
+ * operations until such time as they are actually
+ * necessary. This module is given full information as
+ * to which processors are currently using which maps,
+ * and to when physical maps must be made correct.
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mman.h>
+#include <sys/msgbuf.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/rwlock.h>
+#include <sys/sx.h>
+#include <sys/vmem.h>
+#include <sys/vmmeter.h>
+#include <sys/sched.h>
+#include <sys/sysctl.h>
+#include <sys/_unrhdr.h>
+#include <sys/smp.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_pageout.h>
+#include <vm/vm_pager.h>
+#include <vm/vm_radix.h>
+#include <vm/vm_reserv.h>
+#include <vm/uma.h>
+
+#include <machine/machdep.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+
+#define NPDEPG (PAGE_SIZE/(sizeof (pd_entry_t)))
+#define NUPDE (NPDEPG * NPDEPG)
+#define NUSERPGTBLS (NUPDE + NPDEPG)
+
+#if !defined(DIAGNOSTIC)
+#ifdef __GNUC_GNU_INLINE__
+#define PMAP_INLINE __attribute__((__gnu_inline__)) inline
+#else
+#define PMAP_INLINE extern inline
+#endif
+#else
+#define PMAP_INLINE
+#endif
+
+#ifdef PV_STATS
+#define PV_STAT(x) do { x ; } while (0)
+#else
+#define PV_STAT(x) do { } while (0)
+#endif
+
+#define pmap_l2_pindex(v) ((v) >> L2_SHIFT)
+
+#define NPV_LIST_LOCKS MAXCPU
+
+#define PHYS_TO_PV_LIST_LOCK(pa) \
+ (&pv_list_locks[pa_index(pa) % NPV_LIST_LOCKS])
+
+#define CHANGE_PV_LIST_LOCK_TO_PHYS(lockp, pa) do { \
+ struct rwlock **_lockp = (lockp); \
+ struct rwlock *_new_lock; \
+ \
+ _new_lock = PHYS_TO_PV_LIST_LOCK(pa); \
+ if (_new_lock != *_lockp) { \
+ if (*_lockp != NULL) \
+ rw_wunlock(*_lockp); \
+ *_lockp = _new_lock; \
+ rw_wlock(*_lockp); \
+ } \
+} while (0)
+
+#define CHANGE_PV_LIST_LOCK_TO_VM_PAGE(lockp, m) \
+ CHANGE_PV_LIST_LOCK_TO_PHYS(lockp, VM_PAGE_TO_PHYS(m))
+
+#define RELEASE_PV_LIST_LOCK(lockp) do { \
+ struct rwlock **_lockp = (lockp); \
+ \
+ if (*_lockp != NULL) { \
+ rw_wunlock(*_lockp); \
+ *_lockp = NULL; \
+ } \
+} while (0)
+
+#define VM_PAGE_TO_PV_LIST_LOCK(m) \
+ PHYS_TO_PV_LIST_LOCK(VM_PAGE_TO_PHYS(m))
+
+struct pmap kernel_pmap_store;
+
+vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */
+vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */
+vm_offset_t kernel_vm_end = 0;
+
+struct msgbuf *msgbufp = NULL;
+
+static struct rwlock_padalign pvh_global_lock;
+
+extern uint64_t pagetable_l0;
+
+/*
+ * Data for the pv entry allocation mechanism
+ */
+static TAILQ_HEAD(pch, pv_chunk) pv_chunks = TAILQ_HEAD_INITIALIZER(pv_chunks);
+static struct mtx pv_chunks_mutex;
+static struct rwlock pv_list_locks[NPV_LIST_LOCKS];
+
+static void free_pv_chunk(struct pv_chunk *pc);
+static void free_pv_entry(pmap_t pmap, pv_entry_t pv);
+static pv_entry_t get_pv_entry(pmap_t pmap, struct rwlock **lockp);
+static vm_page_t reclaim_pv_chunk(pmap_t locked_pmap, struct rwlock **lockp);
+static void pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va);
+static pv_entry_t pmap_pvh_remove(struct md_page *pvh, pmap_t pmap,
+ vm_offset_t va);
+static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va,
+ vm_page_t m, vm_prot_t prot, vm_page_t mpte, struct rwlock **lockp);
+static int pmap_remove_l3(pmap_t pmap, pt_entry_t *l3, vm_offset_t sva,
+ pd_entry_t ptepde, struct spglist *free, struct rwlock **lockp);
+static boolean_t pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va,
+ vm_page_t m, struct rwlock **lockp);
+
+static vm_page_t _pmap_alloc_l3(pmap_t pmap, vm_pindex_t ptepindex,
+ struct rwlock **lockp);
+
+static void _pmap_unwire_l3(pmap_t pmap, vm_offset_t va, vm_page_t m,
+ struct spglist *free);
+static int pmap_unuse_l3(pmap_t, vm_offset_t, pd_entry_t, struct spglist *);
+
+/*
+ * These load the old table data and store the new value.
+ * They need to be atomic as the System MMU may write to the table at
+ * the same time as the CPU.
+ */
+#define pmap_load_store(table, entry) atomic_swap_64(table, entry)
+#define pmap_set(table, mask) atomic_set_64(table, mask)
+#define pmap_load_clear(table) atomic_swap_64(table, 0)
+#define pmap_load(table) (*table)
+
+/********************/
+/* Inline functions */
+/********************/
+
+static __inline void
+pagecopy(void *s, void *d)
+{
+
+ memcpy(d, s, PAGE_SIZE);
+}
+
+static __inline void
+pagezero(void *p)
+{
+
+ bzero(p, PAGE_SIZE);
+}
+
+#define pmap_l1_index(va) (((va) >> L1_SHIFT) & Ln_ADDR_MASK)
+#define pmap_l2_index(va) (((va) >> L2_SHIFT) & Ln_ADDR_MASK)
+#define pmap_l3_index(va) (((va) >> L3_SHIFT) & Ln_ADDR_MASK)
+
+#define PTE_TO_PHYS(pte) ((pte >> PTE_PPN0_S) * PAGE_SIZE)
+
+static __inline pd_entry_t *
+pmap_l1(pmap_t pmap, vm_offset_t va)
+{
+
+ return (&pmap->pm_l1[pmap_l1_index(va)]);
+}
+
+static __inline pd_entry_t *
+pmap_l1_to_l2(pd_entry_t *l1, vm_offset_t va)
+{
+ vm_paddr_t phys;
+ pd_entry_t *l2;
+
+ phys = PTE_TO_PHYS(pmap_load(l1));
+ l2 = (pd_entry_t *)PHYS_TO_DMAP(phys);
+
+ return (&l2[pmap_l2_index(va)]);
+}
+
+static __inline pd_entry_t *
+pmap_l2(pmap_t pmap, vm_offset_t va)
+{
+ pd_entry_t *l1;
+
+ l1 = pmap_l1(pmap, va);
+
+ if ((pmap_load(l1) & PTE_VALID) == 0)
+ return (NULL);
+ if ((pmap_load(l1) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S))
+ return (NULL);
+
+ return (pmap_l1_to_l2(l1, va));
+}
+
+static __inline pt_entry_t *
+pmap_l2_to_l3(pd_entry_t *l2, vm_offset_t va)
+{
+ vm_paddr_t phys;
+ pt_entry_t *l3;
+
+ phys = PTE_TO_PHYS(pmap_load(l2));
+ l3 = (pd_entry_t *)PHYS_TO_DMAP(phys);
+
+ return (&l3[pmap_l3_index(va)]);
+}
+
+static __inline pt_entry_t *
+pmap_l3(pmap_t pmap, vm_offset_t va)
+{
+ pd_entry_t *l2;
+
+ l2 = pmap_l2(pmap, va);
+ if (l2 == NULL)
+ return (NULL);
+ if ((pmap_load(l2) & PTE_VALID) == 0)
+ return (NULL);
+ if (l2 == NULL || (pmap_load(l2) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S))
+ return (NULL);
+
+ return (pmap_l2_to_l3(l2, va));
+}
+
+
+static __inline int
+pmap_is_write(pt_entry_t entry)
+{
+
+ if (entry & (1 << PTE_TYPE_S))
+ return (1);
+
+ return (0);
+}
+
+static __inline int
+pmap_is_current(pmap_t pmap)
+{
+
+ return ((pmap == pmap_kernel()) ||
+ (pmap == curthread->td_proc->p_vmspace->vm_map.pmap));
+}
+
+static __inline int
+pmap_l3_valid(pt_entry_t l3)
+{
+
+ return (l3 & PTE_VALID);
+}
+
+static __inline int
+pmap_l3_valid_cacheable(pt_entry_t l3)
+{
+
+ /* TODO */
+
+ return (0);
+}
+
+#define PTE_SYNC(pte) cpu_dcache_wb_range((vm_offset_t)pte, sizeof(*pte))
+
+/* Checks if the page is dirty. */
+static inline int
+pmap_page_dirty(pt_entry_t pte)
+{
+
+ return (pte & PTE_DIRTY);
+}
+
+static __inline void
+pmap_resident_count_inc(pmap_t pmap, int count)
+{
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ pmap->pm_stats.resident_count += count;
+}
+
+static __inline void
+pmap_resident_count_dec(pmap_t pmap, int count)
+{
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ KASSERT(pmap->pm_stats.resident_count >= count,
+ ("pmap %p resident count underflow %ld %d", pmap,
+ pmap->pm_stats.resident_count, count));
+ pmap->pm_stats.resident_count -= count;
+}
+
+static pt_entry_t *
+pmap_early_page_idx(vm_offset_t l1pt, vm_offset_t va, u_int *l1_slot,
+ u_int *l2_slot)
+{
+ pt_entry_t *l2;
+ pd_entry_t *l1;
+
+ l1 = (pd_entry_t *)l1pt;
+ *l1_slot = (va >> L1_SHIFT) & Ln_ADDR_MASK;
+
+ /* Check locore has used a table L1 map */
+ KASSERT((l1[*l1_slot] & PTE_TYPE_M) == (PTE_TYPE_PTR << PTE_TYPE_S),
+ ("Invalid bootstrap L1 table"));
+
+ /* Find the address of the L2 table */
+ l2 = (pt_entry_t *)init_pt_va;
+ *l2_slot = pmap_l2_index(va);
+
+ return (l2);
+}
+
+static vm_paddr_t
+pmap_early_vtophys(vm_offset_t l1pt, vm_offset_t va)
+{
+ u_int l1_slot, l2_slot;
+ pt_entry_t *l2;
+ u_int ret;
+
+ l2 = pmap_early_page_idx(l1pt, va, &l1_slot, &l2_slot);
+
+ /* L2 is superpages */
+ ret = (l2[l2_slot] >> PTE_PPN1_S) << L2_SHIFT;
+ ret += (va & L2_OFFSET);
+
+ return (ret);
+}
+
+static void
+pmap_bootstrap_dmap(vm_offset_t l2pt)
+{
+ vm_offset_t va;
+ vm_paddr_t pa;
+ pd_entry_t *l2;
+ u_int l2_slot;
+ pt_entry_t entry;
+ u_int pn;
+
+ va = DMAP_MIN_ADDRESS;
+ l2 = (pd_entry_t *)l2pt;
+ l2_slot = pmap_l2_index(DMAP_MIN_ADDRESS);
+
+ for (pa = 0; va < DMAP_MAX_ADDRESS; pa += L2_SIZE, va += L2_SIZE, l2_slot++) {
+ KASSERT(l2_slot < Ln_ENTRIES, ("Invalid L2 index"));
+
+ /* superpages */
+ pn = ((pa >> L2_SHIFT) & Ln_ADDR_MASK);
+ entry = (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S));
+ entry |= (pn << PTE_PPN1_S);
+
+ pmap_load_store(&l2[l2_slot], entry);
+ }
+
+ cpu_dcache_wb_range((vm_offset_t)l2, PAGE_SIZE);
+ cpu_tlb_flushID();
+}
+
+/*
+ * Bootstrap the system enough to run with virtual memory.
+ */
+void
+pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen)
+{
+ u_int l1_slot, l2_slot, avail_slot, map_slot, used_map_slot;
+ uint64_t kern_delta;
+ pt_entry_t *l2;
+ vm_offset_t va, freemempos;
+ vm_offset_t dpcpu, msgbufpv;
+ vm_paddr_t pa, min_pa;
+ vm_offset_t l2pt;
+ int i;
+
+ kern_delta = KERNBASE - kernstart;
+ physmem = 0;
+
+ printf("pmap_bootstrap %lx %lx %lx\n", l1pt, kernstart, kernlen);
+ printf("%lx\n", l1pt);
+ printf("%lx\n", (KERNBASE >> L1_SHIFT) & Ln_ADDR_MASK);
+
+ /* Set this early so we can use the pagetable walking functions */
+ kernel_pmap_store.pm_l1 = (pd_entry_t *)l1pt;
+ PMAP_LOCK_INIT(kernel_pmap);
+
+ /*
+ * Initialize the global pv list lock.
+ */
+ rw_init(&pvh_global_lock, "pmap pv global");
+
+ /* Assume the address we were loaded to is a valid physical address */
+ min_pa = KERNBASE - kern_delta;
+
+ /*
+ * Find the minimum physical address. physmap is sorted,
+ * but may contain empty ranges.
+ */
+ for (i = 0; i < (physmap_idx * 2); i += 2) {
+ if (physmap[i] == physmap[i + 1])
+ continue;
+ if (physmap[i] <= min_pa)
+ min_pa = physmap[i];
+ break;
+ }
+
+ /* Create a direct map region early so we can use it for pa -> va */
+ l2pt = (l1pt + PAGE_SIZE);
+ pmap_bootstrap_dmap(l2pt);
+
+ va = KERNBASE;
+ pa = KERNBASE - kern_delta;
+
+ /*
+ * Start to initialize phys_avail by copying from physmap
+ * up to the physical address KERNBASE points at.
+ */
+ map_slot = avail_slot = 0;
+ for (; map_slot < (physmap_idx * 2); map_slot += 2) {
+ if (physmap[map_slot] == physmap[map_slot + 1])
+ continue;
+
+ phys_avail[avail_slot] = physmap[map_slot];
+ phys_avail[avail_slot + 1] = physmap[map_slot + 1];
+ physmem += (phys_avail[avail_slot + 1] -
+ phys_avail[avail_slot]) >> PAGE_SHIFT;
+ avail_slot += 2;
+ }
+
+ /* Add the memory before the kernel */
+ if (physmap[avail_slot] < pa) {
+ phys_avail[avail_slot] = physmap[map_slot];
+ phys_avail[avail_slot + 1] = pa;
+ physmem += (phys_avail[avail_slot + 1] -
+ phys_avail[avail_slot]) >> PAGE_SHIFT;
+ avail_slot += 2;
+ }
+ used_map_slot = map_slot;
+
+ /*
+ * Read the page table to find out what is already mapped.
+ * This assumes we have mapped a block of memory from KERNBASE
+ * using a single L1 entry.
+ */
+ l2 = pmap_early_page_idx(l1pt, KERNBASE, &l1_slot, &l2_slot);
+
+ /* Sanity check the index, KERNBASE should be the first VA */
+ KASSERT(l2_slot == 0, ("The L2 index is non-zero"));
+
+ /* Find how many pages we have mapped */
+ for (; l2_slot < Ln_ENTRIES; l2_slot++) {
+ if ((l2[l2_slot] & PTE_VALID) == 0)
+ break;
+
+ /* Check locore used L2 superpages */
+ KASSERT((l2[l2_slot] & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S),
+ ("Invalid bootstrap L2 table"));
+
+ va += L2_SIZE;
+ pa += L2_SIZE;
+ }
+
+ va = roundup2(va, L2_SIZE);
+
+ freemempos = KERNBASE + kernlen;
+ freemempos = roundup2(freemempos, PAGE_SIZE);
+
+ cpu_tlb_flushID();
+
+#define alloc_pages(var, np) \
+ (var) = freemempos; \
+ freemempos += (np * PAGE_SIZE); \
+ memset((char *)(var), 0, ((np) * PAGE_SIZE));
+
+ /* Allocate dynamic per-cpu area. */
+ alloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE);
+ dpcpu_init((void *)dpcpu, 0);
+
+ /* Allocate memory for the msgbuf, e.g. for /sbin/dmesg */
+ alloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
+ msgbufp = (void *)msgbufpv;
+
+ virtual_avail = roundup2(freemempos, L2_SIZE);
+ virtual_end = VM_MAX_KERNEL_ADDRESS - L2_SIZE;
+ kernel_vm_end = virtual_avail;
+
+ pa = pmap_early_vtophys(l1pt, freemempos);
+
+ /* Finish initialising physmap */
+ map_slot = used_map_slot;
+ for (; avail_slot < (PHYS_AVAIL_SIZE - 2) &&
+ map_slot < (physmap_idx * 2); map_slot += 2) {
+ if (physmap[map_slot] == physmap[map_slot + 1])
+ continue;
+
+ /* Have we used the current range? */
+ if (physmap[map_slot + 1] <= pa)
+ continue;
+
+ /* Do we need to split the entry? */
+ if (physmap[map_slot] < pa) {
+ phys_avail[avail_slot] = pa;
+ phys_avail[avail_slot + 1] = physmap[map_slot + 1];
+ } else {
+ phys_avail[avail_slot] = physmap[map_slot];
+ phys_avail[avail_slot + 1] = physmap[map_slot + 1];
+ }
+ physmem += (phys_avail[avail_slot + 1] -
+ phys_avail[avail_slot]) >> PAGE_SHIFT;
+
+ avail_slot += 2;
+ }
+ phys_avail[avail_slot] = 0;
+ phys_avail[avail_slot + 1] = 0;
+
+ /*
+ * Maxmem isn't the "maximum memory", it's one larger than the
+ * highest page of the physical address space. It should be
+ * called something like "Maxphyspage".
+ */
+ Maxmem = atop(phys_avail[avail_slot - 1]);
+
+ cpu_tlb_flushID();
+}
+
+/*
+ * Initialize a vm_page's machine-dependent fields.
+ */
+void
+pmap_page_init(vm_page_t m)
+{
+
+ TAILQ_INIT(&m->md.pv_list);
+ m->md.pv_memattr = VM_MEMATTR_WRITE_BACK;
+}
+
+/*
+ * Initialize the pmap module.
+ * Called by vm_init, to initialize any structures that the pmap
+ * system needs to map virtual memory.
+ */
+void
+pmap_init(void)
+{
+ int i;
+
+ /*
+ * Initialize the pv chunk list mutex.
+ */
+ mtx_init(&pv_chunks_mutex, "pmap pv chunk list", NULL, MTX_DEF);
+
+ /*
+ * Initialize the pool of pv list locks.
+ */
+ for (i = 0; i < NPV_LIST_LOCKS; i++)
+ rw_init(&pv_list_locks[i], "pmap pv list");
+}
+
+/*
+ * Normal, non-SMP, invalidation functions.
+ * We inline these within pmap.c for speed.
+ */
+PMAP_INLINE void
+pmap_invalidate_page(pmap_t pmap, vm_offset_t va)
+{
+
+ /* TODO */
+
+ sched_pin();
+ __asm __volatile("sfence.vm");
+ sched_unpin();
+}
+
+PMAP_INLINE void
+pmap_invalidate_range(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
+{
+
+ /* TODO */
+
+ sched_pin();
+ __asm __volatile("sfence.vm");
+ sched_unpin();
+}
+
+PMAP_INLINE void
+pmap_invalidate_all(pmap_t pmap)
+{
+
+ /* TODO */
+
+ sched_pin();
+ __asm __volatile("sfence.vm");
+ sched_unpin();
+}
+
+/*
+ * Routine: pmap_extract
+ * Function:
+ * Extract the physical page address associated
+ * with the given map/virtual_address pair.
+ */
+vm_paddr_t
+pmap_extract(pmap_t pmap, vm_offset_t va)
+{
+ pd_entry_t *l2p, l2;
+ pt_entry_t *l3p, l3;
+ vm_paddr_t pa;
+
+ pa = 0;
+ PMAP_LOCK(pmap);
+ /*
+ * Start with the l2 tabel. We are unable to allocate
+ * pages in the l1 table.
+ */
+ l2p = pmap_l2(pmap, va);
+ if (l2p != NULL) {
+ l2 = pmap_load(l2p);
+ if ((l2 & PTE_TYPE_M) == (PTE_TYPE_PTR << PTE_TYPE_S)) {
+ l3p = pmap_l2_to_l3(l2p, va);
+ if (l3p != NULL) {
+ l3 = pmap_load(l3p);
+ pa = PTE_TO_PHYS(l3);
+ pa |= (va & L3_OFFSET);
+ }
+ } else {
+ /* L2 is superpages */
+ pa = (l2 >> PTE_PPN1_S) << L2_SHIFT;
+ pa |= (va & L2_OFFSET);
+ }
+ }
+ PMAP_UNLOCK(pmap);
+ return (pa);
+}
+
+/*
+ * Routine: pmap_extract_and_hold
+ * Function:
+ * Atomically extract and hold the physical page
+ * with the given pmap and virtual address pair
+ * if that mapping permits the given protection.
+ */
+vm_page_t
+pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
+{
+ pt_entry_t *l3p, l3;
+ vm_paddr_t phys;
+ vm_paddr_t pa;
+ vm_page_t m;
+
+ pa = 0;
+ m = NULL;
+ PMAP_LOCK(pmap);
+retry:
+ l3p = pmap_l3(pmap, va);
+ if (l3p != NULL && (l3 = pmap_load(l3p)) != 0) {
+ if ((pmap_is_write(l3)) || ((prot & VM_PROT_WRITE) == 0)) {
+ phys = PTE_TO_PHYS(l3);
+ if (vm_page_pa_tryrelock(pmap, phys, &pa))
+ goto retry;
+ m = PHYS_TO_VM_PAGE(phys);
+ vm_page_hold(m);
+ }
+ }
+ PA_UNLOCK_COND(pa);
+ PMAP_UNLOCK(pmap);
+ return (m);
+}
+
+vm_paddr_t
+pmap_kextract(vm_offset_t va)
+{
+ pd_entry_t *l2;
+ pt_entry_t *l3;
+ vm_paddr_t pa;
+
+ if (va >= DMAP_MIN_ADDRESS && va < DMAP_MAX_ADDRESS) {
+ pa = DMAP_TO_PHYS(va);
+ } else {
+ l2 = pmap_l2(kernel_pmap, va);
+ if (l2 == NULL)
+ panic("pmap_kextract: No l2");
+ if ((pmap_load(l2) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S)) {
+ /* superpages */
+ pa = (pmap_load(l2) >> PTE_PPN1_S) << L2_SHIFT;
+ pa |= (va & L2_OFFSET);
+ return (pa);
+ }
+
+ l3 = pmap_l2_to_l3(l2, va);
+ if (l3 == NULL)
+ panic("pmap_kextract: No l3...");
+ pa = PTE_TO_PHYS(pmap_load(l3));
+ pa |= (va & PAGE_MASK);
+ }
+ return (pa);
+}
+
+/***************************************************
+ * Low level mapping routines.....
+ ***************************************************/
+
+void
+pmap_kenter_device(vm_offset_t sva, vm_size_t size, vm_paddr_t pa)
+{
+ pt_entry_t *l3;
+ vm_offset_t va;
+
+ panic("%s: implement me\n", __func__);
+
+ KASSERT((pa & L3_OFFSET) == 0,
+ ("pmap_kenter_device: Invalid physical address"));
+ KASSERT((sva & L3_OFFSET) == 0,
+ ("pmap_kenter_device: Invalid virtual address"));
+ KASSERT((size & PAGE_MASK) == 0,
+ ("pmap_kenter_device: Mapping is not page-sized"));
+
+ va = sva;
+ while (size != 0) {
+ l3 = pmap_l3(kernel_pmap, va);
+ KASSERT(l3 != NULL, ("Invalid page table, va: 0x%lx", va));
+ panic("%s: unimplemented", __func__);
+#if 0 /* implement me */
+ pmap_load_store(l3, (pa & ~L3_OFFSET) | ATTR_DEFAULT |
+ ATTR_IDX(DEVICE_MEMORY) | L3_PAGE);
+#endif
+ PTE_SYNC(l3);
+
+ va += PAGE_SIZE;
+ pa += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+ pmap_invalidate_range(kernel_pmap, sva, va);
+}
+
+/*
+ * Remove a page from the kernel pagetables.
+ * Note: not SMP coherent.
+ */
+PMAP_INLINE void
+pmap_kremove(vm_offset_t va)
+{
+ pt_entry_t *l3;
+
+ l3 = pmap_l3(kernel_pmap, va);
+ KASSERT(l3 != NULL, ("pmap_kremove: Invalid address"));
+
+ if (pmap_l3_valid_cacheable(pmap_load(l3)))
+ cpu_dcache_wb_range(va, L3_SIZE);
+ pmap_load_clear(l3);
+ PTE_SYNC(l3);
+ pmap_invalidate_page(kernel_pmap, va);
+}
+
+void
+pmap_kremove_device(vm_offset_t sva, vm_size_t size)
+{
+ pt_entry_t *l3;
+ vm_offset_t va;
+
+ KASSERT((sva & L3_OFFSET) == 0,
+ ("pmap_kremove_device: Invalid virtual address"));
+ KASSERT((size & PAGE_MASK) == 0,
+ ("pmap_kremove_device: Mapping is not page-sized"));
+
+ va = sva;
+ while (size != 0) {
+ l3 = pmap_l3(kernel_pmap, va);
+ KASSERT(l3 != NULL, ("Invalid page table, va: 0x%lx", va));
+ pmap_load_clear(l3);
+ PTE_SYNC(l3);
+
+ va += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+ pmap_invalidate_range(kernel_pmap, sva, va);
+}
+
+/*
+ * Used to map a range of physical addresses into kernel
+ * virtual address space.
+ *
+ * The value passed in '*virt' is a suggested virtual address for
+ * the mapping. Architectures which can support a direct-mapped
+ * physical to virtual region can return the appropriate address
+ * within that region, leaving '*virt' unchanged. Other
+ * architectures should map the pages starting at '*virt' and
+ * update '*virt' with the first usable address after the mapped
+ * region.
+ */
+vm_offset_t
+pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot)
+{
+
+ return PHYS_TO_DMAP(start);
+}
+
+
+/*
+ * Add a list of wired pages to the kva
+ * this routine is only used for temporary
+ * kernel mappings that do not need to have
+ * page modification or references recorded.
+ * Note that old mappings are simply written
+ * over. The page *must* be wired.
+ * Note: SMP coherent. Uses a ranged shootdown IPI.
+ */
+void
+pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count)
+{
+ pt_entry_t *l3, pa;
+ vm_offset_t va;
+ vm_page_t m;
+ pt_entry_t entry;
+ u_int pn;
+ int i;
+
+ va = sva;
+ for (i = 0; i < count; i++) {
+ m = ma[i];
+ pa = VM_PAGE_TO_PHYS(m);
+ pn = (pa / PAGE_SIZE);
+ l3 = pmap_l3(kernel_pmap, va);
+
+ entry = (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S));
+ entry |= (pn << PTE_PPN0_S);
+ pmap_load_store(l3, entry);
+
+ PTE_SYNC(l3);
+ va += L3_SIZE;
+ }
+ pmap_invalidate_range(kernel_pmap, sva, va);
+}
+
+/*
+ * This routine tears out page mappings from the
+ * kernel -- it is meant only for temporary mappings.
+ * Note: SMP coherent. Uses a ranged shootdown IPI.
+ */
+void
+pmap_qremove(vm_offset_t sva, int count)
+{
+ pt_entry_t *l3;
+ vm_offset_t va;
+
+ KASSERT(sva >= VM_MIN_KERNEL_ADDRESS, ("usermode va %lx", sva));
+
+ va = sva;
+ while (count-- > 0) {
+ l3 = pmap_l3(kernel_pmap, va);
+ KASSERT(l3 != NULL, ("pmap_kremove: Invalid address"));
+
+ if (pmap_l3_valid_cacheable(pmap_load(l3)))
+ cpu_dcache_wb_range(va, L3_SIZE);
+ pmap_load_clear(l3);
+ PTE_SYNC(l3);
+
+ va += PAGE_SIZE;
+ }
+ pmap_invalidate_range(kernel_pmap, sva, va);
+}
+
+/***************************************************
+ * Page table page management routines.....
+ ***************************************************/
+static __inline void
+pmap_free_zero_pages(struct spglist *free)
+{
+ vm_page_t m;
+
+ while ((m = SLIST_FIRST(free)) != NULL) {
+ SLIST_REMOVE_HEAD(free, plinks.s.ss);
+ /* Preserve the page's PG_ZERO setting. */
+ vm_page_free_toq(m);
+ }
+}
+
+/*
+ * Schedule the specified unused page table page to be freed. Specifically,
+ * add the page to the specified list of pages that will be released to the
+ * physical memory manager after the TLB has been updated.
+ */
+static __inline void
+pmap_add_delayed_free_list(vm_page_t m, struct spglist *free,
+ boolean_t set_PG_ZERO)
+{
+
+ if (set_PG_ZERO)
+ m->flags |= PG_ZERO;
+ else
+ m->flags &= ~PG_ZERO;
+ SLIST_INSERT_HEAD(free, m, plinks.s.ss);
+}
+
+/*
+ * Decrements a page table page's wire count, which is used to record the
+ * number of valid page table entries within the page. If the wire count
+ * drops to zero, then the page table page is unmapped. Returns TRUE if the
+ * page table page was unmapped and FALSE otherwise.
+ */
+static inline boolean_t
+pmap_unwire_l3(pmap_t pmap, vm_offset_t va, vm_page_t m, struct spglist *free)
+{
+
+ --m->wire_count;
+ if (m->wire_count == 0) {
+ _pmap_unwire_l3(pmap, va, m, free);
+ return (TRUE);
+ } else {
+ return (FALSE);
+ }
+}
+
+static void
+_pmap_unwire_l3(pmap_t pmap, vm_offset_t va, vm_page_t m, struct spglist *free)
+{
+ vm_paddr_t phys;
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ /*
+ * unmap the page table page
+ */
+ if (m->pindex >= NUPDE) {
+ /* PD page */
+ pd_entry_t *l1;
+ l1 = pmap_l1(pmap, va);
+ pmap_load_clear(l1);
+ PTE_SYNC(l1);
+ } else {
+ /* PTE page */
+ pd_entry_t *l2;
+ l2 = pmap_l2(pmap, va);
+ pmap_load_clear(l2);
+ PTE_SYNC(l2);
+ }
+ pmap_resident_count_dec(pmap, 1);
+ if (m->pindex < NUPDE) {
+ pd_entry_t *l1;
+ /* We just released a PT, unhold the matching PD */
+ vm_page_t pdpg;
+
+ l1 = pmap_l1(pmap, va);
+ phys = PTE_TO_PHYS(pmap_load(l1));
+ pdpg = PHYS_TO_VM_PAGE(phys);
+ pmap_unwire_l3(pmap, va, pdpg, free);
+ }
+ pmap_invalidate_page(pmap, va);
+
+ /*
+ * This is a release store so that the ordinary store unmapping
+ * the page table page is globally performed before TLB shoot-
+ * down is begun.
+ */
+ atomic_subtract_rel_int(&vm_cnt.v_wire_count, 1);
+
+ /*
+ * Put page on a list so that it is released after
+ * *ALL* TLB shootdown is done
+ */
+ pmap_add_delayed_free_list(m, free, TRUE);
+}
+
+/*
+ * After removing an l3 entry, this routine is used to
+ * conditionally free the page, and manage the hold/wire counts.
+ */
+static int
+pmap_unuse_l3(pmap_t pmap, vm_offset_t va, pd_entry_t ptepde,
+ struct spglist *free)
+{
+ vm_paddr_t phys;
+ vm_page_t mpte;
+
+ if (va >= VM_MAXUSER_ADDRESS)
+ return (0);
+ KASSERT(ptepde != 0, ("pmap_unuse_pt: ptepde != 0"));
+
+ phys = PTE_TO_PHYS(ptepde);
+
+ mpte = PHYS_TO_VM_PAGE(phys);
+ return (pmap_unwire_l3(pmap, va, mpte, free));
+}
+
+void
+pmap_pinit0(pmap_t pmap)
+{
+
+ PMAP_LOCK_INIT(pmap);
+ bzero(&pmap->pm_stats, sizeof(pmap->pm_stats));
+ pmap->pm_l1 = kernel_pmap->pm_l1;
+}
+
+int
+pmap_pinit(pmap_t pmap)
+{
+ vm_paddr_t l1phys;
+ vm_page_t l1pt;
+
+ /*
+ * allocate the l1 page
+ */
+ while ((l1pt = vm_page_alloc(NULL, 0xdeadbeef, VM_ALLOC_NORMAL |
+ VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO)) == NULL)
+ VM_WAIT;
+
+ l1phys = VM_PAGE_TO_PHYS(l1pt);
+ pmap->pm_l1 = (pd_entry_t *)PHYS_TO_DMAP(l1phys);
+
+ if ((l1pt->flags & PG_ZERO) == 0)
+ pagezero(pmap->pm_l1);
+
+ bzero(&pmap->pm_stats, sizeof(pmap->pm_stats));
+
+ return (1);
+}
+
+/*
+ * This routine is called if the desired page table page does not exist.
+ *
+ * If page table page allocation fails, this routine may sleep before
+ * returning NULL. It sleeps only if a lock pointer was given.
+ *
+ * Note: If a page allocation fails at page table level two or three,
+ * one or two pages may be held during the wait, only to be released
+ * afterwards. This conservative approach is easily argued to avoid
+ * race conditions.
+ */
+static vm_page_t
+_pmap_alloc_l3(pmap_t pmap, vm_pindex_t ptepindex, struct rwlock **lockp)
+{
+ vm_page_t m, /*pdppg, */pdpg;
+ pt_entry_t entry;
+ vm_paddr_t phys;
+ int pn;
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+
+ /*
+ * Allocate a page table page.
+ */
+ if ((m = vm_page_alloc(NULL, ptepindex, VM_ALLOC_NOOBJ |
+ VM_ALLOC_WIRED | VM_ALLOC_ZERO)) == NULL) {
+ if (lockp != NULL) {
+ RELEASE_PV_LIST_LOCK(lockp);
+ PMAP_UNLOCK(pmap);
+ rw_runlock(&pvh_global_lock);
+ VM_WAIT;
+ rw_rlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ }
+
+ /*
+ * Indicate the need to retry. While waiting, the page table
+ * page may have been allocated.
+ */
+ return (NULL);
+ }
+
+ if ((m->flags & PG_ZERO) == 0)
+ pmap_zero_page(m);
+
+ /*
+ * Map the pagetable page into the process address space, if
+ * it isn't already there.
+ */
+
+ if (ptepindex >= NUPDE) {
+ pd_entry_t *l1;
+ vm_pindex_t l1index;
+
+ l1index = ptepindex - NUPDE;
+ l1 = &pmap->pm_l1[l1index];
+
+ pn = (VM_PAGE_TO_PHYS(m) / PAGE_SIZE);
+ entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S));
+ entry |= (pn << PTE_PPN0_S);
+ pmap_load_store(l1, entry);
+
+ PTE_SYNC(l1);
+
+ } else {
+ vm_pindex_t l1index;
+ pd_entry_t *l1, *l2;
+
+ l1index = ptepindex >> (L1_SHIFT - L2_SHIFT);
+ l1 = &pmap->pm_l1[l1index];
+ if (pmap_load(l1) == 0) {
+ /* recurse for allocating page dir */
+ if (_pmap_alloc_l3(pmap, NUPDE + l1index,
+ lockp) == NULL) {
+ --m->wire_count;
+ atomic_subtract_int(&vm_cnt.v_wire_count, 1);
+ vm_page_free_zero(m);
+ return (NULL);
+ }
+ } else {
+ phys = PTE_TO_PHYS(pmap_load(l1));
+ pdpg = PHYS_TO_VM_PAGE(phys);
+ pdpg->wire_count++;
+ }
+
+ phys = PTE_TO_PHYS(pmap_load(l1));
+ l2 = (pd_entry_t *)PHYS_TO_DMAP(phys);
+ l2 = &l2[ptepindex & Ln_ADDR_MASK];
+
+ pn = (VM_PAGE_TO_PHYS(m) / PAGE_SIZE);
+ entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S));
+ entry |= (pn << PTE_PPN0_S);
+ pmap_load_store(l2, entry);
+
+ PTE_SYNC(l2);
+ }
+
+ pmap_resident_count_inc(pmap, 1);
+
+ return (m);
+}
+
+static vm_page_t
+pmap_alloc_l3(pmap_t pmap, vm_offset_t va, struct rwlock **lockp)
+{
+ vm_pindex_t ptepindex;
+ pd_entry_t *l2;
+ vm_paddr_t phys;
+ vm_page_t m;
+
+ /*
+ * Calculate pagetable page index
+ */
+ ptepindex = pmap_l2_pindex(va);
+retry:
+ /*
+ * Get the page directory entry
+ */
+ l2 = pmap_l2(pmap, va);
+
+ /*
+ * If the page table page is mapped, we just increment the
+ * hold count, and activate it.
+ */
+ if (l2 != NULL && pmap_load(l2) != 0) {
+ phys = PTE_TO_PHYS(pmap_load(l2));
+ m = PHYS_TO_VM_PAGE(phys);
+ m->wire_count++;
+ } else {
+ /*
+ * Here if the pte page isn't mapped, or if it has been
+ * deallocated.
+ */
+ m = _pmap_alloc_l3(pmap, ptepindex, lockp);
+ if (m == NULL && lockp != NULL)
+ goto retry;
+ }
+ return (m);
+}
+
+
+/***************************************************
+ * Pmap allocation/deallocation routines.
+ ***************************************************/
+
+/*
+ * Release any resources held by the given physical map.
+ * Called when a pmap initialized by pmap_pinit is being released.
+ * Should only be called if the map contains no valid mappings.
+ */
+void
+pmap_release(pmap_t pmap)
+{
+ vm_page_t m;
+
+ KASSERT(pmap->pm_stats.resident_count == 0,
+ ("pmap_release: pmap resident count %ld != 0",
+ pmap->pm_stats.resident_count));
+
+ m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pmap->pm_l1));
+ m->wire_count--;
+ atomic_subtract_int(&vm_cnt.v_wire_count, 1);
+ vm_page_free_zero(m);
+}
+
+#if 0
+static int
+kvm_size(SYSCTL_HANDLER_ARGS)
+{
+ unsigned long ksize = VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS;
+
+ return sysctl_handle_long(oidp, &ksize, 0, req);
+}
+SYSCTL_PROC(_vm, OID_AUTO, kvm_size, CTLTYPE_LONG|CTLFLAG_RD,
+ 0, 0, kvm_size, "LU", "Size of KVM");
+
+static int
+kvm_free(SYSCTL_HANDLER_ARGS)
+{
+ unsigned long kfree = VM_MAX_KERNEL_ADDRESS - kernel_vm_end;
+
+ return sysctl_handle_long(oidp, &kfree, 0, req);
+}
+SYSCTL_PROC(_vm, OID_AUTO, kvm_free, CTLTYPE_LONG|CTLFLAG_RD,
+ 0, 0, kvm_free, "LU", "Amount of KVM free");
+#endif /* 0 */
+
+/*
+ * grow the number of kernel page table entries, if needed
+ */
+void
+pmap_growkernel(vm_offset_t addr)
+{
+ vm_paddr_t paddr;
+ vm_page_t nkpg;
+ pd_entry_t *l1, *l2;
+ pt_entry_t entry;
+ int pn;
+
+ mtx_assert(&kernel_map->system_mtx, MA_OWNED);
+
+ addr = roundup2(addr, L2_SIZE);
+ if (addr - 1 >= kernel_map->max_offset)
+ addr = kernel_map->max_offset;
+ while (kernel_vm_end < addr) {
+ l1 = pmap_l1(kernel_pmap, kernel_vm_end);
+ if (pmap_load(l1) == 0) {
+ /* We need a new PDP entry */
+ nkpg = vm_page_alloc(NULL, kernel_vm_end >> L1_SHIFT,
+ VM_ALLOC_INTERRUPT | VM_ALLOC_NOOBJ |
+ VM_ALLOC_WIRED | VM_ALLOC_ZERO);
+ if (nkpg == NULL)
+ panic("pmap_growkernel: no memory to grow kernel");
+ if ((nkpg->flags & PG_ZERO) == 0)
+ pmap_zero_page(nkpg);
+ paddr = VM_PAGE_TO_PHYS(nkpg);
+
+ panic("%s: implement grow l1\n", __func__);
+#if 0
+ pmap_load_store(l1, paddr | L1_TABLE);
+#endif
+ PTE_SYNC(l1);
+ continue; /* try again */
+ }
+ l2 = pmap_l1_to_l2(l1, kernel_vm_end);
+ if ((pmap_load(l2) & PTE_REF) != 0) {
+ kernel_vm_end = (kernel_vm_end + L2_SIZE) & ~L2_OFFSET;
+ if (kernel_vm_end - 1 >= kernel_map->max_offset) {
+ kernel_vm_end = kernel_map->max_offset;
+ break;
+ }
+ continue;
+ }
+
+ nkpg = vm_page_alloc(NULL, kernel_vm_end >> L2_SHIFT,
+ VM_ALLOC_INTERRUPT | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED |
+ VM_ALLOC_ZERO);
+ if (nkpg == NULL)
+ panic("pmap_growkernel: no memory to grow kernel");
+ if ((nkpg->flags & PG_ZERO) == 0)
+ pmap_zero_page(nkpg);
+ paddr = VM_PAGE_TO_PHYS(nkpg);
+
+ pn = (paddr / PAGE_SIZE);
+ entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S));
+ entry |= (pn << PTE_PPN0_S);
+ pmap_load_store(l2, entry);
+
+ PTE_SYNC(l2);
+ pmap_invalidate_page(kernel_pmap, kernel_vm_end);
+
+ kernel_vm_end = (kernel_vm_end + L2_SIZE) & ~L2_OFFSET;
+ if (kernel_vm_end - 1 >= kernel_map->max_offset) {
+ kernel_vm_end = kernel_map->max_offset;
+ break;
+ }
+ }
+}
+
+
+/***************************************************
+ * page management routines.
+ ***************************************************/
+
+CTASSERT(sizeof(struct pv_chunk) == PAGE_SIZE);
+CTASSERT(_NPCM == 3);
+CTASSERT(_NPCPV == 168);
+
+static __inline struct pv_chunk *
+pv_to_chunk(pv_entry_t pv)
+{
+
+ return ((struct pv_chunk *)((uintptr_t)pv & ~(uintptr_t)PAGE_MASK));
+}
+
+#define PV_PMAP(pv) (pv_to_chunk(pv)->pc_pmap)
+
+#define PC_FREE0 0xfffffffffffffffful
+#define PC_FREE1 0xfffffffffffffffful
+#define PC_FREE2 0x000000fffffffffful
+
+static const uint64_t pc_freemask[_NPCM] = { PC_FREE0, PC_FREE1, PC_FREE2 };
+
+#if 0
+#ifdef PV_STATS
+static int pc_chunk_count, pc_chunk_allocs, pc_chunk_frees, pc_chunk_tryfail;
+
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_count, CTLFLAG_RD, &pc_chunk_count, 0,
+ "Current number of pv entry chunks");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_allocs, CTLFLAG_RD, &pc_chunk_allocs, 0,
+ "Current number of pv entry chunks allocated");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_frees, CTLFLAG_RD, &pc_chunk_frees, 0,
+ "Current number of pv entry chunks frees");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_tryfail, CTLFLAG_RD, &pc_chunk_tryfail, 0,
+ "Number of times tried to get a chunk page but failed.");
+
+static long pv_entry_frees, pv_entry_allocs, pv_entry_count;
+static int pv_entry_spare;
+
+SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_frees, CTLFLAG_RD, &pv_entry_frees, 0,
+ "Current number of pv entry frees");
+SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_allocs, CTLFLAG_RD, &pv_entry_allocs, 0,
+ "Current number of pv entry allocs");
+SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_count, CTLFLAG_RD, &pv_entry_count, 0,
+ "Current number of pv entries");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_spare, CTLFLAG_RD, &pv_entry_spare, 0,
+ "Current number of spare pv entries");
+#endif
+#endif /* 0 */
+
+/*
+ * We are in a serious low memory condition. Resort to
+ * drastic measures to free some pages so we can allocate
+ * another pv entry chunk.
+ *
+ * Returns NULL if PV entries were reclaimed from the specified pmap.
+ *
+ * We do not, however, unmap 2mpages because subsequent accesses will
+ * allocate per-page pv entries until repromotion occurs, thereby
+ * exacerbating the shortage of free pv entries.
+ */
+static vm_page_t
+reclaim_pv_chunk(pmap_t locked_pmap, struct rwlock **lockp)
+{
+
+ panic("RISCVTODO: reclaim_pv_chunk");
+}
+
+/*
+ * free the pv_entry back to the free list
+ */
+static void
+free_pv_entry(pmap_t pmap, pv_entry_t pv)
+{
+ struct pv_chunk *pc;
+ int idx, field, bit;
+
+ rw_assert(&pvh_global_lock, RA_LOCKED);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ PV_STAT(atomic_add_long(&pv_entry_frees, 1));
+ PV_STAT(atomic_add_int(&pv_entry_spare, 1));
+ PV_STAT(atomic_subtract_long(&pv_entry_count, 1));
+ pc = pv_to_chunk(pv);
+ idx = pv - &pc->pc_pventry[0];
+ field = idx / 64;
+ bit = idx % 64;
+ pc->pc_map[field] |= 1ul << bit;
+ if (pc->pc_map[0] != PC_FREE0 || pc->pc_map[1] != PC_FREE1 ||
+ pc->pc_map[2] != PC_FREE2) {
+ /* 98% of the time, pc is already at the head of the list. */
+ if (__predict_false(pc != TAILQ_FIRST(&pmap->pm_pvchunk))) {
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list);
+ }
+ return;
+ }
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ free_pv_chunk(pc);
+}
+
+static void
+free_pv_chunk(struct pv_chunk *pc)
+{
+ vm_page_t m;
+
+ mtx_lock(&pv_chunks_mutex);
+ TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
+ mtx_unlock(&pv_chunks_mutex);
+ PV_STAT(atomic_subtract_int(&pv_entry_spare, _NPCPV));
+ PV_STAT(atomic_subtract_int(&pc_chunk_count, 1));
+ PV_STAT(atomic_add_int(&pc_chunk_frees, 1));
+ /* entire chunk is free, return it */
+ m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pc));
+#if 0 /* TODO: For minidump */
+ dump_drop_page(m->phys_addr);
+#endif
+ vm_page_unwire(m, PQ_INACTIVE);
+ vm_page_free(m);
+}
+
+/*
+ * Returns a new PV entry, allocating a new PV chunk from the system when
+ * needed. If this PV chunk allocation fails and a PV list lock pointer was
+ * given, a PV chunk is reclaimed from an arbitrary pmap. Otherwise, NULL is
+ * returned.
+ *
+ * The given PV list lock may be released.
+ */
+static pv_entry_t
+get_pv_entry(pmap_t pmap, struct rwlock **lockp)
+{
+ int bit, field;
+ pv_entry_t pv;
+ struct pv_chunk *pc;
+ vm_page_t m;
+
+ rw_assert(&pvh_global_lock, RA_LOCKED);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ PV_STAT(atomic_add_long(&pv_entry_allocs, 1));
+retry:
+ pc = TAILQ_FIRST(&pmap->pm_pvchunk);
+ if (pc != NULL) {
+ for (field = 0; field < _NPCM; field++) {
+ if (pc->pc_map[field]) {
+ bit = ffsl(pc->pc_map[field]) - 1;
+ break;
+ }
+ }
+ if (field < _NPCM) {
+ pv = &pc->pc_pventry[field * 64 + bit];
+ pc->pc_map[field] &= ~(1ul << bit);
+ /* If this was the last item, move it to tail */
+ if (pc->pc_map[0] == 0 && pc->pc_map[1] == 0 &&
+ pc->pc_map[2] == 0) {
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ TAILQ_INSERT_TAIL(&pmap->pm_pvchunk, pc,
+ pc_list);
+ }
+ PV_STAT(atomic_add_long(&pv_entry_count, 1));
+ PV_STAT(atomic_subtract_int(&pv_entry_spare, 1));
+ return (pv);
+ }
+ }
+ /* No free items, allocate another chunk */
+ m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ |
+ VM_ALLOC_WIRED);
+ if (m == NULL) {
+ if (lockp == NULL) {
+ PV_STAT(pc_chunk_tryfail++);
+ return (NULL);
+ }
+ m = reclaim_pv_chunk(pmap, lockp);
+ if (m == NULL)
+ goto retry;
+ }
+ PV_STAT(atomic_add_int(&pc_chunk_count, 1));
+ PV_STAT(atomic_add_int(&pc_chunk_allocs, 1));
+#if 0 /* TODO: This is for minidump */
+ dump_add_page(m->phys_addr);
+#endif
+ pc = (void *)PHYS_TO_DMAP(m->phys_addr);
+ pc->pc_pmap = pmap;
+ pc->pc_map[0] = PC_FREE0 & ~1ul; /* preallocated bit 0 */
+ pc->pc_map[1] = PC_FREE1;
+ pc->pc_map[2] = PC_FREE2;
+ mtx_lock(&pv_chunks_mutex);
+ TAILQ_INSERT_TAIL(&pv_chunks, pc, pc_lru);
+ mtx_unlock(&pv_chunks_mutex);
+ pv = &pc->pc_pventry[0];
+ TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list);
+ PV_STAT(atomic_add_long(&pv_entry_count, 1));
+ PV_STAT(atomic_add_int(&pv_entry_spare, _NPCPV - 1));
+ return (pv);
+}
+
+/*
+ * First find and then remove the pv entry for the specified pmap and virtual
+ * address from the specified pv list. Returns the pv entry if found and NULL
+ * otherwise. This operation can be performed on pv lists for either 4KB or
+ * 2MB page mappings.
+ */
+static __inline pv_entry_t
+pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va)
+{
+ pv_entry_t pv;
+
+ rw_assert(&pvh_global_lock, RA_LOCKED);
+ TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
+ if (pmap == PV_PMAP(pv) && va == pv->pv_va) {
+ TAILQ_REMOVE(&pvh->pv_list, pv, pv_next);
+ pvh->pv_gen++;
+ break;
+ }
+ }
+ return (pv);
+}
+
+/*
+ * First find and then destroy the pv entry for the specified pmap and virtual
+ * address. This operation can be performed on pv lists for either 4KB or 2MB
+ * page mappings.
+ */
+static void
+pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va)
+{
+ pv_entry_t pv;
+
+ pv = pmap_pvh_remove(pvh, pmap, va);
+
+ KASSERT(pv != NULL, ("pmap_pvh_free: pv not found"));
+ free_pv_entry(pmap, pv);
+}
+
+/*
+ * Conditionally create the PV entry for a 4KB page mapping if the required
+ * memory can be allocated without resorting to reclamation.
+ */
+static boolean_t
+pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m,
+ struct rwlock **lockp)
+{
+ pv_entry_t pv;
+
+ rw_assert(&pvh_global_lock, RA_LOCKED);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ /* Pass NULL instead of the lock pointer to disable reclamation. */
+ if ((pv = get_pv_entry(pmap, NULL)) != NULL) {
+ pv->pv_va = va;
+ CHANGE_PV_LIST_LOCK_TO_VM_PAGE(lockp, m);
+ TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
+ m->md.pv_gen++;
+ return (TRUE);
+ } else
+ return (FALSE);
+}
+
+/*
+ * pmap_remove_l3: do the things to unmap a page in a process
+ */
+static int
+pmap_remove_l3(pmap_t pmap, pt_entry_t *l3, vm_offset_t va,
+ pd_entry_t l2e, struct spglist *free, struct rwlock **lockp)
+{
+ pt_entry_t old_l3;
+ vm_paddr_t phys;
+ vm_page_t m;
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ if (pmap_is_current(pmap) && pmap_l3_valid_cacheable(pmap_load(l3)))
+ cpu_dcache_wb_range(va, L3_SIZE);
+ old_l3 = pmap_load_clear(l3);
+ PTE_SYNC(l3);
+ pmap_invalidate_page(pmap, va);
+ if (old_l3 & PTE_SW_WIRED)
+ pmap->pm_stats.wired_count -= 1;
+ pmap_resident_count_dec(pmap, 1);
+ if (old_l3 & PTE_SW_MANAGED) {
+ phys = PTE_TO_PHYS(old_l3);
+ m = PHYS_TO_VM_PAGE(phys);
+ if (pmap_page_dirty(old_l3))
+ vm_page_dirty(m);
+ if (old_l3 & PTE_REF)
+ vm_page_aflag_set(m, PGA_REFERENCED);
+ CHANGE_PV_LIST_LOCK_TO_VM_PAGE(lockp, m);
+ pmap_pvh_free(&m->md, pmap, va);
+ }
+
+ return (pmap_unuse_l3(pmap, va, l2e, free));
+}
+
+/*
+ * Remove the given range of addresses from the specified map.
+ *
+ * It is assumed that the start and end are properly
+ * rounded to the page size.
+ */
+void
+pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
+{
+ struct rwlock *lock;
+ vm_offset_t va, va_next;
+ pd_entry_t *l1, *l2;
+ pt_entry_t l3_pte, *l3;
+ struct spglist free;
+ int anyvalid;
+
+ /*
+ * Perform an unsynchronized read. This is, however, safe.
+ */
+ if (pmap->pm_stats.resident_count == 0)
+ return;
+
+ anyvalid = 0;
+ SLIST_INIT(&free);
+
+ rw_rlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+
+ lock = NULL;
+ for (; sva < eva; sva = va_next) {
+ if (pmap->pm_stats.resident_count == 0)
+ break;
+
+ l1 = pmap_l1(pmap, sva);
+ if (pmap_load(l1) == 0) {
+ va_next = (sva + L1_SIZE) & ~L1_OFFSET;
+ if (va_next < sva)
+ va_next = eva;
+ continue;
+ }
+
+ /*
+ * Calculate index for next page table.
+ */
+ va_next = (sva + L2_SIZE) & ~L2_OFFSET;
+ if (va_next < sva)
+ va_next = eva;
+
+ l2 = pmap_l1_to_l2(l1, sva);
+ if (l2 == NULL)
+ continue;
+
+ l3_pte = pmap_load(l2);
+
+ /*
+ * Weed out invalid mappings.
+ */
+ if (l3_pte == 0)
+ continue;
+ if ((pmap_load(l2) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S))
+ continue;
+
+ /*
+ * Limit our scan to either the end of the va represented
+ * by the current page table page, or to the end of the
+ * range being removed.
+ */
+ if (va_next > eva)
+ va_next = eva;
+
+ va = va_next;
+ for (l3 = pmap_l2_to_l3(l2, sva); sva != va_next; l3++,
+ sva += L3_SIZE) {
+ if (l3 == NULL)
+ panic("l3 == NULL");
+ if (pmap_load(l3) == 0) {
+ if (va != va_next) {
+ pmap_invalidate_range(pmap, va, sva);
+ va = va_next;
+ }
+ continue;
+ }
+ if (va == va_next)
+ va = sva;
+ if (pmap_remove_l3(pmap, l3, sva, l3_pte, &free,
+ &lock)) {
+ sva += L3_SIZE;
+ break;
+ }
+ }
+ if (va != va_next)
+ pmap_invalidate_range(pmap, va, sva);
+ }
+ if (lock != NULL)
+ rw_wunlock(lock);
+ if (anyvalid)
+ pmap_invalidate_all(pmap);
+ rw_runlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+ pmap_free_zero_pages(&free);
+}
+
+/*
+ * Routine: pmap_remove_all
+ * Function:
+ * Removes this physical page from
+ * all physical maps in which it resides.
+ * Reflects back modify bits to the pager.
+ *
+ * Notes:
+ * Original versions of this routine were very
+ * inefficient because they iteratively called
+ * pmap_remove (slow...)
+ */
+
+void
+pmap_remove_all(vm_page_t m)
+{
+ pv_entry_t pv;
+ pmap_t pmap;
+ pt_entry_t *l3, tl3;
+ pd_entry_t *l2, tl2;
+ struct spglist free;
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_remove_all: page %p is not managed", m));
+ SLIST_INIT(&free);
+ rw_wlock(&pvh_global_lock);
+ while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pmap_resident_count_dec(pmap, 1);
+ l2 = pmap_l2(pmap, pv->pv_va);
+ KASSERT(l2 != NULL, ("pmap_remove_all: no l2 table found"));
+ tl2 = pmap_load(l2);
+
+ KASSERT((tl2 & PTE_TYPE_M) == (PTE_TYPE_PTR << PTE_TYPE_S),
+ ("pmap_remove_all: found a table when expecting "
+ "a block in %p's pv list", m));
+
+ l3 = pmap_l2_to_l3(l2, pv->pv_va);
+ if (pmap_is_current(pmap) &&
+ pmap_l3_valid_cacheable(pmap_load(l3)))
+ cpu_dcache_wb_range(pv->pv_va, L3_SIZE);
+ tl3 = pmap_load_clear(l3);
+ PTE_SYNC(l3);
+ pmap_invalidate_page(pmap, pv->pv_va);
+ if (tl3 & PTE_SW_WIRED)
+ pmap->pm_stats.wired_count--;
+ if ((tl3 & PTE_REF) != 0)
+ vm_page_aflag_set(m, PGA_REFERENCED);
+
+ /*
+ * Update the vm_page_t clean and reference bits.
+ */
+ if (pmap_page_dirty(tl3))
+ vm_page_dirty(m);
+ pmap_unuse_l3(pmap, pv->pv_va, pmap_load(l2), &free);
+ TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
+ m->md.pv_gen++;
+ free_pv_entry(pmap, pv);
+ PMAP_UNLOCK(pmap);
+ }
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ rw_wunlock(&pvh_global_lock);
+ pmap_free_zero_pages(&free);
+}
+
+/*
+ * Set the physical protection on the
+ * specified range of this map as requested.
+ */
+void
+pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
+{
+ vm_offset_t va, va_next;
+ pd_entry_t *l1, *l2;
+ pt_entry_t *l3p, l3;
+ pt_entry_t entry;
+
+ if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+ pmap_remove(pmap, sva, eva);
+ return;
+ }
+
+ if ((prot & VM_PROT_WRITE) == VM_PROT_WRITE)
+ return;
+
+ PMAP_LOCK(pmap);
+ for (; sva < eva; sva = va_next) {
+
+ l1 = pmap_l1(pmap, sva);
+ if (pmap_load(l1) == 0) {
+ va_next = (sva + L1_SIZE) & ~L1_OFFSET;
+ if (va_next < sva)
+ va_next = eva;
+ continue;
+ }
+
+ va_next = (sva + L2_SIZE) & ~L2_OFFSET;
+ if (va_next < sva)
+ va_next = eva;
+
+ l2 = pmap_l1_to_l2(l1, sva);
+ if (l2 == NULL)
+ continue;
+ if ((pmap_load(l2) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S))
+ continue;
+
+ if (va_next > eva)
+ va_next = eva;
+
+ va = va_next;
+ for (l3p = pmap_l2_to_l3(l2, sva); sva != va_next; l3p++,
+ sva += L3_SIZE) {
+ l3 = pmap_load(l3p);
+ if (pmap_l3_valid(l3)) {
+ entry = pmap_load(l3p);
+ entry &= ~(1 << PTE_TYPE_S);
+ pmap_load_store(l3p, entry);
+ PTE_SYNC(l3p);
+ /* XXX: Use pmap_invalidate_range */
+ pmap_invalidate_page(pmap, va);
+ }
+ }
+ }
+ PMAP_UNLOCK(pmap);
+
+ /* TODO: Only invalidate entries we are touching */
+ pmap_invalidate_all(pmap);
+}
+
+/*
+ * Insert the given physical page (p) at
+ * the specified virtual address (v) in the
+ * target physical map with the protection requested.
+ *
+ * If specified, the page will be wired down, meaning
+ * that the related pte can not be reclaimed.
+ *
+ * NB: This is the only routine which MAY NOT lazy-evaluate
+ * or lose information. That is, this routine must actually
+ * insert this page into the given map NOW.
+ */
+int
+pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
+ u_int flags, int8_t psind __unused)
+{
+ struct rwlock *lock;
+ pd_entry_t *l1, *l2;
+ pt_entry_t new_l3, orig_l3;
+ pt_entry_t *l3;
+ pv_entry_t pv;
+ vm_paddr_t opa, pa, l2_pa, l3_pa;
+ vm_page_t mpte, om, l2_m, l3_m;
+ boolean_t nosleep;
+ pt_entry_t entry;
+ int l2_pn;
+ int l3_pn;
+ int pn;
+
+ va = trunc_page(va);
+ if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m))
+ VM_OBJECT_ASSERT_LOCKED(m->object);
+ pa = VM_PAGE_TO_PHYS(m);
+ pn = (pa / PAGE_SIZE);
+
+ new_l3 = PTE_VALID;
+
+ if ((prot & VM_PROT_WRITE) == 0) { /* Read-only */
+ if ((va >> 63) == 0) /* USER */
+ new_l3 |= (PTE_TYPE_SURX << PTE_TYPE_S);
+ else /* KERNEL */
+ new_l3 |= (PTE_TYPE_SRX << PTE_TYPE_S);
+ } else {
+ if ((va >> 63) == 0) /* USER */
+ new_l3 |= (PTE_TYPE_SURWX << PTE_TYPE_S);
+ else /* KERNEL */
+ new_l3 |= (PTE_TYPE_SRWX << PTE_TYPE_S);
+ }
+
+ new_l3 |= (pn << PTE_PPN0_S);
+ if ((flags & PMAP_ENTER_WIRED) != 0)
+ new_l3 |= PTE_SW_WIRED;
+
+ CTR2(KTR_PMAP, "pmap_enter: %.16lx -> %.16lx", va, pa);
+
+ mpte = NULL;
+
+ lock = NULL;
+ rw_rlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+
+ if (va < VM_MAXUSER_ADDRESS) {
+ nosleep = (flags & PMAP_ENTER_NOSLEEP) != 0;
+ mpte = pmap_alloc_l3(pmap, va, nosleep ? NULL : &lock);
+ if (mpte == NULL && nosleep) {
+ CTR0(KTR_PMAP, "pmap_enter: mpte == NULL");
+ if (lock != NULL)
+ rw_wunlock(lock);
+ rw_runlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+ return (KERN_RESOURCE_SHORTAGE);
+ }
+ l3 = pmap_l3(pmap, va);
+ } else {
+ l3 = pmap_l3(pmap, va);
+ /* TODO: This is not optimal, but should mostly work */
+ if (l3 == NULL) {
+ l2 = pmap_l2(pmap, va);
+ if (l2 == NULL) {
+ l2_m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL |
+ VM_ALLOC_NOOBJ | VM_ALLOC_WIRED |
+ VM_ALLOC_ZERO);
+ if (l2_m == NULL)
+ panic("pmap_enter: l2 pte_m == NULL");
+ if ((l2_m->flags & PG_ZERO) == 0)
+ pmap_zero_page(l2_m);
+
+ l2_pa = VM_PAGE_TO_PHYS(l2_m);
+ l2_pn = (l2_pa / PAGE_SIZE);
+
+ l1 = pmap_l1(pmap, va);
+ entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S));
+ entry |= (l2_pn << PTE_PPN0_S);
+ pmap_load_store(l1, entry);
+ PTE_SYNC(l1);
+
+ l2 = pmap_l1_to_l2(l1, va);
+ }
+
+ KASSERT(l2 != NULL,
+ ("No l2 table after allocating one"));
+
+ l3_m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL |
+ VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
+ if (l3_m == NULL)
+ panic("pmap_enter: l3 pte_m == NULL");
+ if ((l3_m->flags & PG_ZERO) == 0)
+ pmap_zero_page(l3_m);
+
+ l3_pa = VM_PAGE_TO_PHYS(l3_m);
+ l3_pn = (l3_pa / PAGE_SIZE);
+ entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S));
+ entry |= (l3_pn << PTE_PPN0_S);
+ pmap_load_store(l2, entry);
+ PTE_SYNC(l2);
+ l3 = pmap_l2_to_l3(l2, va);
+ }
+ pmap_invalidate_page(pmap, va);
+ }
+
+ om = NULL;
+ orig_l3 = pmap_load(l3);
+ opa = PTE_TO_PHYS(orig_l3);
+
+ /*
+ * Is the specified virtual address already mapped?
+ */
+ if (pmap_l3_valid(orig_l3)) {
+ /*
+ * Wiring change, just update stats. We don't worry about
+ * wiring PT pages as they remain resident as long as there
+ * are valid mappings in them. Hence, if a user page is wired,
+ * the PT page will be also.
+ */
+ if ((flags & PMAP_ENTER_WIRED) != 0 &&
+ (orig_l3 & PTE_SW_WIRED) == 0)
+ pmap->pm_stats.wired_count++;
+ else if ((flags & PMAP_ENTER_WIRED) == 0 &&
+ (orig_l3 & PTE_SW_WIRED) != 0)
+ pmap->pm_stats.wired_count--;
+
+ /*
+ * Remove the extra PT page reference.
+ */
+ if (mpte != NULL) {
+ mpte->wire_count--;
+ KASSERT(mpte->wire_count > 0,
+ ("pmap_enter: missing reference to page table page,"
+ " va: 0x%lx", va));
+ }
+
+ /*
+ * Has the physical page changed?
+ */
+ if (opa == pa) {
+ /*
+ * No, might be a protection or wiring change.
+ */
+ if ((orig_l3 & PTE_SW_MANAGED) != 0) {
+ new_l3 |= PTE_SW_MANAGED;
+ if (pmap_is_write(new_l3))
+ vm_page_aflag_set(m, PGA_WRITEABLE);
+ }
+ goto validate;
+ }
+
+ /* Flush the cache, there might be uncommitted data in it */
+ if (pmap_is_current(pmap) && pmap_l3_valid_cacheable(orig_l3))
+ cpu_dcache_wb_range(va, L3_SIZE);
+ } else {
+ /*
+ * Increment the counters.
+ */
+ if ((new_l3 & PTE_SW_WIRED) != 0)
+ pmap->pm_stats.wired_count++;
+ pmap_resident_count_inc(pmap, 1);
+ }
+ /*
+ * Enter on the PV list if part of our managed memory.
+ */
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
+ new_l3 |= PTE_SW_MANAGED;
+ pv = get_pv_entry(pmap, &lock);
+ pv->pv_va = va;
+ CHANGE_PV_LIST_LOCK_TO_PHYS(&lock, pa);
+ TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
+ m->md.pv_gen++;
+ if (pmap_is_write(new_l3))
+ vm_page_aflag_set(m, PGA_WRITEABLE);
+ }
+
+ /*
+ * Update the L3 entry.
+ */
+ if (orig_l3 != 0) {
+validate:
+ orig_l3 = pmap_load_store(l3, new_l3);
+ PTE_SYNC(l3);
+ opa = PTE_TO_PHYS(orig_l3);
+
+ if (opa != pa) {
+ if ((orig_l3 & PTE_SW_MANAGED) != 0) {
+ om = PHYS_TO_VM_PAGE(opa);
+ if (pmap_page_dirty(orig_l3))
+ vm_page_dirty(om);
+ if ((orig_l3 & PTE_REF) != 0)
+ vm_page_aflag_set(om, PGA_REFERENCED);
+ CHANGE_PV_LIST_LOCK_TO_PHYS(&lock, opa);
+ pmap_pvh_free(&om->md, pmap, va);
+ }
+ } else if (pmap_page_dirty(orig_l3)) {
+ if ((orig_l3 & PTE_SW_MANAGED) != 0)
+ vm_page_dirty(m);
+ }
+ } else {
+ pmap_load_store(l3, new_l3);
+ PTE_SYNC(l3);
+ }
+ pmap_invalidate_page(pmap, va);
+ if ((pmap != pmap_kernel()) && (pmap == &curproc->p_vmspace->vm_pmap))
+ cpu_icache_sync_range(va, PAGE_SIZE);
+
+ if (lock != NULL)
+ rw_wunlock(lock);
+ rw_runlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+ return (KERN_SUCCESS);
+}
+
+/*
+ * Maps a sequence of resident pages belonging to the same object.
+ * The sequence begins with the given page m_start. This page is
+ * mapped at the given virtual address start. Each subsequent page is
+ * mapped at a virtual address that is offset from start by the same
+ * amount as the page is offset from m_start within the object. The
+ * last page in the sequence is the page with the largest offset from
+ * m_start that can be mapped at a virtual address less than the given
+ * virtual address end. Not every virtual page between start and end
+ * is mapped; only those for which a resident page exists with the
+ * corresponding offset from m_start are mapped.
+ */
+void
+pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
+ vm_page_t m_start, vm_prot_t prot)
+{
+ struct rwlock *lock;
+ vm_offset_t va;
+ vm_page_t m, mpte;
+ vm_pindex_t diff, psize;
+
+ VM_OBJECT_ASSERT_LOCKED(m_start->object);
+
+ psize = atop(end - start);
+ mpte = NULL;
+ m = m_start;
+ lock = NULL;
+ rw_rlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
+ va = start + ptoa(diff);
+ mpte = pmap_enter_quick_locked(pmap, va, m, prot, mpte, &lock);
+ m = TAILQ_NEXT(m, listq);
+ }
+ if (lock != NULL)
+ rw_wunlock(lock);
+ rw_runlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+}
+
+/*
+ * this code makes some *MAJOR* assumptions:
+ * 1. Current pmap & pmap exists.
+ * 2. Not wired.
+ * 3. Read access.
+ * 4. No page table pages.
+ * but is *MUCH* faster than pmap_enter...
+ */
+
+void
+pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
+{
+ struct rwlock *lock;
+
+ lock = NULL;
+ rw_rlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ (void)pmap_enter_quick_locked(pmap, va, m, prot, NULL, &lock);
+ if (lock != NULL)
+ rw_wunlock(lock);
+ rw_runlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+}
+
+static vm_page_t
+pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
+ vm_prot_t prot, vm_page_t mpte, struct rwlock **lockp)
+{
+ struct spglist free;
+ vm_paddr_t phys;
+ pd_entry_t *l2;
+ pt_entry_t *l3;
+ vm_paddr_t pa;
+ pt_entry_t entry;
+ int pn;
+
+ KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva ||
+ (m->oflags & VPO_UNMANAGED) != 0,
+ ("pmap_enter_quick_locked: managed mapping within the clean submap"));
+ rw_assert(&pvh_global_lock, RA_LOCKED);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+
+ CTR2(KTR_PMAP, "pmap_enter_quick_locked: %p %lx", pmap, va);
+ /*
+ * In the case that a page table page is not
+ * resident, we are creating it here.
+ */
+ if (va < VM_MAXUSER_ADDRESS) {
+ vm_pindex_t l2pindex;
+
+ /*
+ * Calculate pagetable page index
+ */
+ l2pindex = pmap_l2_pindex(va);
+ if (mpte && (mpte->pindex == l2pindex)) {
+ mpte->wire_count++;
+ } else {
+ /*
+ * Get the l2 entry
+ */
+ l2 = pmap_l2(pmap, va);
+
+ /*
+ * If the page table page is mapped, we just increment
+ * the hold count, and activate it. Otherwise, we
+ * attempt to allocate a page table page. If this
+ * attempt fails, we don't retry. Instead, we give up.
+ */
+ if (l2 != NULL && pmap_load(l2) != 0) {
+ phys = PTE_TO_PHYS(pmap_load(l2));
+ mpte = PHYS_TO_VM_PAGE(phys);
+ mpte->wire_count++;
+ } else {
+ /*
+ * Pass NULL instead of the PV list lock
+ * pointer, because we don't intend to sleep.
+ */
+ mpte = _pmap_alloc_l3(pmap, l2pindex, NULL);
+ if (mpte == NULL)
+ return (mpte);
+ }
+ }
+ l3 = (pt_entry_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(mpte));
+ l3 = &l3[pmap_l3_index(va)];
+ } else {
+ mpte = NULL;
+ l3 = pmap_l3(kernel_pmap, va);
+ }
+ if (l3 == NULL)
+ panic("pmap_enter_quick_locked: No l3");
+ if (pmap_load(l3) != 0) {
+ if (mpte != NULL) {
+ mpte->wire_count--;
+ mpte = NULL;
+ }
+ return (mpte);
+ }
+
+ /*
+ * Enter on the PV list if part of our managed memory.
+ */
+ if ((m->oflags & VPO_UNMANAGED) == 0 &&
+ !pmap_try_insert_pv_entry(pmap, va, m, lockp)) {
+ if (mpte != NULL) {
+ SLIST_INIT(&free);
+ if (pmap_unwire_l3(pmap, va, mpte, &free)) {
+ pmap_invalidate_page(pmap, va);
+ pmap_free_zero_pages(&free);
+ }
+ mpte = NULL;
+ }
+ return (mpte);
+ }
+
+ /*
+ * Increment counters
+ */
+ pmap_resident_count_inc(pmap, 1);
+
+ pa = VM_PAGE_TO_PHYS(m);
+ pn = (pa / PAGE_SIZE);
+
+ /* RISCVTODO: check permissions */
+ entry = (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S));
+ entry |= (pn << PTE_PPN0_S);
+
+ /*
+ * Now validate mapping with RO protection
+ */
+ if ((m->oflags & VPO_UNMANAGED) == 0)
+ entry |= PTE_SW_MANAGED;
+ pmap_load_store(l3, entry);
+
+ PTE_SYNC(l3);
+ pmap_invalidate_page(pmap, va);
+ return (mpte);
+}
+
+/*
+ * This code maps large physical mmap regions into the
+ * processor address space. Note that some shortcuts
+ * are taken, but the code works.
+ */
+void
+pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object,
+ vm_pindex_t pindex, vm_size_t size)
+{
+
+ VM_OBJECT_ASSERT_WLOCKED(object);
+ KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG,
+ ("pmap_object_init_pt: non-device object"));
+}
+
+/*
+ * Clear the wired attribute from the mappings for the specified range of
+ * addresses in the given pmap. Every valid mapping within that range
+ * must have the wired attribute set. In contrast, invalid mappings
+ * cannot have the wired attribute set, so they are ignored.
+ *
+ * The wired attribute of the page table entry is not a hardware feature,
+ * so there is no need to invalidate any TLB entries.
+ */
+void
+pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
+{
+ vm_offset_t va_next;
+ pd_entry_t *l1, *l2;
+ pt_entry_t *l3;
+ boolean_t pv_lists_locked;
+
+ pv_lists_locked = FALSE;
+ PMAP_LOCK(pmap);
+ for (; sva < eva; sva = va_next) {
+ l1 = pmap_l1(pmap, sva);
+ if (pmap_load(l1) == 0) {
+ va_next = (sva + L1_SIZE) & ~L1_OFFSET;
+ if (va_next < sva)
+ va_next = eva;
+ continue;
+ }
+
+ va_next = (sva + L2_SIZE) & ~L2_OFFSET;
+ if (va_next < sva)
+ va_next = eva;
+
+ l2 = pmap_l1_to_l2(l1, sva);
+ if (pmap_load(l2) == 0)
+ continue;
+
+ if (va_next > eva)
+ va_next = eva;
+ for (l3 = pmap_l2_to_l3(l2, sva); sva != va_next; l3++,
+ sva += L3_SIZE) {
+ if (pmap_load(l3) == 0)
+ continue;
+ if ((pmap_load(l3) & PTE_SW_WIRED) == 0)
+ panic("pmap_unwire: l3 %#jx is missing "
+ "PTE_SW_WIRED", (uintmax_t)*l3);
+
+ /*
+ * PG_W must be cleared atomically. Although the pmap
+ * lock synchronizes access to PG_W, another processor
+ * could be setting PG_M and/or PG_A concurrently.
+ */
+ atomic_clear_long(l3, PTE_SW_WIRED);
+ pmap->pm_stats.wired_count--;
+ }
+ }
+ if (pv_lists_locked)
+ rw_runlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+}
+
+/*
+ * Copy the range specified by src_addr/len
+ * from the source map to the range dst_addr/len
+ * in the destination map.
+ *
+ * This routine is only advisory and need not do anything.
+ */
+
+void
+pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
+ vm_offset_t src_addr)
+{
+
+}
+
+/*
+ * pmap_zero_page zeros the specified hardware page by mapping
+ * the page into KVM and using bzero to clear its contents.
+ */
+void
+pmap_zero_page(vm_page_t m)
+{
+ vm_offset_t va = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
+
+ pagezero((void *)va);
+}
+
+/*
+ * pmap_zero_page_area zeros the specified hardware page by mapping
+ * the page into KVM and using bzero to clear its contents.
+ *
+ * off and size may not cover an area beyond a single hardware page.
+ */
+void
+pmap_zero_page_area(vm_page_t m, int off, int size)
+{
+ vm_offset_t va = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
+
+ if (off == 0 && size == PAGE_SIZE)
+ pagezero((void *)va);
+ else
+ bzero((char *)va + off, size);
+}
+
+/*
+ * pmap_zero_page_idle zeros the specified hardware page by mapping
+ * the page into KVM and using bzero to clear its contents. This
+ * is intended to be called from the vm_pagezero process only and
+ * outside of Giant.
+ */
+void
+pmap_zero_page_idle(vm_page_t m)
+{
+ vm_offset_t va = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
+
+ pagezero((void *)va);
+}
+
+/*
+ * pmap_copy_page copies the specified (machine independent)
+ * page by mapping the page into virtual memory and using
+ * bcopy to copy the page, one machine dependent page at a
+ * time.
+ */
+void
+pmap_copy_page(vm_page_t msrc, vm_page_t mdst)
+{
+ vm_offset_t src = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(msrc));
+ vm_offset_t dst = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(mdst));
+
+ pagecopy((void *)src, (void *)dst);
+}
+
+int unmapped_buf_allowed = 1;
+
+void
+pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
+ vm_offset_t b_offset, int xfersize)
+{
+ void *a_cp, *b_cp;
+ vm_page_t m_a, m_b;
+ vm_paddr_t p_a, p_b;
+ vm_offset_t a_pg_offset, b_pg_offset;
+ int cnt;
+
+ while (xfersize > 0) {
+ a_pg_offset = a_offset & PAGE_MASK;
+ m_a = ma[a_offset >> PAGE_SHIFT];
+ p_a = m_a->phys_addr;
+ b_pg_offset = b_offset & PAGE_MASK;
+ m_b = mb[b_offset >> PAGE_SHIFT];
+ p_b = m_b->phys_addr;
+ cnt = min(xfersize, PAGE_SIZE - a_pg_offset);
+ cnt = min(cnt, PAGE_SIZE - b_pg_offset);
+ if (__predict_false(!PHYS_IN_DMAP(p_a))) {
+ panic("!DMAP a %lx", p_a);
+ } else {
+ a_cp = (char *)PHYS_TO_DMAP(p_a) + a_pg_offset;
+ }
+ if (__predict_false(!PHYS_IN_DMAP(p_b))) {
+ panic("!DMAP b %lx", p_b);
+ } else {
+ b_cp = (char *)PHYS_TO_DMAP(p_b) + b_pg_offset;
+ }
+ bcopy(a_cp, b_cp, cnt);
+ a_offset += cnt;
+ b_offset += cnt;
+ xfersize -= cnt;
+ }
+}
+
+vm_offset_t
+pmap_quick_enter_page(vm_page_t m)
+{
+
+ return (PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)));
+}
+
+void
+pmap_quick_remove_page(vm_offset_t addr)
+{
+}
+
+/*
+ * Returns true if the pmap's pv is one of the first
+ * 16 pvs linked to from this page. This count may
+ * be changed upwards or downwards in the future; it
+ * is only necessary that true be returned for a small
+ * subset of pmaps for proper page aging.
+ */
+boolean_t
+pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
+{
+ struct rwlock *lock;
+ pv_entry_t pv;
+ int loops = 0;
+ boolean_t rv;
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_page_exists_quick: page %p is not managed", m));
+ rv = FALSE;
+ rw_rlock(&pvh_global_lock);
+ lock = VM_PAGE_TO_PV_LIST_LOCK(m);
+ rw_rlock(lock);
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
+ if (PV_PMAP(pv) == pmap) {
+ rv = TRUE;
+ break;
+ }
+ loops++;
+ if (loops >= 16)
+ break;
+ }
+ rw_runlock(lock);
+ rw_runlock(&pvh_global_lock);
+ return (rv);
+}
+
+/*
+ * pmap_page_wired_mappings:
+ *
+ * Return the number of managed mappings to the given physical page
+ * that are wired.
+ */
+int
+pmap_page_wired_mappings(vm_page_t m)
+{
+ struct rwlock *lock;
+ pmap_t pmap;
+ pt_entry_t *l3;
+ pv_entry_t pv;
+ int count, md_gen;
+
+ if ((m->oflags & VPO_UNMANAGED) != 0)
+ return (0);
+ rw_rlock(&pvh_global_lock);
+ lock = VM_PAGE_TO_PV_LIST_LOCK(m);
+ rw_rlock(lock);
+restart:
+ count = 0;
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
+ pmap = PV_PMAP(pv);
+ if (!PMAP_TRYLOCK(pmap)) {
+ md_gen = m->md.pv_gen;
+ rw_runlock(lock);
+ PMAP_LOCK(pmap);
+ rw_rlock(lock);
+ if (md_gen != m->md.pv_gen) {
+ PMAP_UNLOCK(pmap);
+ goto restart;
+ }
+ }
+ l3 = pmap_l3(pmap, pv->pv_va);
+ if (l3 != NULL && (pmap_load(l3) & PTE_SW_WIRED) != 0)
+ count++;
+ PMAP_UNLOCK(pmap);
+ }
+ rw_runlock(lock);
+ rw_runlock(&pvh_global_lock);
+ return (count);
+}
+
+/*
+ * Destroy all managed, non-wired mappings in the given user-space
+ * pmap. This pmap cannot be active on any processor besides the
+ * caller.
+ *
+ * This function cannot be applied to the kernel pmap. Moreover, it
+ * is not intended for general use. It is only to be used during
+ * process termination. Consequently, it can be implemented in ways
+ * that make it faster than pmap_remove(). First, it can more quickly
+ * destroy mappings by iterating over the pmap's collection of PV
+ * entries, rather than searching the page table. Second, it doesn't
+ * have to test and clear the page table entries atomically, because
+ * no processor is currently accessing the user address space. In
+ * particular, a page table entry's dirty bit won't change state once
+ * this function starts.
+ */
+void
+pmap_remove_pages(pmap_t pmap)
+{
+ pd_entry_t ptepde, *l2;
+ pt_entry_t *l3, tl3;
+ struct spglist free;
+ vm_page_t m;
+ pv_entry_t pv;
+ struct pv_chunk *pc, *npc;
+ struct rwlock *lock;
+ int64_t bit;
+ uint64_t inuse, bitmask;
+ int allfree, field, freed, idx;
+ vm_paddr_t pa;
+
+ lock = NULL;
+
+ SLIST_INIT(&free);
+ rw_rlock(&pvh_global_lock);
+ PMAP_LOCK(pmap);
+ TAILQ_FOREACH_SAFE(pc, &pmap->pm_pvchunk, pc_list, npc) {
+ allfree = 1;
+ freed = 0;
+ for (field = 0; field < _NPCM; field++) {
+ inuse = ~pc->pc_map[field] & pc_freemask[field];
+ while (inuse != 0) {
+ bit = ffsl(inuse) - 1;
+ bitmask = 1UL << bit;
+ idx = field * 64 + bit;
+ pv = &pc->pc_pventry[idx];
+ inuse &= ~bitmask;
+
+ l2 = pmap_l2(pmap, pv->pv_va);
+ ptepde = pmap_load(l2);
+ l3 = pmap_l2_to_l3(l2, pv->pv_va);
+ tl3 = pmap_load(l3);
+
+/*
+ * We cannot remove wired pages from a process' mapping at this time
+ */
+ if (tl3 & PTE_SW_WIRED) {
+ allfree = 0;
+ continue;
+ }
+
+ pa = PTE_TO_PHYS(tl3);
+ m = PHYS_TO_VM_PAGE(pa);
+ KASSERT(m->phys_addr == pa,
+ ("vm_page_t %p phys_addr mismatch %016jx %016jx",
+ m, (uintmax_t)m->phys_addr,
+ (uintmax_t)tl3));
+
+ KASSERT((m->flags & PG_FICTITIOUS) != 0 ||
+ m < &vm_page_array[vm_page_array_size],
+ ("pmap_remove_pages: bad l3 %#jx",
+ (uintmax_t)tl3));
+
+ if (pmap_is_current(pmap) &&
+ pmap_l3_valid_cacheable(pmap_load(l3)))
+ cpu_dcache_wb_range(pv->pv_va, L3_SIZE);
+ pmap_load_clear(l3);
+ PTE_SYNC(l3);
+ pmap_invalidate_page(pmap, pv->pv_va);
+
+ /*
+ * Update the vm_page_t clean/reference bits.
+ */
+ if (pmap_page_dirty(tl3))
+ vm_page_dirty(m);
+
+ CHANGE_PV_LIST_LOCK_TO_VM_PAGE(&lock, m);
+
+ /* Mark free */
+ pc->pc_map[field] |= bitmask;
+
+ pmap_resident_count_dec(pmap, 1);
+ TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
+ m->md.pv_gen++;
+
+ pmap_unuse_l3(pmap, pv->pv_va, ptepde, &free);
+ freed++;
+ }
+ }
+ PV_STAT(atomic_add_long(&pv_entry_frees, freed));
+ PV_STAT(atomic_add_int(&pv_entry_spare, freed));
+ PV_STAT(atomic_subtract_long(&pv_entry_count, freed));
+ if (allfree) {
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ free_pv_chunk(pc);
+ }
+ }
+ pmap_invalidate_all(pmap);
+ if (lock != NULL)
+ rw_wunlock(lock);
+ rw_runlock(&pvh_global_lock);
+ PMAP_UNLOCK(pmap);
+ pmap_free_zero_pages(&free);
+}
+
+/*
+ * This is used to check if a page has been accessed or modified. As we
+ * don't have a bit to see if it has been modified we have to assume it
+ * has been if the page is read/write.
+ */
+static boolean_t
+pmap_page_test_mappings(vm_page_t m, boolean_t accessed, boolean_t modified)
+{
+ struct rwlock *lock;
+ pv_entry_t pv;
+ pt_entry_t *l3, mask, value;
+ pmap_t pmap;
+ int md_gen;
+ boolean_t rv;
+
+ rv = FALSE;
+ rw_rlock(&pvh_global_lock);
+ lock = VM_PAGE_TO_PV_LIST_LOCK(m);
+ rw_rlock(lock);
+restart:
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
+ pmap = PV_PMAP(pv);
+ if (!PMAP_TRYLOCK(pmap)) {
+ md_gen = m->md.pv_gen;
+ rw_runlock(lock);
+ PMAP_LOCK(pmap);
+ rw_rlock(lock);
+ if (md_gen != m->md.pv_gen) {
+ PMAP_UNLOCK(pmap);
+ goto restart;
+ }
+ }
+ l3 = pmap_l3(pmap, pv->pv_va);
+ mask = 0;
+ value = 0;
+ if (modified) {
+ mask |= PTE_DIRTY;
+ value |= PTE_DIRTY;
+ }
+ if (accessed) {
+ mask |= PTE_REF;
+ value |= PTE_REF;
+ }
+
+#if 0
+ if (modified) {
+ mask |= ATTR_AP_RW_BIT;
+ value |= ATTR_AP(ATTR_AP_RW);
+ }
+ if (accessed) {
+ mask |= ATTR_AF | ATTR_DESCR_MASK;
+ value |= ATTR_AF | L3_PAGE;
+ }
+#endif
+
+ rv = (pmap_load(l3) & mask) == value;
+ PMAP_UNLOCK(pmap);
+ if (rv)
+ goto out;
+ }
+out:
+ rw_runlock(lock);
+ rw_runlock(&pvh_global_lock);
+ return (rv);
+}
+
+/*
+ * pmap_is_modified:
+ *
+ * Return whether or not the specified physical page was modified
+ * in any physical maps.
+ */
+boolean_t
+pmap_is_modified(vm_page_t m)
+{
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_is_modified: page %p is not managed", m));
+
+ /*
+ * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
+ * concurrently set while the object is locked. Thus, if PGA_WRITEABLE
+ * is clear, no PTEs can have PG_M set.
+ */
+ VM_OBJECT_ASSERT_WLOCKED(m->object);
+ if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
+ return (FALSE);
+ return (pmap_page_test_mappings(m, FALSE, TRUE));
+}
+
+/*
+ * pmap_is_prefaultable:
+ *
+ * Return whether or not the specified virtual address is eligible
+ * for prefault.
+ */
+boolean_t
+pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr)
+{
+ pt_entry_t *l3;
+ boolean_t rv;
+
+ rv = FALSE;
+ PMAP_LOCK(pmap);
+ l3 = pmap_l3(pmap, addr);
+ if (l3 != NULL && pmap_load(l3) != 0) {
+ rv = TRUE;
+ }
+ PMAP_UNLOCK(pmap);
+ return (rv);
+}
+
+/*
+ * pmap_is_referenced:
+ *
+ * Return whether or not the specified physical page was referenced
+ * in any physical maps.
+ */
+boolean_t
+pmap_is_referenced(vm_page_t m)
+{
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_is_referenced: page %p is not managed", m));
+ return (pmap_page_test_mappings(m, TRUE, FALSE));
+}
+
+/*
+ * Clear the write and modified bits in each of the given page's mappings.
+ */
+void
+pmap_remove_write(vm_page_t m)
+{
+ pmap_t pmap;
+ struct rwlock *lock;
+ pv_entry_t pv;
+ pt_entry_t *l3, oldl3;
+ pt_entry_t newl3;
+ int md_gen;
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_remove_write: page %p is not managed", m));
+
+ /*
+ * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
+ * set by another thread while the object is locked. Thus,
+ * if PGA_WRITEABLE is clear, no page table entries need updating.
+ */
+ VM_OBJECT_ASSERT_WLOCKED(m->object);
+ if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
+ return;
+ rw_rlock(&pvh_global_lock);
+ lock = VM_PAGE_TO_PV_LIST_LOCK(m);
+retry_pv_loop:
+ rw_wlock(lock);
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
+ pmap = PV_PMAP(pv);
+ if (!PMAP_TRYLOCK(pmap)) {
+ md_gen = m->md.pv_gen;
+ rw_wunlock(lock);
+ PMAP_LOCK(pmap);
+ rw_wlock(lock);
+ if (md_gen != m->md.pv_gen) {
+ PMAP_UNLOCK(pmap);
+ rw_wunlock(lock);
+ goto retry_pv_loop;
+ }
+ }
+ l3 = pmap_l3(pmap, pv->pv_va);
+retry:
+ oldl3 = pmap_load(l3);
+
+ if (pmap_is_write(oldl3)) {
+ newl3 = oldl3 & ~(1 << PTE_TYPE_S);
+ if (!atomic_cmpset_long(l3, oldl3, newl3))
+ goto retry;
+ /* TODO: use pmap_page_dirty(oldl3) ? */
+ if ((oldl3 & PTE_REF) != 0)
+ vm_page_dirty(m);
+ pmap_invalidate_page(pmap, pv->pv_va);
+ }
+ PMAP_UNLOCK(pmap);
+ }
+ rw_wunlock(lock);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ rw_runlock(&pvh_global_lock);
+}
+
+static __inline boolean_t
+safe_to_clear_referenced(pmap_t pmap, pt_entry_t pte)
+{
+
+ return (FALSE);
+}
+
+#define PMAP_TS_REFERENCED_MAX 5
+
+/*
+ * pmap_ts_referenced:
+ *
+ * Return a count of reference bits for a page, clearing those bits.
+ * It is not necessary for every reference bit to be cleared, but it
+ * is necessary that 0 only be returned when there are truly no
+ * reference bits set.
+ *
+ * XXX: The exact number of bits to check and clear is a matter that
+ * should be tested and standardized at some point in the future for
+ * optimal aging of shared pages.
+ */
+int
+pmap_ts_referenced(vm_page_t m)
+{
+ pv_entry_t pv, pvf;
+ pmap_t pmap;
+ struct rwlock *lock;
+ pd_entry_t *l2;
+ pt_entry_t *l3;
+ vm_paddr_t pa;
+ int cleared, md_gen, not_cleared;
+ struct spglist free;
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_ts_referenced: page %p is not managed", m));
+ SLIST_INIT(&free);
+ cleared = 0;
+ pa = VM_PAGE_TO_PHYS(m);
+ lock = PHYS_TO_PV_LIST_LOCK(pa);
+ rw_rlock(&pvh_global_lock);
+ rw_wlock(lock);
+retry:
+ not_cleared = 0;
+ if ((pvf = TAILQ_FIRST(&m->md.pv_list)) == NULL)
+ goto out;
+ pv = pvf;
+ do {
+ if (pvf == NULL)
+ pvf = pv;
+ pmap = PV_PMAP(pv);
+ if (!PMAP_TRYLOCK(pmap)) {
+ md_gen = m->md.pv_gen;
+ rw_wunlock(lock);
+ PMAP_LOCK(pmap);
+ rw_wlock(lock);
+ if (md_gen != m->md.pv_gen) {
+ PMAP_UNLOCK(pmap);
+ goto retry;
+ }
+ }
+ l2 = pmap_l2(pmap, pv->pv_va);
+
+ KASSERT((pmap_load(l2) & PTE_TYPE_M) == (PTE_TYPE_PTR << PTE_TYPE_S),
+ ("pmap_ts_referenced: found an invalid l2 table"));
+
+ l3 = pmap_l2_to_l3(l2, pv->pv_va);
+ if ((pmap_load(l3) & PTE_REF) != 0) {
+ if (safe_to_clear_referenced(pmap, pmap_load(l3))) {
+ /*
+ * TODO: We don't handle the access flag
+ * at all. We need to be able to set it in
+ * the exception handler.
+ */
+ panic("RISCVTODO: safe_to_clear_referenced\n");
+ } else if ((pmap_load(l3) & PTE_SW_WIRED) == 0) {
+ /*
+ * Wired pages cannot be paged out so
+ * doing accessed bit emulation for
+ * them is wasted effort. We do the
+ * hard work for unwired pages only.
+ */
+ pmap_remove_l3(pmap, l3, pv->pv_va,
+ pmap_load(l2), &free, &lock);
+ pmap_invalidate_page(pmap, pv->pv_va);
+ cleared++;
+ if (pvf == pv)
+ pvf = NULL;
+ pv = NULL;
+ KASSERT(lock == VM_PAGE_TO_PV_LIST_LOCK(m),
+ ("inconsistent pv lock %p %p for page %p",
+ lock, VM_PAGE_TO_PV_LIST_LOCK(m), m));
+ } else
+ not_cleared++;
+ }
+ PMAP_UNLOCK(pmap);
+ /* Rotate the PV list if it has more than one entry. */
+ if (pv != NULL && TAILQ_NEXT(pv, pv_next) != NULL) {
+ TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
+ TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
+ m->md.pv_gen++;
+ }
+ } while ((pv = TAILQ_FIRST(&m->md.pv_list)) != pvf && cleared +
+ not_cleared < PMAP_TS_REFERENCED_MAX);
+out:
+ rw_wunlock(lock);
+ rw_runlock(&pvh_global_lock);
+ pmap_free_zero_pages(&free);
+ return (cleared + not_cleared);
+}
+
+/*
+ * Apply the given advice to the specified range of addresses within the
+ * given pmap. Depending on the advice, clear the referenced and/or
+ * modified flags in each mapping and set the mapped page's dirty field.
+ */
+void
+pmap_advise(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, int advice)
+{
+}
+
+/*
+ * Clear the modify bits on the specified physical page.
+ */
+void
+pmap_clear_modify(vm_page_t m)
+{
+
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+ ("pmap_clear_modify: page %p is not managed", m));
+ VM_OBJECT_ASSERT_WLOCKED(m->object);
+ KASSERT(!vm_page_xbusied(m),
+ ("pmap_clear_modify: page %p is exclusive busied", m));
+
+ /*
+ * If the page is not PGA_WRITEABLE, then no PTEs can have PG_M set.
+ * If the object containing the page is locked and the page is not
+ * exclusive busied, then PGA_WRITEABLE cannot be concurrently set.
+ */
+ if ((m->aflags & PGA_WRITEABLE) == 0)
+ return;
+
+ /* RISCVTODO: We lack support for tracking if a page is modified */
+}
+
+void *
+pmap_mapbios(vm_paddr_t pa, vm_size_t size)
+{
+
+ return ((void *)PHYS_TO_DMAP(pa));
+}
+
+void
+pmap_unmapbios(vm_paddr_t pa, vm_size_t size)
+{
+}
+
+/*
+ * Sets the memory attribute for the specified page.
+ */
+void
+pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma)
+{
+
+ m->md.pv_memattr = ma;
+
+ /*
+ * RISCVTODO: Implement the below (from the amd64 pmap)
+ * If "m" is a normal page, update its direct mapping. This update
+ * can be relied upon to perform any cache operations that are
+ * required for data coherence.
+ */
+ if ((m->flags & PG_FICTITIOUS) == 0 &&
+ PHYS_IN_DMAP(VM_PAGE_TO_PHYS(m)))
+ panic("RISCVTODO: pmap_page_set_memattr");
+}
+
+/*
+ * perform the pmap work for mincore
+ */
+int
+pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *locked_pa)
+{
+
+ panic("RISCVTODO: pmap_mincore");
+}
+
+void
+pmap_activate(struct thread *td)
+{
+ uint64_t entry;
+ uint64_t pn;
+ pmap_t pmap;
+
+ critical_enter();
+ pmap = vmspace_pmap(td->td_proc->p_vmspace);
+ td->td_pcb->pcb_l1addr = vtophys(pmap->pm_l1);
+
+ pn = (td->td_pcb->pcb_l1addr / PAGE_SIZE);
+ entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S));
+ entry |= (pn << PTE_PPN0_S);
+ pmap_load_store(&pagetable_l0, entry);
+
+ pmap_invalidate_all(pmap);
+ critical_exit();
+}
+
+void
+pmap_sync_icache(pmap_t pm, vm_offset_t va, vm_size_t sz)
+{
+
+ panic("RISCVTODO: pmap_sync_icache");
+}
+
+/*
+ * Increase the starting virtual address of the given mapping if a
+ * different alignment might result in more superpage mappings.
+ */
+void
+pmap_align_superpage(vm_object_t object, vm_ooffset_t offset,
+ vm_offset_t *addr, vm_size_t size)
+{
+}
+
+/**
+ * Get the kernel virtual address of a set of physical pages. If there are
+ * physical addresses not covered by the DMAP perform a transient mapping
+ * that will be removed when calling pmap_unmap_io_transient.
+ *
+ * \param page The pages the caller wishes to obtain the virtual
+ * address on the kernel memory map.
+ * \param vaddr On return contains the kernel virtual memory address
+ * of the pages passed in the page parameter.
+ * \param count Number of pages passed in.
+ * \param can_fault TRUE if the thread using the mapped pages can take
+ * page faults, FALSE otherwise.
+ *
+ * \returns TRUE if the caller must call pmap_unmap_io_transient when
+ * finished or FALSE otherwise.
+ *
+ */
+boolean_t
+pmap_map_io_transient(vm_page_t page[], vm_offset_t vaddr[], int count,
+ boolean_t can_fault)
+{
+ vm_paddr_t paddr;
+ boolean_t needs_mapping;
+ int error, i;
+
+ /*
+ * Allocate any KVA space that we need, this is done in a separate
+ * loop to prevent calling vmem_alloc while pinned.
+ */
+ needs_mapping = FALSE;
+ for (i = 0; i < count; i++) {
+ paddr = VM_PAGE_TO_PHYS(page[i]);
+ if (__predict_false(paddr >= DMAP_MAX_PHYSADDR)) {
+ error = vmem_alloc(kernel_arena, PAGE_SIZE,
+ M_BESTFIT | M_WAITOK, &vaddr[i]);
+ KASSERT(error == 0, ("vmem_alloc failed: %d", error));
+ needs_mapping = TRUE;
+ } else {
+ vaddr[i] = PHYS_TO_DMAP(paddr);
+ }
+ }
+
+ /* Exit early if everything is covered by the DMAP */
+ if (!needs_mapping)
+ return (FALSE);
+
+ if (!can_fault)
+ sched_pin();
+ for (i = 0; i < count; i++) {
+ paddr = VM_PAGE_TO_PHYS(page[i]);
+ if (paddr >= DMAP_MAX_PHYSADDR) {
+ panic(
+ "pmap_map_io_transient: TODO: Map out of DMAP data");
+ }
+ }
+
+ return (needs_mapping);
+}
+
+void
+pmap_unmap_io_transient(vm_page_t page[], vm_offset_t vaddr[], int count,
+ boolean_t can_fault)
+{
+ vm_paddr_t paddr;
+ int i;
+
+ if (!can_fault)
+ sched_unpin();
+ for (i = 0; i < count; i++) {
+ paddr = VM_PAGE_TO_PHYS(page[i]);
+ if (paddr >= DMAP_MAX_PHYSADDR) {
+ panic("RISCVTODO: pmap_unmap_io_transient: Unmap data");
+ }
+ }
+}
diff --git a/sys/riscv/riscv/support.S b/sys/riscv/riscv/support.S
new file mode 100644
index 000000000000..59e2680fa33e
--- /dev/null
+++ b/sys/riscv/riscv/support.S
@@ -0,0 +1,295 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/setjmp.h>
+
+#include "assym.s"
+
+/*
+ * One of the fu* or su* functions failed, return -1.
+ */
+ENTRY(fsu_fault)
+ SET_FAULT_HANDLER(x0, a1) /* Reset the handler function */
+fsu_fault_nopcb:
+ li a0, -1
+ ret
+END(fsu_fault)
+
+/*
+ * int casueword32(volatile uint32_t *, uint32_t, uint32_t *, uint32_t)
+ */
+ENTRY(casueword32)
+ li a4, (VM_MAXUSER_ADDRESS-3)
+ bgt a0, a4, fsu_fault_nopcb
+ la a6, fsu_fault /* Load the fault handler */
+ SET_FAULT_HANDLER(a6, a4) /* And set it */
+1: lr.w a4, 0(a0) /* Load-exclusive the data */
+ bne a4, a1, 2f /* If not equal then exit */
+ sc.w a5, a3, 0(a0) /* Store the new data */
+ bnez a5, 1b /* Retry on failure */
+2: SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */
+ sw a4, 0(a2) /* Store the read data */
+ li a0, 0 /* Success */
+ ret /* Return */
+END(casueword32)
+
+/*
+ * int casueword(volatile u_long *, u_long, u_long *, u_long)
+ */
+ENTRY(casueword)
+ li a4, (VM_MAXUSER_ADDRESS-7)
+ bgt a0, a4, fsu_fault_nopcb
+ la a6, fsu_fault /* Load the fault handler */
+ SET_FAULT_HANDLER(a6, a4) /* And set it */
+1: lr.d a4, 0(a0) /* Load-exclusive the data */
+ bne a4, a1, 2f /* If not equal then exit */
+ sc.d a5, a3, 0(a0) /* Store the new data */
+ bnez a5, 1b /* Retry on failure */
+2: SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */
+ sd a4, 0(a2) /* Store the read data */
+ li a0, 0 /* Success */
+ ret /* Return */
+END(casueword)
+
+/*
+ * int fubyte(volatile const void *)
+ */
+ENTRY(fubyte)
+ li a1, VM_MAXUSER_ADDRESS
+ bgt a0, a1, fsu_fault_nopcb
+ la a6, fsu_fault /* Load the fault handler */
+ SET_FAULT_HANDLER(a6, a1) /* And set it */
+ lb a0, 0(a0) /* Try loading the data */
+ SET_FAULT_HANDLER(x0, a1) /* Reset the fault handler */
+ ret /* Return */
+END(fubyte)
+
+/*
+ * int fuword(volatile const void *)
+ */
+ENTRY(fuword16)
+ li a1, (VM_MAXUSER_ADDRESS-1)
+ bgt a0, a1, fsu_fault_nopcb
+ la a6, fsu_fault /* Load the fault handler */
+ SET_FAULT_HANDLER(a6, a1) /* And set it */
+ lh a0, 0(a0) /* Try loading the data */
+ SET_FAULT_HANDLER(x0, a1) /* Reset the fault handler */
+ ret /* Return */
+END(fuword16)
+
+/*
+ * int32_t fueword32(volatile const void *, int32_t *)
+ */
+ENTRY(fueword32)
+ li a2, (VM_MAXUSER_ADDRESS-3)
+ bgt a0, a2, fsu_fault_nopcb
+ la a6, fsu_fault /* Load the fault handler */
+ SET_FAULT_HANDLER(a6, a2) /* And set it */
+ lw a0, 0(a0) /* Try loading the data */
+ SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
+ sw a0, 0(a1) /* Save the data in kernel space */
+ li a0, 0 /* Success */
+ ret /* Return */
+END(fueword32)
+
+/*
+ * long fueword(volatile const void *, int64_t *)
+ * int64_t fueword64(volatile const void *, int64_t *)
+ */
+ENTRY(fueword)
+EENTRY(fueword64)
+ li a2, (VM_MAXUSER_ADDRESS-7)
+ bgt a0, a2, fsu_fault_nopcb
+ la a6, fsu_fault /* Load the fault handler */
+ SET_FAULT_HANDLER(a6, a2) /* And set it */
+ ld a0, 0(a0) /* Try loading the data */
+ SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
+ sd a0, 0(a1) /* Save the data in kernel space */
+ li a0, 0 /* Success */
+ ret /* Return */
+EEND(fueword64)
+END(fueword)
+
+/*
+ * int subyte(volatile void *, int)
+ */
+ENTRY(subyte)
+ li a2, VM_MAXUSER_ADDRESS
+ bgt a0, a2, fsu_fault_nopcb
+ la a6, fsu_fault /* Load the fault handler */
+ SET_FAULT_HANDLER(a6, a2) /* And set it */
+ sb a1, 0(a0) /* Try storing the data */
+ SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
+ li a0, 0 /* Success */
+ ret /* Return */
+END(subyte)
+
+/*
+ * int suword16(volatile void *, int)
+ */
+ENTRY(suword16)
+ li a2, (VM_MAXUSER_ADDRESS-1)
+ bgt a0, a2, fsu_fault_nopcb
+ la a6, fsu_fault /* Load the fault handler */
+ SET_FAULT_HANDLER(a6, a2) /* And set it */
+ sh a1, 0(a0) /* Try storing the data */
+ SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
+ li a0, 0 /* Success */
+ ret /* Return */
+END(suword16)
+
+/*
+ * int suword32(volatile void *, int)
+ */
+ENTRY(suword32)
+ li a2, (VM_MAXUSER_ADDRESS-3)
+ bgt a0, a2, fsu_fault_nopcb
+ la a6, fsu_fault /* Load the fault handler */
+ SET_FAULT_HANDLER(a6, a2) /* And set it */
+ sw a1, 0(a0) /* Try storing the data */
+ SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
+ li a0, 0 /* Success */
+ ret /* Return */
+END(suword32)
+
+/*
+ * int suword(volatile void *, long)
+ */
+ENTRY(suword)
+EENTRY(suword64)
+ li a2, (VM_MAXUSER_ADDRESS-7)
+ bgt a0, a2, fsu_fault_nopcb
+ la a6, fsu_fault /* Load the fault handler */
+ SET_FAULT_HANDLER(a6, a2) /* And set it */
+ sd a1, 0(a0) /* Try storing the data */
+ SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
+ li a0, 0 /* Success */
+ ret /* Return */
+EEND(suword64)
+END(suword)
+
+/*
+ * fuswintr and suswintr are just like fusword and susword except that if
+ * the page is not in memory or would cause a trap, then we return an error.
+ * The important thing is to prevent sleep() and switch().
+ */
+
+/*
+ * Special handler so the trap code knows not to sleep.
+ */
+ENTRY(fsu_intr_fault)
+ SET_FAULT_HANDLER(x0, a1) /* Reset the handler function */
+ li a0, -1
+ ret
+END(fsu_fault)
+
+/*
+ * int fuswintr(void *)
+ */
+ENTRY(fuswintr)
+ li a1, (VM_MAXUSER_ADDRESS-3)
+ bgt a0, a1, fsu_fault_nopcb
+ la a6, fsu_intr_fault /* Load the fault handler */
+ SET_FAULT_HANDLER(a6, a1) /* And set it */
+ lw a0, 0(a0) /* Try loading the data */
+ SET_FAULT_HANDLER(x0, x1) /* Reset the fault handler */
+ ret /* Return */
+END(fuswintr)
+
+/*
+ * int suswintr(void *base, int word)
+ */
+ENTRY(suswintr)
+ li a2, (VM_MAXUSER_ADDRESS-3)
+ bgt a0, a2, fsu_fault_nopcb
+ la a6, fsu_intr_fault /* Load the fault handler */
+ SET_FAULT_HANDLER(a6, a2) /* And set it */
+ sw a1, 0(a0) /* Try storing the data */
+ SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
+ li a0, 0 /* Success */
+ ret /* Return */
+END(suswintr)
+
+ENTRY(setjmp)
+ /* Store the stack pointer */
+ sd sp, 0(a0)
+ addi a0, a0, 8
+
+ /* Store the general purpose registers and ra */
+ sd s0, (0 * 8)(a0)
+ sd s1, (1 * 8)(a0)
+ sd s2, (2 * 8)(a0)
+ sd s3, (3 * 8)(a0)
+ sd s4, (4 * 8)(a0)
+ sd s5, (5 * 8)(a0)
+ sd s6, (6 * 8)(a0)
+ sd s7, (7 * 8)(a0)
+ sd s8, (8 * 8)(a0)
+ sd s9, (9 * 8)(a0)
+ sd s10, (10 * 8)(a0)
+ sd s11, (11 * 8)(a0)
+ sd ra, (12 * 8)(a0)
+
+ /* Return value */
+ li a0, 0
+ ret
+END(setjmp)
+
+ENTRY(longjmp)
+ /* Restore the stack pointer */
+ ld sp, 0(a0)
+ addi a0, a0, 8
+
+ /* Restore the general purpose registers and ra */
+ ld s0, (0 * 8)(a0)
+ ld s1, (1 * 8)(a0)
+ ld s2, (2 * 8)(a0)
+ ld s3, (3 * 8)(a0)
+ ld s4, (4 * 8)(a0)
+ ld s5, (5 * 8)(a0)
+ ld s6, (6 * 8)(a0)
+ ld s7, (7 * 8)(a0)
+ ld s8, (8 * 8)(a0)
+ ld s9, (9 * 8)(a0)
+ ld s10, (10 * 8)(a0)
+ ld s11, (11 * 8)(a0)
+ ld ra, (12 * 8)(a0)
+
+ /* Load the return value */
+ mv a0, a1
+ ret
+END(longjmp)
diff --git a/sys/riscv/riscv/swtch.S b/sys/riscv/riscv/swtch.S
new file mode 100644
index 000000000000..c6336a968d15
--- /dev/null
+++ b/sys/riscv/riscv/swtch.S
@@ -0,0 +1,271 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "assym.s"
+#include "opt_sched.h"
+
+#include <machine/param.h>
+#include <machine/asm.h>
+#include <machine/riscvreg.h>
+#include <machine/pte.h>
+
+__FBSDID("$FreeBSD$");
+
+/*
+ * void cpu_throw(struct thread *old, struct thread *new)
+ */
+ENTRY(cpu_throw)
+ /* Store the new curthread */
+ sd a1, PC_CURTHREAD(gp)
+ /* And the new pcb */
+ ld x13, TD_PCB(a1)
+ sd x13, PC_CURPCB(gp)
+
+ sfence.vm
+
+ /* Switch to the new pmap */
+ la t0, pagetable_l0
+ ld t1, PCB_L1ADDR(x13) /* Link to next level PN */
+ srli t1, t1, PAGE_SHIFT /* PN no */
+ li t2, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S))
+ slli t3, t1, PTE_PPN0_S /* (t1 << PTE_PPN0_S) */
+ or t4, t2, t3
+ /* Store single level0 PTE entry to position */
+ sd t4, 0(t0)
+
+ /* TODO: Invalidate the TLB */
+
+ sfence.vm
+
+ /* Load registers */
+ ld ra, (PCB_RA)(x13)
+ ld sp, (PCB_SP)(x13)
+
+ /* s[0-11] */
+ ld s0, (PCB_S + 0 * 8)(x13)
+ ld s1, (PCB_S + 1 * 8)(x13)
+ ld s2, (PCB_S + 2 * 8)(x13)
+ ld s3, (PCB_S + 3 * 8)(x13)
+ ld s4, (PCB_S + 4 * 8)(x13)
+ ld s5, (PCB_S + 5 * 8)(x13)
+ ld s6, (PCB_S + 6 * 8)(x13)
+ ld s7, (PCB_S + 7 * 8)(x13)
+ ld s8, (PCB_S + 8 * 8)(x13)
+ ld s9, (PCB_S + 9 * 8)(x13)
+ ld s10, (PCB_S + 10 * 8)(x13)
+ ld s11, (PCB_S + 11 * 8)(x13)
+ ret
+
+.Lcpu_throw_panic_str:
+ .asciz "cpu_throw: %p\0"
+END(cpu_throw)
+
+/*
+ * void cpu_switch(struct thread *old, struct thread *new, struct mtx *mtx)
+ *
+ * a0 = old
+ * a1 = new
+ * a2 = mtx
+ * x3 to x7, x16 and x17 are caller saved
+ */
+ENTRY(cpu_switch)
+ /* Store the new curthread */
+ sd a1, PC_CURTHREAD(gp)
+ /* And the new pcb */
+ ld x13, TD_PCB(a1)
+ sd x13, PC_CURPCB(gp)
+
+ /* Save the old context. */
+ ld x13, TD_PCB(a0)
+
+ /* Store the callee-saved registers */
+ sd ra, (PCB_RA)(x13)
+ sd sp, (PCB_SP)(x13)
+
+ /* We use these in fork_trampoline */
+ sd t0, (PCB_T + 0 * 8)(x13)
+ sd t1, (PCB_T + 1 * 8)(x13)
+
+ /* s[0-11] */
+ sd s0, (PCB_S + 0 * 8)(x13)
+ sd s1, (PCB_S + 1 * 8)(x13)
+ sd s2, (PCB_S + 2 * 8)(x13)
+ sd s3, (PCB_S + 3 * 8)(x13)
+ sd s4, (PCB_S + 4 * 8)(x13)
+ sd s5, (PCB_S + 5 * 8)(x13)
+ sd s6, (PCB_S + 6 * 8)(x13)
+ sd s7, (PCB_S + 7 * 8)(x13)
+ sd s8, (PCB_S + 8 * 8)(x13)
+ sd s9, (PCB_S + 9 * 8)(x13)
+ sd s10, (PCB_S + 10 * 8)(x13)
+ sd s11, (PCB_S + 11 * 8)(x13)
+
+ /*
+ * Restore the saved context.
+ */
+ ld x13, TD_PCB(a1)
+
+ /*
+ * TODO: We may need to flush the cache here if switching
+ * to a user process.
+ */
+
+ sfence.vm
+
+ /* Switch to the new pmap */
+ la t0, pagetable_l0
+ ld t1, PCB_L1ADDR(x13) /* Link to next level PN */
+ srli t1, t1, PAGE_SHIFT /* PN no */
+ li t2, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S))
+ slli t3, t1, PTE_PPN0_S /* (t1 << PTE_PPN0_S) */
+ or t4, t2, t3
+ /* Store single level0 PTE entry to position */
+ sd t4, 0(t0)
+
+ /* TODO: Invalidate the TLB */
+
+ sfence.vm
+
+ /* Release the old thread */
+ sd a2, TD_LOCK(a0)
+#if defined(SCHED_ULE) && defined(SMP)
+ /* TODO */
+#endif
+
+ /* Restore the registers */
+ ld ra, (PCB_RA)(x13)
+ ld sp, (PCB_SP)(x13)
+
+ /* We use these in fork_trampoline */
+ ld t0, (PCB_T + 0 * 8)(x13)
+ ld t1, (PCB_T + 1 * 8)(x13)
+
+ /* s[0-11] */
+ ld s0, (PCB_S + 0 * 8)(x13)
+ ld s1, (PCB_S + 1 * 8)(x13)
+ ld s2, (PCB_S + 2 * 8)(x13)
+ ld s3, (PCB_S + 3 * 8)(x13)
+ ld s4, (PCB_S + 4 * 8)(x13)
+ ld s5, (PCB_S + 5 * 8)(x13)
+ ld s6, (PCB_S + 6 * 8)(x13)
+ ld s7, (PCB_S + 7 * 8)(x13)
+ ld s8, (PCB_S + 8 * 8)(x13)
+ ld s9, (PCB_S + 9 * 8)(x13)
+ ld s10, (PCB_S + 10 * 8)(x13)
+ ld s11, (PCB_S + 11 * 8)(x13)
+ ret
+.Lcpu_switch_panic_str:
+ .asciz "cpu_switch: %p\0"
+END(cpu_switch)
+
+/*
+ * fork_exit(void (*callout)(void *, struct trapframe *), void *arg,
+ * struct trapframe *frame)
+ */
+
+ENTRY(fork_trampoline)
+ mv a0, x5
+ mv a1, x6
+ mv a2, sp
+ call _C_LABEL(fork_exit)
+
+ /* Restore sstatus */
+ ld t0, (TF_SSTATUS)(sp)
+ /* Ensure interrupts disabled */
+ li t1, ~SSTATUS_IE
+ and t0, t0, t1
+ csrw sstatus, t0
+
+ /* Restore exception program counter */
+ ld t0, (TF_SEPC)(sp)
+ csrw sepc, t0
+
+ /* Restore the registers */
+ ld t0, (TF_T + 0 * 8)(sp)
+ ld t1, (TF_T + 1 * 8)(sp)
+ ld t2, (TF_T + 2 * 8)(sp)
+ ld t3, (TF_T + 3 * 8)(sp)
+ ld t4, (TF_T + 4 * 8)(sp)
+ ld t5, (TF_T + 5 * 8)(sp)
+ ld t6, (TF_T + 6 * 8)(sp)
+
+ ld s0, (TF_S + 0 * 8)(sp)
+ ld s1, (TF_S + 1 * 8)(sp)
+ ld s2, (TF_S + 2 * 8)(sp)
+ ld s3, (TF_S + 3 * 8)(sp)
+ ld s4, (TF_S + 4 * 8)(sp)
+ ld s5, (TF_S + 5 * 8)(sp)
+ ld s6, (TF_S + 6 * 8)(sp)
+ ld s7, (TF_S + 7 * 8)(sp)
+ ld s8, (TF_S + 8 * 8)(sp)
+ ld s9, (TF_S + 9 * 8)(sp)
+ ld s10, (TF_S + 10 * 8)(sp)
+ ld s11, (TF_S + 11 * 8)(sp)
+
+ ld a0, (TF_A + 0 * 8)(sp)
+ ld a1, (TF_A + 1 * 8)(sp)
+ ld a2, (TF_A + 2 * 8)(sp)
+ ld a3, (TF_A + 3 * 8)(sp)
+ ld a4, (TF_A + 4 * 8)(sp)
+ ld a5, (TF_A + 5 * 8)(sp)
+ ld a6, (TF_A + 6 * 8)(sp)
+ ld a7, (TF_A + 7 * 8)(sp)
+
+ /* Load user ra and sp */
+ ld tp, (TF_TP)(sp)
+ ld ra, (TF_RA)(sp)
+
+ /*
+ * Store our pcpup on stack, we will load it back
+ * on kernel mode trap.
+ */
+ sd gp, (TF_SIZE)(sp)
+ ld gp, (TF_GP)(sp)
+
+ /* Save kernel stack so we can use it doing a user trap */
+ addi sp, sp, TF_SIZE
+ csrw sscratch, sp
+
+ /* Load user stack */
+ ld sp, (TF_SP - TF_SIZE)(sp)
+
+ eret
+END(fork_trampoline)
+
+ENTRY(savectx)
+ la a0, .Lsavectx_panic_str
+ call panic
+.Lsavectx_panic_str:
+ .asciz "savectx_panic: %p\0"
+END(savectx)
diff --git a/sys/riscv/riscv/sys_machdep.c b/sys/riscv/riscv/sys_machdep.c
new file mode 100644
index 000000000000..8fdc7dbe0aaf
--- /dev/null
+++ b/sys/riscv/riscv/sys_machdep.c
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+
+#include <machine/sysarch.h>
+
+int
+sysarch(struct thread *td, struct sysarch_args *uap)
+{
+
+ return (ENOTSUP);
+}
diff --git a/sys/riscv/riscv/timer.c b/sys/riscv/riscv/timer.c
new file mode 100644
index 000000000000..e3f3f22579a1
--- /dev/null
+++ b/sys/riscv/riscv/timer.c
@@ -0,0 +1,298 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * RISC-V Timer
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <sys/proc.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/asm.h>
+#include <machine/trap.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#define DEFAULT_FREQ 1000000
+
+struct riscv_tmr_softc {
+ struct resource *res[1];
+ void *ihl[1];
+ uint32_t clkfreq;
+ struct eventtimer et;
+};
+
+static struct riscv_tmr_softc *riscv_tmr_sc = NULL;
+
+static struct resource_spec timer_spec[] = {
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static timecounter_get_t riscv_tmr_get_timecount;
+
+static struct timecounter riscv_tmr_timecount = {
+ .tc_name = "RISC-V Timecounter",
+ .tc_get_timecount = riscv_tmr_get_timecount,
+ .tc_poll_pps = NULL,
+ .tc_counter_mask = ~0u,
+ .tc_frequency = 0,
+ .tc_quality = 1000,
+};
+
+static long
+get_counts(void)
+{
+
+ return (csr_read(stime));
+}
+
+static unsigned
+riscv_tmr_get_timecount(struct timecounter *tc)
+{
+
+ return (get_counts());
+}
+
+static int
+riscv_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
+{
+ struct riscv_tmr_softc *sc;
+ int counts;
+
+ sc = (struct riscv_tmr_softc *)et->et_priv;
+
+ if (first != 0) {
+ counts = ((uint32_t)et->et_frequency * first) >> 32;
+ machine_command(ECALL_MTIMECMP, counts);
+ return (0);
+ }
+
+ return (EINVAL);
+
+}
+
+static int
+riscv_tmr_stop(struct eventtimer *et)
+{
+ struct riscv_tmr_softc *sc;
+
+ sc = (struct riscv_tmr_softc *)et->et_priv;
+
+ /* TODO */
+
+ return (0);
+}
+
+static int
+riscv_tmr_intr(void *arg)
+{
+ struct riscv_tmr_softc *sc;
+
+ sc = (struct riscv_tmr_softc *)arg;
+
+ /*
+ * Clear interrupt pending bit.
+ * Note sip register is unimplemented in Spike simulator,
+ * so use machine command to clear in mip.
+ */
+ machine_command(ECALL_CLEAR_PENDING, 0);
+
+ if (sc->et.et_active)
+ sc->et.et_event_cb(&sc->et, sc->et.et_arg);
+
+ return (FILTER_HANDLED);
+}
+
+static int
+riscv_tmr_fdt_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "riscv,timer")) {
+ device_set_desc(dev, "RISC-V Timer");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+riscv_tmr_attach(device_t dev)
+{
+ struct riscv_tmr_softc *sc;
+ phandle_t node;
+ pcell_t clock;
+ int error;
+
+ sc = device_get_softc(dev);
+ if (riscv_tmr_sc)
+ return (ENXIO);
+
+ /* Get the base clock frequency */
+ node = ofw_bus_get_node(dev);
+ if (node > 0) {
+ error = OF_getprop(node, "clock-frequency", &clock,
+ sizeof(clock));
+ if (error > 0) {
+ sc->clkfreq = fdt32_to_cpu(clock);
+ }
+ }
+
+ if (sc->clkfreq == 0)
+ sc->clkfreq = DEFAULT_FREQ;
+
+ if (sc->clkfreq == 0) {
+ device_printf(dev, "No clock frequency specified\n");
+ return (ENXIO);
+ }
+
+ if (bus_alloc_resources(dev, timer_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ riscv_tmr_sc = sc;
+
+ /* Setup IRQs handler */
+ error = bus_setup_intr(dev, sc->res[0], INTR_TYPE_CLK,
+ riscv_tmr_intr, NULL, sc, &sc->ihl[0]);
+ if (error) {
+ device_printf(dev, "Unable to alloc int resource.\n");
+ return (ENXIO);
+ }
+
+ riscv_tmr_timecount.tc_frequency = sc->clkfreq;
+ tc_init(&riscv_tmr_timecount);
+
+ sc->et.et_name = "RISC-V Eventtimer";
+ sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU;
+ sc->et.et_quality = 1000;
+
+ sc->et.et_frequency = sc->clkfreq;
+ sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
+ sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
+ sc->et.et_start = riscv_tmr_start;
+ sc->et.et_stop = riscv_tmr_stop;
+ sc->et.et_priv = sc;
+ et_register(&sc->et);
+
+ return (0);
+}
+
+static device_method_t riscv_tmr_fdt_methods[] = {
+ DEVMETHOD(device_probe, riscv_tmr_fdt_probe),
+ DEVMETHOD(device_attach, riscv_tmr_attach),
+ { 0, 0 }
+};
+
+static driver_t riscv_tmr_fdt_driver = {
+ "timer",
+ riscv_tmr_fdt_methods,
+ sizeof(struct riscv_tmr_softc),
+};
+
+static devclass_t riscv_tmr_fdt_devclass;
+
+EARLY_DRIVER_MODULE(timer, simplebus, riscv_tmr_fdt_driver, riscv_tmr_fdt_devclass,
+ 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
+EARLY_DRIVER_MODULE(timer, ofwbus, riscv_tmr_fdt_driver, riscv_tmr_fdt_devclass,
+ 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
+
+void
+DELAY(int usec)
+{
+ int32_t counts, counts_per_usec;
+ uint32_t first, last;
+
+ /*
+ * Check the timers are setup, if not just
+ * use a for loop for the meantime
+ */
+ if (riscv_tmr_sc == NULL) {
+ for (; usec > 0; usec--)
+ for (counts = 200; counts > 0; counts--)
+ /*
+ * Prevent the compiler from optimizing
+ * out the loop
+ */
+ cpufunc_nullop();
+ return;
+ }
+
+ /* Get the number of times to count */
+ counts_per_usec = ((riscv_tmr_timecount.tc_frequency / 1000000) + 1);
+
+ /*
+ * Clamp the timeout at a maximum value (about 32 seconds with
+ * a 66MHz clock). *Nobody* should be delay()ing for anywhere
+ * near that length of time and if they are, they should be hung
+ * out to dry.
+ */
+ if (usec >= (0x80000000U / counts_per_usec))
+ counts = (0x80000000U / counts_per_usec) - 1;
+ else
+ counts = usec * counts_per_usec;
+
+ first = get_counts();
+
+ while (counts > 0) {
+ last = get_counts();
+ counts -= (int32_t)(last - first);
+ first = last;
+ }
+}
diff --git a/sys/riscv/riscv/trap.c b/sys/riscv/riscv/trap.c
new file mode 100644
index 000000000000..c192b3135feb
--- /dev/null
+++ b/sys/riscv/riscv/trap.c
@@ -0,0 +1,311 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/pioctl.h>
+#include <sys/bus.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_map.h>
+#include <vm/vm_param.h>
+#include <vm/vm_extern.h>
+
+#include <machine/frame.h>
+#include <machine/pcb.h>
+#include <machine/pcpu.h>
+#include <machine/vmparam.h>
+
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+extern register_t fsu_intr_fault;
+
+/* Called from exception.S */
+void do_trap_supervisor(struct trapframe *);
+void do_trap_user(struct trapframe *);
+
+static __inline void
+call_trapsignal(struct thread *td, int sig, int code, void *addr)
+{
+ ksiginfo_t ksi;
+
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = sig;
+ ksi.ksi_code = code;
+ ksi.ksi_addr = addr;
+ trapsignal(td, &ksi);
+}
+
+int
+cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
+{
+ struct proc *p;
+ register_t *ap;
+ int nap;
+
+ nap = 8;
+ p = td->td_proc;
+ ap = &td->td_frame->tf_a[0];
+
+ sa->code = td->td_frame->tf_t[0];
+
+ if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
+ sa->code = *ap++;
+ nap--;
+ }
+
+ if (p->p_sysent->sv_mask)
+ sa->code &= p->p_sysent->sv_mask;
+ if (sa->code >= p->p_sysent->sv_size)
+ sa->callp = &p->p_sysent->sv_table[0];
+ else
+ sa->callp = &p->p_sysent->sv_table[sa->code];
+
+ sa->narg = sa->callp->sy_narg;
+ memcpy(sa->args, ap, nap * sizeof(register_t));
+ if (sa->narg > nap)
+ panic("TODO: Could we have more then 8 args?");
+
+ td->td_retval[0] = 0;
+ td->td_retval[1] = 0;
+
+ return (0);
+}
+
+#include "../../kern/subr_syscall.c"
+
+static void
+dump_regs(struct trapframe *frame)
+{
+ int n;
+ int i;
+
+ n = (sizeof(frame->tf_t) / sizeof(frame->tf_t[0]));
+ for (i = 0; i < n; i++)
+ printf("t[%d] == 0x%016lx\n", i, frame->tf_t[i]);
+
+ n = (sizeof(frame->tf_s) / sizeof(frame->tf_s[0]));
+ for (i = 0; i < n; i++)
+ printf("s[%d] == 0x%016lx\n", i, frame->tf_s[i]);
+
+ n = (sizeof(frame->tf_a) / sizeof(frame->tf_a[0]));
+ for (i = 0; i < n; i++)
+ printf("a[%d] == 0x%016lx\n", i, frame->tf_a[i]);
+
+ printf("sepc == 0x%016lx\n", frame->tf_sepc);
+ printf("sstatus == 0x%016lx\n", frame->tf_sstatus);
+}
+
+static void
+svc_handler(struct trapframe *frame)
+{
+ struct syscall_args sa;
+ struct thread *td;
+ int error;
+
+ td = curthread;
+ td->td_frame = frame;
+
+ error = syscallenter(td, &sa);
+ syscallret(td, error, &sa);
+}
+
+static void
+data_abort(struct trapframe *frame, int lower)
+{
+ struct vm_map *map;
+ uint64_t sbadaddr;
+ struct thread *td;
+ struct pcb *pcb;
+ vm_prot_t ftype;
+ vm_offset_t va;
+ struct proc *p;
+ int ucode;
+ int error;
+ int sig;
+
+ td = curthread;
+ pcb = td->td_pcb;
+
+ /*
+ * Special case for fuswintr and suswintr. These can't sleep so
+ * handle them early on in the trap handler.
+ */
+ if (__predict_false(pcb->pcb_onfault == (vm_offset_t)&fsu_intr_fault)) {
+ frame->tf_sepc = pcb->pcb_onfault;
+ return;
+ }
+
+ sbadaddr = frame->tf_sbadaddr;
+
+ p = td->td_proc;
+
+ if (lower)
+ map = &td->td_proc->p_vmspace->vm_map;
+ else {
+ /* The top bit tells us which range to use */
+ if ((sbadaddr >> 63) == 1)
+ map = kernel_map;
+ else
+ map = &td->td_proc->p_vmspace->vm_map;
+ }
+
+ va = trunc_page(sbadaddr);
+
+ if (frame->tf_scause == EXCP_STORE_ACCESS_FAULT) {
+ ftype = (VM_PROT_READ | VM_PROT_WRITE);
+ } else {
+ ftype = (VM_PROT_READ);
+ }
+
+ if (map != kernel_map) {
+ /*
+ * Keep swapout from messing with us during this
+ * critical time.
+ */
+ PROC_LOCK(p);
+ ++p->p_lock;
+ PROC_UNLOCK(p);
+
+ /* Fault in the user page: */
+ error = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
+
+ PROC_LOCK(p);
+ --p->p_lock;
+ PROC_UNLOCK(p);
+ } else {
+ /*
+ * Don't have to worry about process locking or stacks in the
+ * kernel.
+ */
+ error = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
+ }
+
+ if (error != KERN_SUCCESS) {
+ if (lower) {
+ sig = SIGSEGV;
+ if (error == KERN_PROTECTION_FAILURE)
+ ucode = SEGV_ACCERR;
+ else
+ ucode = SEGV_MAPERR;
+ call_trapsignal(td, sig, ucode, (void *)sbadaddr);
+ } else {
+ if (td->td_intr_nesting_level == 0 &&
+ pcb->pcb_onfault != 0) {
+ frame->tf_a[0] = error;
+ frame->tf_sepc = pcb->pcb_onfault;
+ return;
+ }
+ dump_regs(frame);
+ panic("vm_fault failed: %lx, va 0x%016lx",
+ frame->tf_sepc, sbadaddr);
+ }
+ }
+
+ if (lower)
+ userret(td, frame);
+}
+
+void
+do_trap_supervisor(struct trapframe *frame)
+{
+ uint64_t exception;
+
+ exception = (frame->tf_scause & EXCP_MASK);
+ if (frame->tf_scause & EXCP_INTR) {
+ /* Interrupt */
+ riscv_cpu_intr(frame);
+ return;
+ }
+
+ CTR3(KTR_TRAP, "do_trap_supervisor: curthread: %p, sepc: %lx, frame: %p",
+ curthread, frame->tf_sepc, frame);
+
+ switch(exception) {
+ case EXCP_LOAD_ACCESS_FAULT:
+ case EXCP_STORE_ACCESS_FAULT:
+ case EXCP_INSTR_ACCESS_FAULT:
+ data_abort(frame, 0);
+ break;
+ default:
+ dump_regs(frame);
+ panic("Unknown kernel exception %x badaddr %lx\n",
+ exception, frame->tf_sbadaddr);
+ }
+}
+
+void
+do_trap_user(struct trapframe *frame)
+{
+ uint64_t exception;
+
+ exception = (frame->tf_scause & EXCP_MASK);
+ if (frame->tf_scause & EXCP_INTR) {
+ /* Interrupt */
+ riscv_cpu_intr(frame);
+ return;
+ }
+
+ CTR3(KTR_TRAP, "do_trap_user: curthread: %p, sepc: %lx, frame: %p",
+ curthread, frame->tf_sepc, frame);
+
+ switch(exception) {
+ case EXCP_LOAD_ACCESS_FAULT:
+ case EXCP_STORE_ACCESS_FAULT:
+ case EXCP_INSTR_ACCESS_FAULT:
+ data_abort(frame, 1);
+ break;
+ case EXCP_UMODE_ENV_CALL:
+ frame->tf_sepc += 4; /* Next instruction */
+ svc_handler(frame);
+ break;
+ default:
+ dump_regs(frame);
+ panic("Unknown userland exception %x badaddr %lx\n",
+ exception, frame->tf_sbadaddr);
+ }
+}
diff --git a/sys/riscv/riscv/uio_machdep.c b/sys/riscv/riscv/uio_machdep.c
new file mode 100644
index 000000000000..e6f6d39f02be
--- /dev/null
+++ b/sys/riscv/riscv/uio_machdep.c
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 2004 Alan L. Cox <alc@cs.rice.edu>
+ * Copyright (c) 1982, 1986, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the 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.
+ *
+ * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+
+#include <machine/vmparam.h>
+
+/*
+ * Implement uiomove(9) from physical memory using the direct map to
+ * avoid the creation and destruction of ephemeral mappings.
+ */
+int
+uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
+{
+ struct thread *td = curthread;
+ struct iovec *iov;
+ void *cp;
+ vm_offset_t page_offset, vaddr;
+ size_t cnt;
+ int error = 0;
+ int save = 0;
+ boolean_t mapped;
+
+ KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
+ ("uiomove_fromphys: mode"));
+ KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
+ ("uiomove_fromphys proc"));
+ save = td->td_pflags & TDP_DEADLKTREAT;
+ td->td_pflags |= TDP_DEADLKTREAT;
+ mapped = FALSE;
+ while (n > 0 && uio->uio_resid) {
+ iov = uio->uio_iov;
+ cnt = iov->iov_len;
+ if (cnt == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ continue;
+ }
+ if (cnt > n)
+ cnt = n;
+ page_offset = offset & PAGE_MASK;
+ cnt = min(cnt, PAGE_SIZE - page_offset);
+ if (uio->uio_segflg != UIO_NOCOPY) {
+ mapped = pmap_map_io_transient(
+ &ma[offset >> PAGE_SHIFT], &vaddr, 1, TRUE);
+ cp = (char *)vaddr + page_offset;
+ }
+ switch (uio->uio_segflg) {
+ case UIO_USERSPACE:
+ maybe_yield();
+ if (uio->uio_rw == UIO_READ)
+ error = copyout(cp, iov->iov_base, cnt);
+ else
+ error = copyin(iov->iov_base, cp, cnt);
+ if (error)
+ goto out;
+ break;
+ case UIO_SYSSPACE:
+ if (uio->uio_rw == UIO_READ)
+ bcopy(cp, iov->iov_base, cnt);
+ else
+ bcopy(iov->iov_base, cp, cnt);
+ break;
+ case UIO_NOCOPY:
+ break;
+ }
+ if (__predict_false(mapped)) {
+ pmap_unmap_io_transient(&ma[offset >> PAGE_SHIFT],
+ &vaddr, 1, TRUE);
+ mapped = FALSE;
+ }
+ iov->iov_base = (char *)iov->iov_base + cnt;
+ iov->iov_len -= cnt;
+ uio->uio_resid -= cnt;
+ uio->uio_offset += cnt;
+ offset += cnt;
+ n -= cnt;
+ }
+out:
+ if (__predict_false(mapped)) {
+ panic("TODO 3");
+ pmap_unmap_io_transient(&ma[offset >> PAGE_SHIFT], &vaddr, 1,
+ TRUE);
+ }
+ if (save == 0)
+ td->td_pflags &= ~TDP_DEADLKTREAT;
+ return (error);
+}
diff --git a/sys/riscv/riscv/uma_machdep.c b/sys/riscv/riscv/uma_machdep.c
new file mode 100644
index 000000000000..b3f2d82be13c
--- /dev/null
+++ b/sys/riscv/riscv/uma_machdep.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2003 Alan L. Cox <alc@cs.rice.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+#include <vm/uma.h>
+#include <vm/uma_int.h>
+#include <machine/md_var.h>
+#include <machine/vmparam.h>
+
+void *
+uma_small_alloc(uma_zone_t zone, vm_size_t bytes, u_int8_t *flags, int wait)
+{
+
+ panic("uma_small_alloc");
+}
+
+void
+uma_small_free(void *mem, vm_size_t size, u_int8_t flags)
+{
+
+ panic("uma_small_free");
+}
diff --git a/sys/riscv/riscv/vm_machdep.c b/sys/riscv/riscv/vm_machdep.c
new file mode 100644
index 000000000000..fef626b9f2fa
--- /dev/null
+++ b/sys/riscv/riscv/vm_machdep.c
@@ -0,0 +1,260 @@
+/*-
+ * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/limits.h>
+#include <sys/proc.h>
+#include <sys/sf_buf.h>
+#include <sys/signal.h>
+#include <sys/unistd.h>
+#include <sys/taskqueue.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/uma.h>
+#include <vm/uma_int.h>
+
+#include <machine/riscvreg.h>
+#include <machine/cpu.h>
+#include <machine/pcb.h>
+#include <machine/frame.h>
+
+/*
+ * Finish a fork operation, with process p2 nearly set up.
+ * Copy and update the pcb, set up the stack so that the child
+ * ready to run and return to user mode.
+ */
+void
+cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
+{
+ struct pcb *pcb2;
+ struct trapframe *tf;
+ uint64_t val;
+
+ if ((flags & RFPROC) == 0)
+ return;
+
+ if (td1 == curthread) {
+ __asm __volatile("mv %0, tp" : "=&r"(val));
+ td1->td_pcb->pcb_tp = val;
+ }
+
+ pcb2 = (struct pcb *)(td2->td_kstack +
+ td2->td_kstack_pages * PAGE_SIZE) - 1;
+
+ td2->td_pcb = pcb2;
+ bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
+
+ td2->td_pcb->pcb_l1addr =
+ vtophys(vmspace_pmap(td2->td_proc->p_vmspace)->pm_l1);
+
+ tf = (struct trapframe *)STACKALIGN((struct trapframe *)pcb2 - 1);
+ bcopy(td1->td_frame, tf, sizeof(*tf));
+
+ /* Clear syscall error flag */
+ tf->tf_t[0] = 0;
+
+ /* Arguments for child */
+ tf->tf_a[0] = 0;
+ tf->tf_a[1] = 0;
+ tf->tf_sstatus = SSTATUS_PIE;
+
+ td2->td_frame = tf;
+
+ /* Set the return value registers for fork() */
+ td2->td_pcb->pcb_t[0] = (uintptr_t)fork_return;
+ td2->td_pcb->pcb_t[1] = (uintptr_t)td2;
+ td2->td_pcb->pcb_ra = (uintptr_t)fork_trampoline;
+ td2->td_pcb->pcb_sp = (uintptr_t)td2->td_frame;
+
+ /* Setup to release spin count in fork_exit(). */
+ td2->td_md.md_spinlock_count = 1;
+ td2->td_md.md_saved_sstatus_ie = 1;
+}
+
+void
+cpu_reset(void)
+{
+
+ printf("cpu_reset");
+ while(1)
+ __asm volatile("wfi" ::: "memory");
+}
+
+void
+cpu_thread_swapin(struct thread *td)
+{
+}
+
+void
+cpu_thread_swapout(struct thread *td)
+{
+}
+
+void
+cpu_set_syscall_retval(struct thread *td, int error)
+{
+ struct trapframe *frame;
+
+ frame = td->td_frame;
+
+ switch (error) {
+ case 0:
+ frame->tf_a[0] = td->td_retval[0];
+ frame->tf_a[1] = td->td_retval[1];
+ frame->tf_t[0] = 0; /* syscall succeeded */
+ break;
+ case ERESTART:
+ frame->tf_sepc -= 4; /* prev instruction */
+ break;
+ case EJUSTRETURN:
+ break;
+ default:
+ frame->tf_a[0] = error;
+ frame->tf_t[0] = 1; /* syscall error */
+ break;
+ }
+}
+
+/*
+ * Initialize machine state (pcb and trap frame) for a new thread about to
+ * upcall. Put enough state in the new thread's PCB to get it to go back
+ * userret(), where we can intercept it again to set the return (upcall)
+ * Address and stack, along with those from upcals that are from other sources
+ * such as those generated in thread_userret() itself.
+ */
+void
+cpu_set_upcall(struct thread *td, struct thread *td0)
+{
+
+ bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe));
+ bcopy(td0->td_pcb, td->td_pcb, sizeof(struct pcb));
+
+ td->td_pcb->pcb_t[0] = (uintptr_t)fork_return;
+ td->td_pcb->pcb_t[1] = (uintptr_t)td;
+ td->td_pcb->pcb_ra = (uintptr_t)fork_trampoline;
+ td->td_pcb->pcb_sp = (uintptr_t)td->td_frame;
+
+ /* Setup to release spin count in fork_exit(). */
+ td->td_md.md_spinlock_count = 1;
+ td->td_md.md_saved_sstatus_ie = 1;
+}
+
+/*
+ * Set that machine state for performing an upcall that has to
+ * be done in thread_userret() so that those upcalls generated
+ * in thread_userret() itself can be done as well.
+ */
+void
+cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
+ stack_t *stack)
+{
+ struct trapframe *tf = td->td_frame;
+
+ tf->tf_sp = STACKALIGN((uintptr_t)stack->ss_sp + stack->ss_size);
+ tf->tf_sepc = (register_t)entry;
+ tf->tf_a[0] = (register_t)arg;
+}
+
+int
+cpu_set_user_tls(struct thread *td, void *tls_base)
+{
+ struct pcb *pcb;
+
+ if ((uintptr_t)tls_base >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+
+ pcb = td->td_pcb;
+ pcb->pcb_tp = (register_t)tls_base;
+
+ return (0);
+}
+
+void
+cpu_thread_exit(struct thread *td)
+{
+}
+
+void
+cpu_thread_alloc(struct thread *td)
+{
+
+ td->td_pcb = (struct pcb *)(td->td_kstack +
+ td->td_kstack_pages * PAGE_SIZE) - 1;
+ td->td_frame = (struct trapframe *)STACKALIGN(
+ (caddr_t)td->td_pcb - 8 - sizeof(struct trapframe));
+}
+
+void
+cpu_thread_free(struct thread *td)
+{
+}
+
+void
+cpu_thread_clean(struct thread *td)
+{
+}
+
+/*
+ * Intercept the return address from a freshly forked process that has NOT
+ * been scheduled yet.
+ *
+ * This is needed to make kernel threads stay in kernel mode.
+ */
+void
+cpu_set_fork_handler(struct thread *td, void (*func)(void *), void *arg)
+{
+
+ td->td_pcb->pcb_t[0] = (uintptr_t)func;
+ td->td_pcb->pcb_t[1] = (uintptr_t)arg;
+ td->td_pcb->pcb_ra = (uintptr_t)fork_trampoline;
+ td->td_pcb->pcb_sp = (uintptr_t)td->td_frame;
+}
+
+void
+cpu_exit(struct thread *td)
+{
+}
+
+void
+swi_vm(void *v)
+{
+
+ /* Nothing to do here - busdma bounce buffers are not implemented. */
+}
diff --git a/sys/rpc/replay.c b/sys/rpc/replay.c
index 1bd5378d9fbe..3900a84d0f14 100644
--- a/sys/rpc/replay.c
+++ b/sys/rpc/replay.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/hash.h>
#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/queue.h>
diff --git a/sys/sparc64/sparc64/vm_machdep.c b/sys/sparc64/sparc64/vm_machdep.c
index df8be0b4e0c2..9780406ae0f0 100644
--- a/sys/sparc64/sparc64/vm_machdep.c
+++ b/sys/sparc64/sparc64/vm_machdep.c
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/unistd.h>
#include <sys/vmmeter.h>
+#include <sys/taskqueue.h>
#include <dev/ofw/openfirm.h>
diff --git a/sys/sys/ata.h b/sys/sys/ata.h
index 272b46a553d5..5df610e0da09 100644
--- a/sys/sys/ata.h
+++ b/sys/sys/ata.h
@@ -368,6 +368,9 @@ struct ata_params {
#define ATA_WRITE_LOG_EXT 0x3f
#define ATA_READ_VERIFY 0x40
#define ATA_READ_VERIFY48 0x42
+#define ATA_WRITE_UNCORRECTABLE48 0x45 /* write uncorrectable 48bit LBA */
+#define ATA_WU_PSEUDO 0x55 /* pseudo-uncorrectable error */
+#define ATA_WU_FLAGGED 0xaa /* flagged-uncorrectable error */
#define ATA_READ_LOG_DMA_EXT 0x47 /* read log DMA ext - PIO Data-In */
#define ATA_READ_FPDMA_QUEUED 0x60 /* read DMA NCQ */
#define ATA_WRITE_FPDMA_QUEUED 0x61 /* write DMA NCQ */
diff --git a/sys/sys/cdefs.h b/sys/sys/cdefs.h
index 59cc45f0e5fa..530359f6c1e4 100644
--- a/sys/sys/cdefs.h
+++ b/sys/sys/cdefs.h
@@ -776,7 +776,7 @@
#endif
#endif
-#if defined(__mips) || defined(__powerpc64__)
+#if defined(__mips) || defined(__powerpc64__) || defined(__riscv__)
#define __NO_TLS 1
#endif
diff --git a/sys/sys/event.h b/sys/sys/event.h
index 0f132318c827..7897c818cb0e 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -80,6 +80,7 @@ struct kevent {
#define EV_SYSFLAGS 0xF000 /* reserved by system */
#define EV_DROP 0x1000 /* note should be dropped */
#define EV_FLAG1 0x2000 /* filter-specific flag */
+#define EV_FLAG2 0x4000 /* filter-specific flag */
/* returned values */
#define EV_EOF 0x8000 /* EOF detected */
@@ -221,7 +222,7 @@ struct knote {
union {
struct file *p_fp; /* file data pointer */
struct proc *p_proc; /* proc pointer */
- struct aiocblist *p_aio; /* AIO job pointer */
+ struct kaiocb *p_aio; /* AIO job pointer */
struct aioliojob *p_lio; /* LIO job pointer */
sbintime_t *p_nexttime; /* next timer event fires at */
void *p_v; /* generic other pointer */
diff --git a/sys/sys/kerneldump.h b/sys/sys/kerneldump.h
index 763b7cd1c5aa..fd010181eb1d 100644
--- a/sys/sys/kerneldump.h
+++ b/sys/sys/kerneldump.h
@@ -72,6 +72,7 @@ struct kerneldumpheader {
#define KERNELDUMP_I386_VERSION 2
#define KERNELDUMP_MIPS_VERSION 1
#define KERNELDUMP_POWERPC_VERSION 1
+#define KERNELDUMP_RISCV_VERSION 1
#define KERNELDUMP_SPARC64_VERSION 1
#define KERNELDUMP_TEXT_VERSION 1
uint64_t dumplength; /* excl headers */
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index f2f4a9d17202..039fd394d34a 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -907,6 +907,16 @@ struct proc *pfind_locked(pid_t pid);
struct pgrp *pgfind(pid_t); /* Find process group by id. */
struct proc *zpfind(pid_t); /* Find zombie process by id. */
+struct fork_req {
+ int fr_flags;
+ int fr_pages;
+ int *fr_pidp;
+ struct proc **fr_procp;
+ int *fr_pd_fd;
+ int fr_pd_flags;
+ struct filecaps *fr_pd_fcaps;
+};
+
/*
* pget() flags.
*/
@@ -930,8 +940,7 @@ int enterpgrp(struct proc *p, pid_t pgid, struct pgrp *pgrp,
int enterthispgrp(struct proc *p, struct pgrp *pgrp);
void faultin(struct proc *p);
void fixjobc(struct proc *p, struct pgrp *pgrp, int entering);
-int fork1(struct thread *, int, int, struct proc **, int *, int,
- struct filecaps *);
+int fork1(struct thread *, struct fork_req *);
void fork_exit(void (*)(void *, struct trapframe *), void *,
struct trapframe *);
void fork_return(struct thread *, struct trapframe *);
diff --git a/sys/sys/socket.h b/sys/sys/socket.h
index ee621d9dd1e8..c20b07522c97 100644
--- a/sys/sys/socket.h
+++ b/sys/sys/socket.h
@@ -431,6 +431,7 @@ struct msghdr {
#define MSG_NBIO 0x4000 /* FIONBIO mode, used by fifofs */
#define MSG_COMPAT 0x8000 /* used in sendit() */
#define MSG_CMSG_CLOEXEC 0x40000 /* make received fds close-on-exec */
+#define MSG_WAITFORONE 0x80000 /* for recvmmsg() */
#endif
#ifdef _KERNEL
#define MSG_SOCALLBCK 0x10000 /* for use by socket callbacks - soreceive (TCP) */
@@ -596,6 +597,14 @@ struct sf_hdtr {
#define SFK_COMPAT 0x00000001
#define SF_READAHEAD(flags) ((flags) >> 16)
#endif /* _KERNEL */
+
+/*
+ * Sendmmsg/recvmmsg specific structure(s)
+ */
+struct mmsghdr {
+ struct msghdr msg_hdr; /* message header */
+ ssize_t msg_len; /* message length */
+};
#endif /* __BSD_VISIBLE */
#ifndef _KERNEL
@@ -618,12 +627,18 @@ int listen(int, int);
ssize_t recv(int, void *, size_t, int);
ssize_t recvfrom(int, void *, size_t, int, struct sockaddr * __restrict, socklen_t * __restrict);
ssize_t recvmsg(int, struct msghdr *, int);
+#if __BSD_VISIBLE
+struct timespec;
+ssize_t recvmmsg(int, struct mmsghdr * __restrict, size_t, int,
+ const struct timespec * __restrict);
+#endif
ssize_t send(int, const void *, size_t, int);
ssize_t sendto(int, const void *,
size_t, int, const struct sockaddr *, socklen_t);
ssize_t sendmsg(int, const struct msghdr *, int);
#if __BSD_VISIBLE
int sendfile(int, int, off_t, size_t, struct sf_hdtr *, off_t *, int);
+ssize_t sendmmsg(int, struct mmsghdr * __restrict, size_t, int);
int setfib(int);
#endif
int setsockopt(int, int, int, const void *, socklen_t);
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index 26cf9a6721ed..f101849eb92d 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -95,16 +95,16 @@ struct socket {
TAILQ_HEAD(, socket) so_incomp; /* (e) queue of partial unaccepted connections */
TAILQ_HEAD(, socket) so_comp; /* (e) queue of complete unaccepted connections */
TAILQ_ENTRY(socket) so_list; /* (e) list of unaccepted connections */
- u_short so_qlen; /* (e) number of unaccepted connections */
- u_short so_incqlen; /* (e) number of unaccepted incomplete
+ u_int so_qlen; /* (e) number of unaccepted connections */
+ u_int so_incqlen; /* (e) number of unaccepted incomplete
connections */
- u_short so_qlimit; /* (e) max number queued connections */
+ u_int so_qlimit; /* (e) max number queued connections */
short so_timeo; /* (g) connection timeout */
u_short so_error; /* (f) error affecting connection */
struct sigio *so_sigio; /* [sg] information for async I/O or
out of band data (SIGURG) */
u_long so_oobmark; /* (c) chars to oob mark */
- TAILQ_HEAD(, aiocblist) so_aiojobq; /* AIO ops waiting on socket */
+ TAILQ_HEAD(, kaiocb) so_aiojobq; /* AIO ops waiting on socket */
struct sockbuf so_rcv, so_snd;
@@ -172,9 +172,9 @@ struct xsocket {
caddr_t so_pcb; /* another convenient handle */
int xso_protocol;
int xso_family;
- u_short so_qlen;
- u_short so_incqlen;
- u_short so_qlimit;
+ u_int so_qlen;
+ u_int so_incqlen;
+ u_int so_qlimit;
short so_timeo;
u_short so_error;
pid_t so_pgid;
diff --git a/sys/tools/embed_mfs.sh b/sys/tools/embed_mfs.sh
index 785cf3f81bc0..3f20257b7a58 100644
--- a/sys/tools/embed_mfs.sh
+++ b/sys/tools/embed_mfs.sh
@@ -32,8 +32,20 @@
# $2: MFS image filename
#
-obs=`strings -at d $1 | grep "MFS Filesystem goes here" | awk '{print $1}'`
-dd if=$2 ibs=8192 of=$1 obs=${obs} oseek=1 conv=notrunc 2> /dev/null
+mfs_size=`stat -f '%z' $2 2> /dev/null`
+# If we can't determine MFS image size - bail.
+[ -z ${mfs_size} ] && echo "Can't determine MFS image size" && exit 1
-strings $1 | grep 'MFS Filesystem had better STOP here' > /dev/null || \
- (rm $1 && echo "MFS image too large" && false)
+sec_info=`objdump -h $1 2> /dev/null | grep " oldmfs "`
+# If we can't find the mfs section within the given kernel - bail.
+[ -z "${sec_info}" ] && echo "Can't locate mfs section within kernel" && exit 1
+
+sec_size=`echo ${sec_info} | awk '{printf("%d", "0x" $3)}' 2> /dev/null`
+sec_start=`echo ${sec_info} | awk '{printf("%d", "0x" $6)}' 2> /dev/null`
+
+# If the mfs section size is smaller than the mfs image - bail.
+[ ${sec_size} -lt ${mfs_size} ] && echo "MFS image too large" && exit 1
+
+# Dump the mfs image into the mfs section
+dd if=$2 ibs=8192 of=$1 obs=${sec_start} oseek=1 conv=notrunc 2> /dev/null && \
+ echo "MFS image embedded into kernel" && exit 0
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index c29e5d5dc12a..b4ec348f3329 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -77,7 +77,6 @@ void ffs_fserr(struct fs *, ino_t, char *);
int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t);
int ffs_isfreeblock(struct fs *, u_char *, ufs1_daddr_t);
void ffs_load_inode(struct buf *, struct inode *, struct fs *, ino_t);
-int ffs_mountroot(void);
void ffs_oldfscompat_write(struct fs *, struct ufsmount *);
int ffs_own_mount(const struct mount *mp);
int ffs_reallocblks(struct vop_reallocblks_args *);
diff --git a/sys/vm/memguard.c b/sys/vm/memguard.c
index d4efc2b7123e..fb70a4186c73 100644
--- a/sys/vm/memguard.c
+++ b/sys/vm/memguard.c
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/malloc.h>
#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
#include <sys/vmem.h>
#include <vm/vm.h>
diff --git a/sys/vm/sg_pager.c b/sys/vm/sg_pager.c
index 84bfa49f11a4..2cccb7ea1598 100644
--- a/sys/vm/sg_pager.c
+++ b/sys/vm/sg_pager.c
@@ -189,6 +189,9 @@ sg_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind,
VM_OBJECT_WLOCK(object);
TAILQ_INSERT_TAIL(&object->un_pager.sgp.sgp_pglist, page, plinks.q);
vm_page_replace_checked(page, object, offset, m[0]);
+ vm_page_lock(m[0]);
+ vm_page_free(m[0]);
+ vm_page_unlock(m[0]);
m[0] = page;
page->valid = VM_PAGE_BITS_ALL;
diff --git a/sys/vm/uma.h b/sys/vm/uma.h
index d218e60886dc..21c61214315d 100644
--- a/sys/vm/uma.h
+++ b/sys/vm/uma.h
@@ -530,7 +530,7 @@ void uma_zone_set_warning(uma_zone_t zone, const char *warning);
* Returns:
* Nothing
*/
-typedef void (*uma_maxaction_t)(uma_zone_t);
+typedef void (*uma_maxaction_t)(uma_zone_t, int);
void uma_zone_set_maxaction(uma_zone_t zone, uma_maxaction_t);
/*
diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
index 4600589bd06d..0d45046e7e51 100644
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sbuf.h>
#include <sys/sched.h>
#include <sys/smp.h>
+#include <sys/taskqueue.h>
#include <sys/vmmeter.h>
#include <vm/vm.h>
@@ -275,6 +276,11 @@ void uma_print_stats(void);
static int sysctl_vm_zone_count(SYSCTL_HANDLER_ARGS);
static int sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS);
+#ifdef INVARIANTS
+static void uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item);
+static void uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item);
+#endif
+
SYSINIT(uma_startup3, SI_SUB_VM_CONF, SI_ORDER_SECOND, uma_startup3, NULL);
SYSCTL_PROC(_vm, OID_AUTO, zone_count, CTLFLAG_RD|CTLTYPE_INT,
@@ -434,8 +440,9 @@ zone_log_warning(uma_zone_t zone)
static inline void
zone_maxaction(uma_zone_t zone)
{
- if (zone->uz_maxaction)
- (*zone->uz_maxaction)(zone);
+
+ if (zone->uz_maxaction.ta_func != NULL)
+ taskqueue_enqueue(taskqueue_thread, &zone->uz_maxaction);
}
static void
@@ -1585,7 +1592,6 @@ zone_ctor(void *mem, int size, void *udata, int flags)
zone->uz_flags = 0;
zone->uz_warning = NULL;
timevalclear(&zone->uz_ratecheck);
- zone->uz_maxaction = NULL;
keg = arg->keg;
ZONE_LOCK_INIT(zone, (arg->flags & UMA_ZONE_MTXCLASS));
@@ -3022,7 +3028,7 @@ uma_zone_set_maxaction(uma_zone_t zone, uma_maxaction_t maxaction)
{
ZONE_LOCK(zone);
- zone->uz_maxaction = maxaction;
+ TASK_INIT(&zone->uz_maxaction, 0, (task_fn_t *)maxaction, zone);
ZONE_UNLOCK(zone);
}
@@ -3607,6 +3613,102 @@ sysctl_handle_uma_zone_cur(SYSCTL_HANDLER_ARGS)
return (sysctl_handle_int(oidp, &cur, 0, req));
}
+#ifdef INVARIANTS
+static uma_slab_t
+uma_dbg_getslab(uma_zone_t zone, void *item)
+{
+ uma_slab_t slab;
+ uma_keg_t keg;
+ uint8_t *mem;
+
+ mem = (uint8_t *)((uintptr_t)item & (~UMA_SLAB_MASK));
+ if (zone->uz_flags & UMA_ZONE_VTOSLAB) {
+ slab = vtoslab((vm_offset_t)mem);
+ } else {
+ /*
+ * It is safe to return the slab here even though the
+ * zone is unlocked because the item's allocation state
+ * essentially holds a reference.
+ */
+ ZONE_LOCK(zone);
+ keg = LIST_FIRST(&zone->uz_kegs)->kl_keg;
+ if (keg->uk_flags & UMA_ZONE_HASH)
+ slab = hash_sfind(&keg->uk_hash, mem);
+ else
+ slab = (uma_slab_t)(mem + keg->uk_pgoff);
+ ZONE_UNLOCK(zone);
+ }
+
+ return (slab);
+}
+
+/*
+ * Set up the slab's freei data such that uma_dbg_free can function.
+ *
+ */
+static void
+uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item)
+{
+ uma_keg_t keg;
+ int freei;
+
+ if (zone_first_keg(zone) == NULL)
+ return;
+ if (slab == NULL) {
+ slab = uma_dbg_getslab(zone, item);
+ if (slab == NULL)
+ panic("uma: item %p did not belong to zone %s\n",
+ item, zone->uz_name);
+ }
+ keg = slab->us_keg;
+ freei = ((uintptr_t)item - (uintptr_t)slab->us_data) / keg->uk_rsize;
+
+ if (BIT_ISSET(SLAB_SETSIZE, freei, &slab->us_debugfree))
+ panic("Duplicate alloc of %p from zone %p(%s) slab %p(%d)\n",
+ item, zone, zone->uz_name, slab, freei);
+ BIT_SET_ATOMIC(SLAB_SETSIZE, freei, &slab->us_debugfree);
+
+ return;
+}
+
+/*
+ * Verifies freed addresses. Checks for alignment, valid slab membership
+ * and duplicate frees.
+ *
+ */
+static void
+uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item)
+{
+ uma_keg_t keg;
+ int freei;
+
+ if (zone_first_keg(zone) == NULL)
+ return;
+ if (slab == NULL) {
+ slab = uma_dbg_getslab(zone, item);
+ if (slab == NULL)
+ panic("uma: Freed item %p did not belong to zone %s\n",
+ item, zone->uz_name);
+ }
+ keg = slab->us_keg;
+ freei = ((uintptr_t)item - (uintptr_t)slab->us_data) / keg->uk_rsize;
+
+ if (freei >= keg->uk_ipers)
+ panic("Invalid free of %p from zone %p(%s) slab %p(%d)\n",
+ item, zone, zone->uz_name, slab, freei);
+
+ if (((freei * keg->uk_rsize) + slab->us_data) != item)
+ panic("Unaligned free of %p from zone %p(%s) slab %p(%d)\n",
+ item, zone, zone->uz_name, slab, freei);
+
+ if (!BIT_ISSET(SLAB_SETSIZE, freei, &slab->us_debugfree))
+ panic("Duplicate free of %p from zone %p(%s) slab %p(%d)\n",
+ item, zone, zone->uz_name, slab, freei);
+
+ BIT_CLR_ATOMIC(SLAB_SETSIZE, freei, &slab->us_debugfree);
+}
+#endif /* INVARIANTS */
+
#ifdef DDB
DB_SHOW_COMMAND(uma, db_show_uma)
{
@@ -3664,4 +3766,4 @@ DB_SHOW_COMMAND(umacache, db_show_umacache)
return;
}
}
-#endif
+#endif /* DDB */
diff --git a/sys/vm/uma_dbg.c b/sys/vm/uma_dbg.c
index 3fbd29b16dea..7bf06d35b4e2 100644
--- a/sys/vm/uma_dbg.c
+++ b/sys/vm/uma_dbg.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/malloc.h>
+#include <sys/taskqueue.h>
#include <vm/vm.h>
#include <vm/vm_object.h>
@@ -196,100 +197,3 @@ mtrash_fini(void *mem, int size)
{
(void)mtrash_ctor(mem, size, NULL, 0);
}
-
-#ifdef INVARIANTS
-static uma_slab_t
-uma_dbg_getslab(uma_zone_t zone, void *item)
-{
- uma_slab_t slab;
- uma_keg_t keg;
- uint8_t *mem;
-
- mem = (uint8_t *)((uintptr_t)item & (~UMA_SLAB_MASK));
- if (zone->uz_flags & UMA_ZONE_VTOSLAB) {
- slab = vtoslab((vm_offset_t)mem);
- } else {
- /*
- * It is safe to return the slab here even though the
- * zone is unlocked because the item's allocation state
- * essentially holds a reference.
- */
- ZONE_LOCK(zone);
- keg = LIST_FIRST(&zone->uz_kegs)->kl_keg;
- if (keg->uk_flags & UMA_ZONE_HASH)
- slab = hash_sfind(&keg->uk_hash, mem);
- else
- slab = (uma_slab_t)(mem + keg->uk_pgoff);
- ZONE_UNLOCK(zone);
- }
-
- return (slab);
-}
-
-/*
- * Set up the slab's freei data such that uma_dbg_free can function.
- *
- */
-void
-uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item)
-{
- uma_keg_t keg;
- int freei;
-
- if (zone_first_keg(zone) == NULL)
- return;
- if (slab == NULL) {
- slab = uma_dbg_getslab(zone, item);
- if (slab == NULL)
- panic("uma: item %p did not belong to zone %s\n",
- item, zone->uz_name);
- }
- keg = slab->us_keg;
- freei = ((uintptr_t)item - (uintptr_t)slab->us_data) / keg->uk_rsize;
-
- if (BIT_ISSET(SLAB_SETSIZE, freei, &slab->us_debugfree))
- panic("Duplicate alloc of %p from zone %p(%s) slab %p(%d)\n",
- item, zone, zone->uz_name, slab, freei);
- BIT_SET_ATOMIC(SLAB_SETSIZE, freei, &slab->us_debugfree);
-
- return;
-}
-
-/*
- * Verifies freed addresses. Checks for alignment, valid slab membership
- * and duplicate frees.
- *
- */
-void
-uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item)
-{
- uma_keg_t keg;
- int freei;
-
- if (zone_first_keg(zone) == NULL)
- return;
- if (slab == NULL) {
- slab = uma_dbg_getslab(zone, item);
- if (slab == NULL)
- panic("uma: Freed item %p did not belong to zone %s\n",
- item, zone->uz_name);
- }
- keg = slab->us_keg;
- freei = ((uintptr_t)item - (uintptr_t)slab->us_data) / keg->uk_rsize;
-
- if (freei >= keg->uk_ipers)
- panic("Invalid free of %p from zone %p(%s) slab %p(%d)\n",
- item, zone, zone->uz_name, slab, freei);
-
- if (((freei * keg->uk_rsize) + slab->us_data) != item)
- panic("Unaligned free of %p from zone %p(%s) slab %p(%d)\n",
- item, zone, zone->uz_name, slab, freei);
-
- if (!BIT_ISSET(SLAB_SETSIZE, freei, &slab->us_debugfree))
- panic("Duplicate free of %p from zone %p(%s) slab %p(%d)\n",
- item, zone, zone->uz_name, slab, freei);
-
- BIT_CLR_ATOMIC(SLAB_SETSIZE, freei, &slab->us_debugfree);
-}
-
-#endif /* INVARIANTS */
diff --git a/sys/vm/uma_dbg.h b/sys/vm/uma_dbg.h
index 341cecbf8de3..e3c9df02f2d3 100644
--- a/sys/vm/uma_dbg.h
+++ b/sys/vm/uma_dbg.h
@@ -49,7 +49,4 @@ void mtrash_dtor(void *mem, int size, void *arg);
int mtrash_init(void *mem, int size, int flags);
void mtrash_fini(void *mem, int size);
-void uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item);
-void uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item);
-
#endif /* VM_UMA_DBG_H */
diff --git a/sys/vm/uma_int.h b/sys/vm/uma_int.h
index 5d7ecd331a7f..1b0d5d5dbf37 100644
--- a/sys/vm/uma_int.h
+++ b/sys/vm/uma_int.h
@@ -307,7 +307,7 @@ struct uma_zone {
const char *uz_warning; /* Warning to print on failure */
struct timeval uz_ratecheck; /* Warnings rate-limiting */
- uma_maxaction_t uz_maxaction; /* Function to run when at limit */
+ struct task uz_maxaction; /* Task to run when at limit */
/*
* This HAS to be the last item because we adjust the zone size
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index d27eb2d4eaf0..b510696ed170 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -102,6 +102,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
#include <sys/vnode.h>
+#include <sys/taskqueue.h>
#include <vm/vm.h>
#include <vm/pmap.h>
diff --git a/tests/sys/acl/Makefile b/tests/sys/acl/Makefile
index 298b0a27c91d..d101088dcd3f 100644
--- a/tests/sys/acl/Makefile
+++ b/tests/sys/acl/Makefile
@@ -22,8 +22,14 @@ TAP_TESTS_SH+= 04
TEST_METADATA.$t+= required_user="root"
.endfor
+_ACL_PROGS= getfacl setfacl
+
.for t in 01 03 04
-TEST_METADATA.$t+= required_programs="/sbin/zpool"
+TEST_METADATA.$t+= required_programs="zpool ${_ACL_PROGS}"
+.endfor
+
+.for t in 00 02
+TEST_METADATA.$t+= required_programs="${_ACL_PROGS}"
.endfor
.include <bsd.test.mk>
diff --git a/tests/sys/geom/class/gate/1_test.sh b/tests/sys/geom/class/gate/1_test.sh
index 3e277349631f..ba573bb6e122 100644
--- a/tests/sys/geom/class/gate/1_test.sh
+++ b/tests/sys/geom/class/gate/1_test.sh
@@ -10,6 +10,7 @@ us=0
while [ -c /dev/ggate${us} ]; do
: $(( us += 1 ))
done
+pidfile=ggated.$$.pid
conf=`mktemp $base.XXXXXX` || exit 1
port=33080
@@ -19,7 +20,7 @@ src=$(attach_md -t malloc -s 1M)
test_cleanup()
{
ggatec destroy -f -u $us
- killall ggated
+ pkill -F $pidfile
geom_test_cleanup
}
trap test_cleanup ABRT EXIT INT TERM
@@ -30,7 +31,7 @@ src_checksum=$(md5 -q /dev/$src)
echo "127.0.0.1 RW /dev/$work" > $conf
-if ! ggated -p $port $conf; then
+if ! ggated -p $port -F $pidfile $conf; then
echo 'ggated failed to start'
echo 'Bail out!'
exit 1
@@ -41,6 +42,7 @@ if ! ggatec create -p $port -u $us 127.0.0.1 /dev/$work; then
echo 'Bail out!'
exit 1
fi
+sleep 1
dd if=/dev/${src} of=/dev/ggate${us} bs=1m count=1
sleep 1
diff --git a/tests/sys/kqueue/common.h b/tests/sys/kqueue/common.h
index aada7786ad0c..89a402986021 100644
--- a/tests/sys/kqueue/common.h
+++ b/tests/sys/kqueue/common.h
@@ -46,6 +46,7 @@ int vnode_fd;
extern const char * kevent_to_str(struct kevent *);
struct kevent * kevent_get(int);
+struct kevent * kevent_get_timeout(int, int);
void kevent_cmp(struct kevent *, struct kevent *);
diff --git a/tests/sys/kqueue/main.c b/tests/sys/kqueue/main.c
index f76c4e23be12..553478a514f5 100644
--- a/tests/sys/kqueue/main.c
+++ b/tests/sys/kqueue/main.c
@@ -69,6 +69,28 @@ kevent_get(int kqfd)
return (kev);
}
+/* Retrieve a single kevent, specifying a maximum time to wait for it. */
+struct kevent *
+kevent_get_timeout(int kqfd, int seconds)
+{
+ int nfds;
+ struct kevent *kev;
+ struct timespec timeout = {seconds, 0};
+
+ if ((kev = calloc(1, sizeof(*kev))) == NULL)
+ err(1, "out of memory");
+
+ nfds = kevent(kqfd, NULL, 0, kev, 1, &timeout);
+ if (nfds < 0) {
+ err(1, "kevent(2)");
+ } else if (nfds == 0) {
+ free(kev);
+ kev = NULL;
+ }
+
+ return (kev);
+}
+
char *
kevent_fflags_dump(struct kevent *kev)
{
@@ -82,25 +104,39 @@ kevent_fflags_dump(struct kevent *kev)
abort();
/* Not every filter has meaningful fflags */
- if (kev->filter != EVFILT_VNODE) {
- snprintf(buf, 1024, "fflags = %d", kev->fflags);
- return (buf);
- }
-
- snprintf(buf, 1024, "fflags = %d (", kev->fflags);
- KEVFFL_DUMP(NOTE_DELETE);
- KEVFFL_DUMP(NOTE_WRITE);
- KEVFFL_DUMP(NOTE_EXTEND);
+ if (kev->filter == EVFILT_PROC) {
+ snprintf(buf, 1024, "fflags = %x (", kev->fflags);
+ KEVFFL_DUMP(NOTE_EXIT);
+ KEVFFL_DUMP(NOTE_FORK);
+ KEVFFL_DUMP(NOTE_EXEC);
+ KEVFFL_DUMP(NOTE_CHILD);
+ KEVFFL_DUMP(NOTE_TRACKERR);
+ KEVFFL_DUMP(NOTE_TRACK);
+ buf[strlen(buf) - 1] = ')';
+ } else if (kev->filter == EVFILT_PROCDESC) {
+ snprintf(buf, 1024, "fflags = %x (", kev->fflags);
+ KEVFFL_DUMP(NOTE_EXIT);
+ KEVFFL_DUMP(NOTE_FORK);
+ KEVFFL_DUMP(NOTE_EXEC);
+ buf[strlen(buf) - 1] = ')';
+ } else if (kev->filter == EVFILT_VNODE) {
+ snprintf(buf, 1024, "fflags = %x (", kev->fflags);
+ KEVFFL_DUMP(NOTE_DELETE);
+ KEVFFL_DUMP(NOTE_WRITE);
+ KEVFFL_DUMP(NOTE_EXTEND);
#if HAVE_NOTE_TRUNCATE
- KEVFFL_DUMP(NOTE_TRUNCATE);
+ KEVFFL_DUMP(NOTE_TRUNCATE);
#endif
- KEVFFL_DUMP(NOTE_ATTRIB);
- KEVFFL_DUMP(NOTE_LINK);
- KEVFFL_DUMP(NOTE_RENAME);
+ KEVFFL_DUMP(NOTE_ATTRIB);
+ KEVFFL_DUMP(NOTE_LINK);
+ KEVFFL_DUMP(NOTE_RENAME);
#if HAVE_NOTE_REVOKE
- KEVFFL_DUMP(NOTE_REVOKE);
+ KEVFFL_DUMP(NOTE_REVOKE);
#endif
- buf[strlen(buf) - 1] = ')';
+ buf[strlen(buf) - 1] = ')';
+ } else {
+ snprintf(buf, 1024, "fflags = %x", kev->fflags);
+ }
return (buf);
}
@@ -260,6 +296,15 @@ main(int argc, char **argv)
argc--;
}
+ /*
+ * Some tests fork. If output is fully buffered,
+ * the children inherit some buffered data and flush
+ * it when they exit, causing some data to be printed twice.
+ * Use line buffering to avoid this problem.
+ */
+ setlinebuf(stdout);
+ setlinebuf(stderr);
+
test_kqueue();
test_kqueue_close();
diff --git a/tests/sys/kqueue/proc.c b/tests/sys/kqueue/proc.c
index 6288ee6d91b4..79b8d35f4f25 100644
--- a/tests/sys/kqueue/proc.c
+++ b/tests/sys/kqueue/proc.c
@@ -74,6 +74,172 @@ add_and_delete(void)
}
+static void
+proc_track(int sleep_time)
+{
+ char test_id[64];
+ struct kevent kev;
+ pid_t pid;
+ int pipe_fd[2];
+ ssize_t result;
+
+ snprintf(test_id, sizeof(test_id),
+ "kevent(EVFILT_PROC, NOTE_TRACK); sleep %d", sleep_time);
+ test_begin(test_id);
+ test_no_kevents();
+
+ if (pipe(pipe_fd)) {
+ err(1, "pipe (parent) failed! (%s() at %s:%d)",
+ __func__, __FILE__, __LINE__);
+ }
+
+ /* Create a child to track. */
+ pid = fork();
+ if (pid == 0) { /* Child */
+ pid_t grandchild = -1;
+
+ /*
+ * Give the parent a chance to start tracking us.
+ */
+ result = read(pipe_fd[1], test_id, 1);
+ if (result != 1) {
+ err(1, "read from pipe in child failed! (ret %zd) (%s() at %s:%d)",
+ result, __func__, __FILE__, __LINE__);
+ }
+
+ /*
+ * Spawn a grandchild that will immediately exit. If the kernel has bug
+ * 180385, the parent will see a kevent with both NOTE_CHILD and
+ * NOTE_EXIT. If that bug is fixed, it will see two separate kevents
+ * for those notes. Note that this triggers the conditions for
+ * detecting the bug quite reliably on a 1 CPU system (or if the test
+ * process is restricted to a single CPU), but may not trigger it on a
+ * multi-CPU system.
+ */
+ grandchild = fork();
+ if (grandchild == 0) { /* Grandchild */
+ if (sleep_time) sleep(sleep_time);
+ exit(1);
+ } else if (grandchild == -1) { /* Error */
+ err(1, "fork (grandchild) failed! (%s() at %s:%d)",
+ __func__, __FILE__, __LINE__);
+ } else { /* Child (Grandchild Parent) */
+ printf(" -- grandchild created (pid %d)\n", (int) grandchild);
+ }
+ if (sleep_time) sleep(sleep_time);
+ exit(0);
+ } else if (pid == -1) { /* Error */
+ err(1, "fork (child) failed! (%s() at %s:%d)",
+ __func__, __FILE__, __LINE__);
+ }
+
+ printf(" -- child created (pid %d)\n", (int) pid);
+
+ kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD | EV_ENABLE,
+ NOTE_TRACK | NOTE_EXEC | NOTE_EXIT | NOTE_FORK,
+ 0, NULL);
+
+ printf(" -- tracking child (pid %d)\n", (int) pid);
+
+ /* Now that we're tracking the child, tell it to proceed. */
+ result = write(pipe_fd[0], test_id, 1);
+ if (result != 1) {
+ err(1, "write to pipe in parent failed! (ret %zd) (%s() at %s:%d)",
+ result, __func__, __FILE__, __LINE__);
+ }
+
+ /*
+ * Several events should be received:
+ * - NOTE_FORK (from child)
+ * - NOTE_CHILD (from grandchild)
+ * - NOTE_EXIT (from grandchild)
+ * - NOTE_EXIT (from child)
+ *
+ * The NOTE_FORK and NOTE_EXIT from the child could be combined into a
+ * single event, but the NOTE_CHILD and NOTE_EXIT from the grandchild must
+ * not be combined.
+ *
+ * The loop continues until no events are received within a 5 second
+ * period, at which point it is assumed that no more will be coming. The
+ * loop is deliberately designed to attempt to get events even after all
+ * the expected ones are received in case some spurious events are
+ * generated as well as the expected ones.
+ */
+ {
+ int child_exit = 0;
+ int child_fork = 0;
+ int gchild_exit = 0;
+ int gchild_note = 0;
+ pid_t gchild_pid = -1;
+ int done = 0;
+
+ while (!done)
+ {
+ int handled = 0;
+ struct kevent *kevp;
+
+ kevp = kevent_get_timeout(kqfd, 5);
+ if (kevp == NULL) {
+ done = 1;
+ } else {
+ printf(" -- Received kevent: %s\n", kevent_to_str(kevp));
+
+ if ((kevp->fflags & NOTE_CHILD) && (kevp->fflags & NOTE_EXIT)) {
+ errx(1, "NOTE_CHILD and NOTE_EXIT in same kevent: %s", kevent_to_str(kevp));
+ }
+
+ if (kevp->fflags & NOTE_CHILD) {
+ if (kevp->data == pid) {
+ if (!gchild_note) {
+ ++gchild_note;
+ gchild_pid = kevp->ident;
+ ++handled;
+ } else {
+ errx(1, "Spurious NOTE_CHILD: %s", kevent_to_str(kevp));
+ }
+ }
+ }
+
+ if (kevp->fflags & NOTE_EXIT) {
+ if ((kevp->ident == pid) && (!child_exit)) {
+ ++child_exit;
+ ++handled;
+ } else if ((kevp->ident == gchild_pid) && (!gchild_exit)) {
+ ++gchild_exit;
+ ++handled;
+ } else {
+ errx(1, "Spurious NOTE_EXIT: %s", kevent_to_str(kevp));
+ }
+ }
+
+ if (kevp->fflags & NOTE_FORK) {
+ if ((kevp->ident == pid) && (!child_fork)) {
+ ++child_fork;
+ ++handled;
+ } else {
+ errx(1, "Spurious NOTE_FORK: %s", kevent_to_str(kevp));
+ }
+ }
+
+ if (!handled) {
+ errx(1, "Spurious kevent: %s", kevent_to_str(kevp));
+ }
+
+ free(kevp);
+ }
+ }
+
+ /* Make sure all expected events were received. */
+ if (child_exit && child_fork && gchild_exit && gchild_note) {
+ printf(" -- Received all expected events.\n");
+ } else {
+ errx(1, "Did not receive all expected events.");
+ }
+ }
+
+ success();
+}
+
#ifdef TODO
static void
event_trigger(void)
@@ -236,6 +402,8 @@ test_evfilt_proc()
signal(SIGUSR1, sig_handler);
add_and_delete();
+ proc_track(0); /* Run without sleeping before children exit. */
+ proc_track(1); /* Sleep a bit in the children before exiting. */
#if TODO
event_trigger();
diff --git a/tools/tools/nanobsd/defaults.sh b/tools/tools/nanobsd/defaults.sh
index 8084bfaf0fcb..a0e6be580b9b 100755
--- a/tools/tools/nanobsd/defaults.sh
+++ b/tools/tools/nanobsd/defaults.sh
@@ -156,6 +156,8 @@ NANO_SLICE_ROOT=s1
NANO_SLICE_ALTROOT=s2
NANO_SLICE_CFG=s3
NANO_SLICE_DATA=s4
+NANO_ROOT=s1a
+NANO_ALTROOT=s2a
# Default ownwership for nopriv build
NANO_DEF_UNAME=root
@@ -569,7 +571,7 @@ setup_nanobsd_etc ( ) (
# save config file for scripts
echo "NANO_DRIVE=${NANO_DRIVE}" > etc/nanobsd.conf
- echo "/dev/${NANO_DRIVE}${NANO_SLICE_ROOT}a / ufs ro 1 1" > etc/fstab
+ echo "/dev/${NANO_DRIVE}${NANO_ROOT} / ufs ro 1 1" > etc/fstab
echo "/dev/${NANO_DRIVE}${NANO_SLICE_CFG} /cfg ufs rw,noauto 2 2" >> etc/fstab
mkdir -p cfg
)
@@ -731,8 +733,8 @@ create_diskimage ( ) (
bsdlabel ${MD}${NANO_SLICE_ROOT}
# Create first image
- populate_slice /dev/${MD}${NANO_SLICE_ROOT}a ${NANO_WORLDDIR} ${MNT} "${NANO_SLICE_ROOT}a"
- mount /dev/${MD}${NANO_SLICE_ROOT}a ${MNT}
+ populate_slice /dev/${MD}${NANO_ROOT} ${NANO_WORLDDIR} ${MNT} "${NANO_ROOT}"
+ mount /dev/${MD}${NANO_ROOT} ${MNT}
echo "Generating mtree..."
( cd "${MNT}" && mtree -c ) > ${NANO_OBJ}/_.mtree
( cd "${MNT}" && du -k ) > ${NANO_OBJ}/_.du
@@ -742,7 +744,7 @@ create_diskimage ( ) (
# Duplicate to second image (if present)
echo "Duplicating to second image..."
dd conv=sparse if=/dev/${MD}${NANO_SLICE_ROOT} of=/dev/${MD}${NANO_SLICE_ALTROOT} bs=64k
- mount /dev/${MD}${NANO_SLICE_ALTROOT}a ${MNT}
+ mount /dev/${MD}${NANO_ALTROOT} ${MNT}
for f in ${MNT}/etc/fstab ${MNT}/conf/base/etc/fstab
do
sed -i "" "s=${NANO_DRIVE}${NANO_SLICE_ROOT}=${NANO_DRIVE}${NANO_SLICE_ALTROOT}=g" $f
@@ -751,7 +753,7 @@ create_diskimage ( ) (
# Override the label from the first partition so we
# don't confuse glabel with duplicates.
if [ -n "${NANO_LABEL}" ]; then
- tunefs -L ${NANO_LABEL}"${NANO_SLICE_ALTROOT}a" /dev/${MD}${NANO_SLICE_ALTROOT}a
+ tunefs -L ${NANO_LABEL}"${NANO_ALTROOT}" /dev/${MD}${NANO_ALTROOT}
fi
fi
diff --git a/tools/tools/nanobsd/embedded/README b/tools/tools/nanobsd/embedded/README
index e8b1c8c6506e..ebaba4c7c97a 100644
--- a/tools/tools/nanobsd/embedded/README
+++ b/tools/tools/nanobsd/embedded/README
@@ -10,8 +10,6 @@ and DHCPd.
This is a work in progress. Generally, to build this you should
cd tools/tools/nanobsd/embedded
sudo sh ../nanobsd.sh -c foo.cfg
-but do be careful if things are interrupted. There may still be
-bugs lurking that cause your entire FreeBSD tree to disappear.
Some features:
diff --git a/tools/tools/nanobsd/embedded/common b/tools/tools/nanobsd/embedded/common
index a1d401a03782..bbac16205304 100644
--- a/tools/tools/nanobsd/embedded/common
+++ b/tools/tools/nanobsd/embedded/common
@@ -76,6 +76,8 @@ fi
NANO_SLICE_FAT_SIZE=32m
NANO_SLICE_CFG_SIZE=32m
+NANO_BOOT2CFG="-D -h -S115200 comconsole_port=0x3e8"
+
NANO_RAM_ETCSIZE=8192
NANO_RAM_TMPVARSIZE=8192
NANO_IMAGES=2
@@ -292,7 +294,7 @@ create_diskimage_mbr ( ) (
bootbsd=${NANO_BOOT_BSD:+-b ${NANO_BOOT_BSD}}
skiparg=${NANO_MBR_FIRST_SKIP:+-S ${NANO_MBR_FIRST_SKIP}}
- for i in s1 s2 s3 s4 empty; do
+ for i in s1 s2 s3 s4 p1 p2 p3 p4 p5 empty; do
rm -fr ${NANO_OBJ}/_.${i}*
done
@@ -317,10 +319,10 @@ create_diskimage_mbr ( ) (
# bsd label
[ -z ${NANO_NOPRIV_BUILD} ] || extra="-F ${NANO_METALOG}"
sz=${NANO_SLICE_ROOT_SIZE:+-s ${NANO_SLICE_ROOT_SIZE}}
- eval "${NANO_MAKEFS_UFS}" ${extra} $sz "${NANO_OBJ}/_.${NANO_SLICE_ROOT}a" \
+ eval "${NANO_MAKEFS_UFS}" ${extra} $sz "${NANO_OBJ}/_.${NANO_SLICE_ROOT}" \
"${NANO_WORLDDIR}"
- mkimg -s bsd ${bootbsd} -p freebsd-ufs:=${NANO_OBJ}/_.${NANO_SLICE_ROOT}a \
- -o ${NANO_OBJ}/_.${NANO_SLICE_ROOT}
+# mkimg -s bsd ${bootbsd} -p freebsd-ufs:=${NANO_OBJ}/_.${NANO_SLICE_ROOT} \
+# -o ${NANO_OBJ}/_.${NANO_SLICE_ROOT}
# Populate the /cfg partition, empty if none given
if [ -z "${NANO_CFGDIR}" ]; then
@@ -339,8 +341,18 @@ create_diskimage_mbr ( ) (
if [ -n "$NANO_SLICE_FAT" ]; then
eval $NANO_SLICE_FAT=fat16b
fi
- eval $NANO_SLICE_CFG=freebsd
- eval $NANO_SLICE_ROOT=freebsd
+ case ${NANO_SLICE_CFG} in
+ s*)
+ echo slice
+ eval $NANO_SLICE_CFG=freebsd
+ eval $NANO_SLICE_ROOT=freebsd
+ ;;
+ p*)
+ echo part
+ eval $NANO_SLICE_CFG=freebsd-ufs
+ eval $NANO_SLICE_ROOT=freebsd-ufs
+ ;;
+ esac
# below depends on https://reviews.freebsd.org/D4403 not yet in the tree
# but there's problems: it marks all partitions as active, so you have to
# boot off parittion 3 or 2 by hand if you're playing around with this WIP
@@ -358,6 +370,25 @@ create_diskimage_mbr ( ) (
-p ${s2}:=${NANO_OBJ}/_.s2 \
-o ${NANO_OBJ}/_.disk.image.${NANO_NAME}${fmt}
;;
+ std-uefi)
+ # s1 is boot, s2 is cfg, s3 is /, not sure how to make that
+ # boot (marked as active) with mkimg yet
+ mkimg -a 2 ${fmtarg} ${bootmbr} -s mbr \
+ -p efi:=${NANO_WORLDDIR}/boot/boot1.efifat \
+ -p ${s2}:=${NANO_OBJ}/_.s2 \
+ -p ${s3}:=${NANO_OBJ}/_.s3 \
+ -o ${NANO_OBJ}/_.disk.image.${NANO_NAME}${fmt}
+ ;;
+ std-uefi-bios)
+ # p1 is boot for uefi, p2 is boot for gpt, p3 is cfg, p4 is /
+ # and p5 is alt-root (after resize)
+ mkimg -a 2 ${fmtarg} ${bootmbr} -s gpt \
+ -p efi:=${NANO_WORLDDIR}/boot/boot1.efifat \
+ -p freebsd-boot:=${NAANO_WORLDDIR}/boot/gptboot \
+ -p ${p3}:=${NANO_OBJ}/_.p3 \
+ -p ${p4}:=${NANO_OBJ}/_.p4 \
+ -o ${NANO_OBJ}/_.disk.image.${NANO_NAME}${fmt}
+ ;;
powerpc64-ibm)
# A lie to make the boot loader work, it boots the first BSD partition
# it finds, regardless of the active flag.
@@ -658,12 +689,30 @@ powerpc64-apple)
echo Not yet
exit 1
;;
+std-uefi)
+ NANO_SLICE_UEFI=s1
+ NANO_SLICE_CFG=s2
+ NANO_SLICE_ROOT=s3
+ NANO_SLICE_ALTROOT=s4
+ ;;
+std-uefi-bios)
+ NANO_SLICE_UEFI=p1
+ NANO_SLICE_BOOT=p2
+ NANO_SLICE_CFG=p3
+ NANO_SLICE_ROOT=p4
+ NANO_SLICE_ALTROOT=p5
+ ;;
*)
echo Unknown Layout ${NANO_LAYOUT}
exit 1
;;
esac
+# For this config, no BSD labels so NANO_ROOT and NANO_ALTROOT need to be
+# adjusted
+NANO_ROOT=${NANO_SLICE_ROOT}
+NANO_ALTROOT=${NANO_SLICE_ALTROOT}
+
NANO_SLICE_DATA= # Not included
# Each major disk scheme has its own routine. Generally
diff --git a/tools/tools/nanobsd/embedded/qemu-amd64-uefi-bios.cfg b/tools/tools/nanobsd/embedded/qemu-amd64-uefi-bios.cfg
new file mode 100644
index 000000000000..7f4f4276bb90
--- /dev/null
+++ b/tools/tools/nanobsd/embedded/qemu-amd64-uefi-bios.cfg
@@ -0,0 +1,43 @@
+# $FreeBSD$
+
+#-
+# Copyright (c) 2015 Warner Losh. All Rights Reserved.
+# Copyright (c) 2010-2011 iXsystems, Inc., All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL iXsystems, Inc. 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.
+#
+
+NANO_ARCH=amd64
+NANO_NAME=qemu-amd64-uefi-bios
+NANO_LAYOUT=std-uefi-bios
+
+. common # Pull in common definitions
+
+qemu_env
+
+#
+# Run with
+# qemu-system-x86_64 -serial stdio -bios OVMF.fd \
+# -hda _.disk.image.qemu-amd64-uefi.qcow2
+# OVMF.fd is from
+# http://sourceforge.net/projects/edk2/files/OVMF/OVMF-X64-r15214.zip
+#
diff --git a/tools/tools/nanobsd/embedded/qemu-amd64-uefi.cfg b/tools/tools/nanobsd/embedded/qemu-amd64-uefi.cfg
new file mode 100644
index 000000000000..a88e459a50c0
--- /dev/null
+++ b/tools/tools/nanobsd/embedded/qemu-amd64-uefi.cfg
@@ -0,0 +1,43 @@
+# $FreeBSD$
+
+#-
+# Copyright (c) 2015 Warner Losh. All Rights Reserved.
+# Copyright (c) 2010-2011 iXsystems, Inc., All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL iXsystems, Inc. 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.
+#
+
+NANO_ARCH=amd64
+NANO_NAME=qemu-amd64-uefi
+NANO_LAYOUT=std-uefi
+
+. common # Pull in common definitions
+
+qemu_env
+
+#
+# Run with
+# qemu-system-x86_64 -serial stdio -bios OVMF.fd \
+# -hda _.disk.image.qemu-amd64-uefi.qcow2
+# OVMF.fd is from
+# http://sourceforge.net/projects/edk2/files/OVMF/OVMF-X64-r15214.zip
+#
diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c
index d4406545fc4d..8fe03ea27766 100644
--- a/usr.bin/kdump/kdump.c
+++ b/usr.bin/kdump/kdump.c
@@ -690,20 +690,20 @@ syscallabi(u_int sv_flags)
{
if (sv_flags == 0)
- return (FREEBSD);
+ return (SYSDECODE_ABI_FREEBSD);
switch (sv_flags & SV_ABI_MASK) {
case SV_ABI_FREEBSD:
- return (FREEBSD);
+ return (SYSDECODE_ABI_FREEBSD);
#if defined(__amd64__) || defined(__i386__)
case SV_ABI_LINUX:
#ifdef __amd64__
if (sv_flags & SV_ILP32)
- return (LINUX32);
+ return (SYSDECODE_ABI_LINUX32);
#endif
- return (LINUX);
+ return (SYSDECODE_ABI_LINUX);
#endif
default:
- return (UNKNOWN_ABI);
+ return (SYSDECODE_ABI_UNKNOWN);
}
}
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c
index 6a933145e7e8..b0a0a7fca050 100644
--- a/usr.bin/netstat/inet.c
+++ b/usr.bin/netstat/inet.c
@@ -486,11 +486,11 @@ protopr(u_long off, const char *name, int af1, int proto)
else
xo_emit("{:protocol/%-3.3s%-2.2s/%s%s} ", name, vchar);
if (Lflag) {
- char buf1[15];
+ char buf1[33];
- snprintf(buf1, 15, "%d/%d/%d", so->so_qlen,
+ snprintf(buf1, sizeof buf1, "%u/%u/%u", so->so_qlen,
so->so_incqlen, so->so_qlimit);
- xo_emit("{:listen-queue-sizes/%-14.14s} ", buf1);
+ xo_emit("{:listen-queue-sizes/%-32.32s} ", buf1);
} else if (Tflag) {
if (istcp)
xo_emit("{:sent-retransmit-packets/%6u} "
diff --git a/usr.bin/netstat/sctp.c b/usr.bin/netstat/sctp.c
index 5f609a077d24..6c766b2ad082 100644
--- a/usr.bin/netstat/sctp.c
+++ b/usr.bin/netstat/sctp.c
@@ -467,9 +467,10 @@ sctp_process_inpcb(struct xsctp_inpcb *xinpcb,
tname = "????";
if (Lflag) {
- char buf1[9];
+ char buf1[22];
- snprintf(buf1, 9, "%hu/%hu", xinpcb->qlen, xinpcb->maxqlen);
+ snprintf(buf1, sizeof buf1, "%u/%u",
+ xinpcb->qlen, xinpcb->maxqlen);
xo_emit("{:protocol/%-6.6s/%s} {:type/%-5.5s/%s} ",
pname, tname);
xo_emit("{d:queues/%-8.8s}{e:queue-len/%hu}"
diff --git a/usr.bin/netstat/unix.c b/usr.bin/netstat/unix.c
index a7503f5f4725..04e4ae5e0aa7 100644
--- a/usr.bin/netstat/unix.c
+++ b/usr.bin/netstat/unix.c
@@ -271,7 +271,7 @@ unixdomainpr(struct xunpcb *xunp, struct xsocket *so)
struct unpcb *unp;
struct sockaddr_un *sa;
static int first = 1;
- char buf1[15];
+ char buf1[33];
static const char *titles[2] = {
"{T:/%-8.8s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s} {T:/%8.8s} "
"{T:/%8.8s} {T:/%8.8s} {T:/%8.8s} {T:Addr}\n",
@@ -310,10 +310,10 @@ unixdomainpr(struct xunpcb *xunp, struct xsocket *so)
return;
if (Lflag) {
- snprintf(buf1, 15, "%d/%d/%d", so->so_qlen,
+ snprintf(buf1, sizeof buf1, "%u/%u/%u", so->so_qlen,
so->so_incqlen, so->so_qlimit);
- xo_emit("unix {d:socket/%-14.14s}{e:queue-length/%d}"
- "{e:incomplete-queue-length/%d}{e:queue-limit/%d}",
+ xo_emit("unix {d:socket/%-32.32s}{e:queue-length/%u}"
+ "{e:incomplete-queue-length/%u}{e:queue-limit/%u}",
buf1, so->so_qlen, so->so_incqlen, so->so_qlimit);
} else {
xo_emit(format[fmt],
diff --git a/usr.bin/truss/aarch64-cloudabi64.c b/usr.bin/truss/aarch64-cloudabi64.c
index 099cb1e7d746..f2891afe02a8 100644
--- a/usr.bin/truss/aarch64-cloudabi64.c
+++ b/usr.bin/truss/aarch64-cloudabi64.c
@@ -81,7 +81,7 @@ aarch64_cloudabi64_fetch_retval(struct trussinfo *trussinfo, long *retval,
static struct procabi aarch64_cloudabi64 = {
"CloudABI ELF64",
- CLOUDABI64,
+ SYSDECODE_ABI_CLOUDABI64,
aarch64_cloudabi64_fetch_args,
aarch64_cloudabi64_fetch_retval
};
diff --git a/usr.bin/truss/aarch64-freebsd.c b/usr.bin/truss/aarch64-freebsd.c
index 454bba7d77ca..534441c60b8c 100644
--- a/usr.bin/truss/aarch64-freebsd.c
+++ b/usr.bin/truss/aarch64-freebsd.c
@@ -99,7 +99,7 @@ aarch64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp)
static struct procabi aarch64_freebsd = {
"FreeBSD ELF64",
- FREEBSD,
+ SYSDECODE_ABI_FREEBSD,
aarch64_fetch_args,
aarch64_fetch_retval
};
diff --git a/usr.bin/truss/amd64-cloudabi64.c b/usr.bin/truss/amd64-cloudabi64.c
index 38768ff0074d..ce8b18918fd8 100644
--- a/usr.bin/truss/amd64-cloudabi64.c
+++ b/usr.bin/truss/amd64-cloudabi64.c
@@ -90,7 +90,7 @@ amd64_cloudabi64_fetch_retval(struct trussinfo *trussinfo, long *retval,
static struct procabi amd64_cloudabi64 = {
"CloudABI ELF64",
- CLOUDABI64,
+ SYSDECODE_ABI_CLOUDABI64,
amd64_cloudabi64_fetch_args,
amd64_cloudabi64_fetch_retval
};
diff --git a/usr.bin/truss/amd64-freebsd.c b/usr.bin/truss/amd64-freebsd.c
index 8a211a0ce474..a2f378ca8ea5 100644
--- a/usr.bin/truss/amd64-freebsd.c
+++ b/usr.bin/truss/amd64-freebsd.c
@@ -121,7 +121,7 @@ amd64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp)
static struct procabi amd64_freebsd = {
"FreeBSD ELF64",
- FREEBSD,
+ SYSDECODE_ABI_FREEBSD,
amd64_fetch_args,
amd64_fetch_retval
};
diff --git a/usr.bin/truss/amd64-freebsd32.c b/usr.bin/truss/amd64-freebsd32.c
index adce798b7c5c..cfcead2a6014 100644
--- a/usr.bin/truss/amd64-freebsd32.c
+++ b/usr.bin/truss/amd64-freebsd32.c
@@ -117,7 +117,7 @@ amd64_freebsd32_fetch_retval(struct trussinfo *trussinfo, long *retval,
static struct procabi amd64_freebsd32 = {
"FreeBSD ELF32",
- FREEBSD32,
+ SYSDECODE_ABI_FREEBSD32,
amd64_freebsd32_fetch_args,
amd64_freebsd32_fetch_retval
};
@@ -126,7 +126,7 @@ PROCABI(amd64_freebsd32);
static struct procabi amd64_freebsd32_aout = {
"FreeBSD a.out",
- FREEBSD32,
+ SYSDECODE_ABI_FREEBSD32,
amd64_freebsd32_fetch_args,
amd64_freebsd32_fetch_retval
};
diff --git a/usr.bin/truss/amd64-linux32.c b/usr.bin/truss/amd64-linux32.c
index dd1d83361095..2ede61757b03 100644
--- a/usr.bin/truss/amd64-linux32.c
+++ b/usr.bin/truss/amd64-linux32.c
@@ -131,7 +131,7 @@ amd64_linux32_fetch_retval(struct trussinfo *trussinfo, long *retval,
static struct procabi amd64_linux32 = {
"Linux ELF32",
- LINUX32,
+ SYSDECODE_ABI_LINUX32,
amd64_linux32_fetch_args,
amd64_linux32_fetch_retval
};
diff --git a/usr.bin/truss/arm-freebsd.c b/usr.bin/truss/arm-freebsd.c
index 5722c91442fb..a1b2b21313ba 100644
--- a/usr.bin/truss/arm-freebsd.c
+++ b/usr.bin/truss/arm-freebsd.c
@@ -128,7 +128,7 @@ arm_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp)
static struct procabi arm_freebsd = {
"FreeBSD ELF32",
- FREEBSD,
+ SYSDECODE_ABI_FREEBSD,
arm_fetch_args,
arm_fetch_retval
};
diff --git a/usr.bin/truss/i386-freebsd.c b/usr.bin/truss/i386-freebsd.c
index c166596dcb11..bf35af2f015b 100644
--- a/usr.bin/truss/i386-freebsd.c
+++ b/usr.bin/truss/i386-freebsd.c
@@ -110,7 +110,7 @@ i386_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp)
static struct procabi i386_freebsd = {
"FreeBSD ELF32",
- FREEBSD,
+ SYSDECODE_ABI_FREEBSD,
i386_fetch_args,
i386_fetch_retval
};
@@ -119,7 +119,7 @@ PROCABI(i386_freebsd);
static struct procabi i386_freebsd_aout = {
"FreeBSD a.out",
- FREEBSD,
+ SYSDECODE_ABI_FREEBSD,
i386_fetch_args,
i386_fetch_retval
};
diff --git a/usr.bin/truss/i386-linux.c b/usr.bin/truss/i386-linux.c
index 5fdae8ee958c..fbc54a096d4f 100644
--- a/usr.bin/truss/i386-linux.c
+++ b/usr.bin/truss/i386-linux.c
@@ -130,7 +130,7 @@ i386_linux_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp)
static struct procabi i386_linux = {
"Linux ELF32",
- LINUX,
+ SYSDECODE_ABI_LINUX,
i386_linux_fetch_args,
i386_linux_fetch_retval
};
diff --git a/usr.bin/truss/mips-freebsd.c b/usr.bin/truss/mips-freebsd.c
index f4b5a7eb2aa0..3a42a59d7323 100644
--- a/usr.bin/truss/mips-freebsd.c
+++ b/usr.bin/truss/mips-freebsd.c
@@ -131,7 +131,7 @@ static struct procabi mips_freebsd = {
#else
"FreeBSD ELF32",
#endif
- FREEBSD,
+ SYSDECODE_ABI_FREEBSD,
mips_fetch_args,
mips_fetch_retval
};
diff --git a/usr.bin/truss/powerpc-freebsd.c b/usr.bin/truss/powerpc-freebsd.c
index 6a245df76c6a..ee78d038297a 100644
--- a/usr.bin/truss/powerpc-freebsd.c
+++ b/usr.bin/truss/powerpc-freebsd.c
@@ -112,7 +112,7 @@ powerpc_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp)
static struct procabi powerpc_freebsd = {
"FreeBSD ELF32",
- FREEBSD,
+ SYSDECODE_ABI_FREEBSD,
powerpc_fetch_args,
powerpc_fetch_retval
};
diff --git a/usr.bin/truss/powerpc64-freebsd.c b/usr.bin/truss/powerpc64-freebsd.c
index 68a0b5d36abe..cc64cd685e7e 100644
--- a/usr.bin/truss/powerpc64-freebsd.c
+++ b/usr.bin/truss/powerpc64-freebsd.c
@@ -108,7 +108,7 @@ powerpc64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp)
static struct procabi powerpc64_freebsd = {
"FreeBSD ELF64",
- FREEBSD,
+ SYSDECODE_ABI_FREEBSD,
powerpc64_fetch_args,
powerpc64_fetch_retval
};
diff --git a/usr.bin/truss/powerpc64-freebsd32.c b/usr.bin/truss/powerpc64-freebsd32.c
index ee37ead3cc11..c6f3b10a7092 100644
--- a/usr.bin/truss/powerpc64-freebsd32.c
+++ b/usr.bin/truss/powerpc64-freebsd32.c
@@ -117,7 +117,7 @@ powerpc64_freebsd32_fetch_retval(struct trussinfo *trussinfo, long *retval, int
static struct procabi powerpc64_freebsd32 = {
"FreeBSD ELF32",
- FREEBSD32,
+ SYSDECODE_ABI_FREEBSD32,
powerpc64_freebsd32_fetch_args,
powerpc64_freebsd32_fetch_retval
};
diff --git a/usr.bin/truss/sparc64-freebsd.c b/usr.bin/truss/sparc64-freebsd.c
index 23486d76baa4..a8569c010e06 100644
--- a/usr.bin/truss/sparc64-freebsd.c
+++ b/usr.bin/truss/sparc64-freebsd.c
@@ -115,7 +115,7 @@ sparc64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp)
static struct procabi sparc64_freebsd = {
"FreeBSD ELF64",
- FREEBSD,
+ SYSDECODE_ABI_FREEBSD,
sparc64_fetch_args,
sparc64_fetch_retval
};
diff --git a/usr.sbin/bsdconfig/bsdconfig b/usr.sbin/bsdconfig/bsdconfig
index 993865cacc8c..2ecdb30bc5a9 100755
--- a/usr.sbin/bsdconfig/bsdconfig
+++ b/usr.sbin/bsdconfig/bsdconfig
@@ -212,7 +212,7 @@ dialog_menu_main()
*) menu_program="$menuitem/$menu_program"
esac
- tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 )
+ f_substr -v tag "$DIALOG_MENU_TAGS" $index 1
setvar "menu_program$tag" "$menu_program"
f_shell_escape "$menu_title" menu_title
@@ -256,7 +256,7 @@ dialog_menu_main()
*) menu_program="$BSDCFG_LOCAL_LIBE/$menuitem/$menu_program"
esac
- tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 )
+ f_substr -v tag "$DIALOG_MENU_TAGS" $index 1
setvar "menu_program$tag" "$menu_program"
f_shell_escape "$menu_title" menu_title
diff --git a/usr.sbin/bsdconfig/networking/share/media.subr b/usr.sbin/bsdconfig/networking/share/media.subr
index 1cb77f802948..028944b5eb6b 100644
--- a/usr.sbin/bsdconfig/networking/share/media.subr
+++ b/usr.sbin/bsdconfig/networking/share/media.subr
@@ -180,18 +180,18 @@ f_dialog_menu_media_options()
f_ifconfig_media $interface | \
( index=1
- echo "'$( f_substr "$DIALOG_MENU_TAGS" $index 1 )'"
- echo "'$opt_none'"
+ f_substr -v tagn "$DIALOG_MENU_TAGS" $index 1
+ echo "'$tagn' '$opt_none'"
index=$(( $index + 1 ))
- echo "'$( f_substr "$DIALOG_MENU_TAGS" $index 1 )'"
- echo "'$opt_cust'"
+ f_substr -v tagn "$DIALOG_MENU_TAGS" $index 1
+ echo "'$tagn' '$opt_cust'"
index=$(( $index + 1 ))
while read media_options; do
[ $index -lt ${#DIALOG_MENU_TAGS} ] || break
- echo "'$( f_substr "$DIALOG_MENU_TAGS" $index 1 )'"
- echo "'$media_options'"
+ f_substr -v tagn "$DIALOG_MENU_TAGS" $index 1
+ echo "'$tagn' '$media_options'"
index=$(( $index + 1 ))
done
)
diff --git a/usr.sbin/bsdconfig/networking/share/resolv.subr b/usr.sbin/bsdconfig/networking/share/resolv.subr
index fc42e1265c9c..779863c9981d 100644
--- a/usr.sbin/bsdconfig/networking/share/resolv.subr
+++ b/usr.sbin/bsdconfig/networking/share/resolv.subr
@@ -441,7 +441,7 @@ f_dialog_menu_nameservers()
for ns in $nameservers; do
[ $index -lt ${#DIALOG_MENU_TAGS} ] || break
- tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 )
+ f_substr -v tag "$DIALOG_MENU_TAGS" $index 1
echo "'$tag nameserver' '$ns'"
index=$(( $index + 1 ))
done
diff --git a/usr.sbin/bsdconfig/share/common.subr b/usr.sbin/bsdconfig/share/common.subr
index 599644637922..2b911fcec668 100644
--- a/usr.sbin/bsdconfig/share/common.subr
+++ b/usr.sbin/bsdconfig/share/common.subr
@@ -1,7 +1,7 @@
if [ ! "$_COMMON_SUBR" ]; then _COMMON_SUBR=1
#
# Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2015 Devin Teske
+# Copyright (c) 2012-2016 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -1015,10 +1015,9 @@ f_count_ifs()
#
# Trap signals so we can recover gracefully
#
-trap 'f_interrupt' SIGINT
-trap 'f_die' SIGTERM SIGPIPE SIGXCPU SIGXFSZ \
- SIGFPE SIGTRAP SIGABRT SIGSEGV
-trap '' SIGALRM SIGPROF SIGUSR1 SIGUSR2 SIGHUP SIGVTALRM
+trap 'f_interrupt' INT
+trap 'f_die' TERM PIPE XCPU XFSZ FPE TRAP ABRT SEGV
+trap '' ALRM PROF USR1 USR2 HUP VTALRM
#
# Clone terminal stdout/stderr so we can redirect to it from within sub-shells
diff --git a/usr.sbin/bsdconfig/share/device.subr b/usr.sbin/bsdconfig/share/device.subr
index d95684dc702e..97c3ecd99586 100644
--- a/usr.sbin/bsdconfig/share/device.subr
+++ b/usr.sbin/bsdconfig/share/device.subr
@@ -1,6 +1,6 @@
if [ ! "$_DEVICE_SUBR" ]; then _DEVICE_SUBR=1
#
-# Copyright (c) 2012-2014 Devin Teske
+# Copyright (c) 2012-2016 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -1032,7 +1032,7 @@ f_device_is_active()
#
f_device_find()
{
- local OPTIND OPTARG flag only_one=
+ local OPTIND=1 OPTARG flag only_one=
while getopts 1 flag; do
case "$flag" in
1) only_one=1 ;;
diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr
index e0cd7e0a1d5a..f33f4df566ad 100644
--- a/usr.sbin/bsdconfig/share/strings.subr
+++ b/usr.sbin/bsdconfig/share/strings.subr
@@ -1,6 +1,6 @@
if [ ! "$_STRINGS_SUBR" ]; then _STRINGS_SUBR=1
#
-# Copyright (c) 2006-2013 Devin Teske
+# Copyright (c) 2006-2016 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -52,48 +52,73 @@ VALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"
############################################################ FUNCTIONS
-# f_substr "$string" $start [$length]
+# f_isinteger $arg
#
-# Simple wrapper to awk(1)'s `substr' function.
+# Returns true if argument is a positive/negative whole integer.
#
-f_substr()
+f_isinteger()
{
- local string="$1" start="${2:-0}" len="${3:-0}"
- echo "$string" | awk "{ print substr(\$0, $start, $len) }"
+ local arg="${1#-}"
+ [ "${arg:-x}" = "${arg%[!0-9]*}" ]
}
-# f_snprintf $var_to_set $size $format [$arguments ...]
+# f_substr [-v $var_to_set] $string $start [$length]
#
-# Similar to snprintf(3), write at most $size number of bytes into $var_to_set
-# using printf(1) syntax (`$format [$arguments ...]'). The value of $var_to_set
-# is NULL unless at-least one byte is stored from the output.
+# Similar to awk(1)'s substr(), return length substring of string that begins
+# at start position counted from 1.
#
-f_snprintf()
-{
- local __funcname=f_snprintf
- local __var_to_set="$1" __size="$2"
- shift 2 # var_to_set size
-
- if [ "$__size" -eq 0 ] 2> /dev/null; then
- setvar "$__var_to_set" ""
- return ${SUCCESS:-0}
- elif [ $? -ge 2 ] || [ $__size -lt 0 ]; then
- setvar "$__var_to_set" ""
- echo "$__funcname: invalid size argument \`__size'" >&2
- return ${FAILURE:-1}
- fi
-
- local __f_snprintf_tmp
- f_sprintf __f_snprintf_tmp "$@"
+case "$BASH_VERSION" in
+*?*)
+ f_substr()
+ {
+ local __var_to_set=
+ case "$1" in
+ -v) __var_to_set="$2"; shift 2 ;;
+ -v?*) __var_to_set="${2#-v}"; shift 1 ;;
+ esac
+ local __tmp="$1" __start="${2:-1}" __len="$3"
+ [ "$__start" -gt 0 ] 2> /dev/null &&
+ __start=$(( $__start - 1 ))
+ if [ ! "$__var_to_set" ]; then
+ eval echo \"\${__tmp:\$__start${__len:+:\$__len}}\"
+ return $?
+ fi
+ if [ "$__len" ]; then
+ eval $__var_to_set=\"\${__tmp:\$__start:\$__len}\"
+ else
+ eval $__var_to_set=\"\${__tmp:\$__start}\"
+ fi
+ }
+ ;;
+*)
+ # NB: On FreeBSD, sh(1) runs this faster than bash(1) runs the above
+ f_substr()
+ {
+ local OPTIND=1 OPTARG __flag __var_to_set=
+ while getopts v: __flag; do
+ case "$__flag" in
+ v) __var_to_set="$OPTARG" ;;
+ esac
+ done
+ shift $(( $OPTIND - 1 ))
+
+ local __tmp="$1" __start="${2:-1}" __size="$3"
+ local __tbuf __tbuf_len __trim __trimq
+
+ if [ ! "$__tmp" ]; then
+ [ "$__var_to_set" ] && setvar "$__var_to_set" ""
+ return ${SUCCESS:-0}
+ fi
+ [ "$__start" -ge 1 ] 2> /dev/null || __start=1
+ if ! [ "${__size:-1}" -ge 1 ] 2> /dev/null; then
+ [ "$__var_to_set" ] && setvar "$__var_to_set" ""
+ return ${FAILURE:-1}
+ fi
- local __tmp_size=${#__f_snprintf_tmp}
- local __trim=$(( $__tmp_size - $__size )) __trimq
- local __tbuf __tbuf_len
- local __mask __mask_len
- while [ $__trim -gt 0 ]; do
- __tbuf="?"
- __tbuf_len=1
- if [ $__trim -le $__size ]; then
+ __trim=$(( $__start - 1 ))
+ while [ $__trim -gt 0 ]; do
+ __tbuf="?"
+ __tbuf_len=1
while [ $__tbuf_len -lt $(( $__trim / $__tbuf_len )) ]
do
__tbuf="$__tbuf?"
@@ -102,43 +127,115 @@ f_snprintf()
__trimq=$(( $__trim / $__tbuf_len ))
__trim=$(( $__trim - $__tbuf_len * $__trimq ))
while [ $__trimq -gt 0 ]; do
- __f_snprintf_tmp="${__f_snprintf_tmp%$__tbuf}"
+ __tmp="${__tmp#$__tbuf}"
__trimq=$(( $__trimq - 1 ))
done
- else
- __mask="$__f_snprintf_tmp"
- while [ $__tbuf_len -lt $(( $__size / $__tbuf_len )) ]
- do
- __tbuf="$__tbuf?"
- __tbuf_len=$(( $__tbuf_len + 1 ))
- done
- __trimq=$(( $__size / $__tbuf_len ))
- if [ $(( $__trimq * $__tbuf_len )) -ne $__size ]; then
- __tbuf="$__tbuf?"
- __tbuf_len=$(( $__tbuf_len + 1 ))
+ done
+
+ local __tmp_size=${#__tmp}
+ local __mask __mask_len
+ __trim=$(( $__tmp_size - ${__size:-$__tmp_size} ))
+ while [ $__trim -gt 0 ]; do
+ __tbuf="?"
+ __tbuf_len=1
+ if [ $__trim -le $__size ]; then
+ while [ $__tbuf_len -lt $((
+ $__trim / $__tbuf_len
+ )) ]; do
+ __tbuf="$__tbuf?"
+ __tbuf_len=$(( $__tbuf_len + 1 ))
+ done
+ __trimq=$(( $__trim / $__tbuf_len ))
+ __trim=$(( $__trim - $__tbuf_len * $__trimq ))
+ while [ $__trimq -gt 0 ]; do
+ __tmp="${__tmp%$__tbuf}"
+ __trimq=$(( $__trimq - 1 ))
+ done
+ else
+ __mask="$__tmp"
+ while [ $__tbuf_len -lt $((
+ $__size / $__tbuf_len
+ )) ]; do
+ __tbuf="$__tbuf?"
+ __tbuf_len=$(( $__tbuf_len + 1 ))
+ done
+ __trimq=$(( $__size / $__tbuf_len ))
+ if [ $__size -ne $((
+ $__trimq * $__tbuf_len
+ )) ]; then
+ __tbuf="$__tbuf?"
+ __tbuf_len=$(( $__tbuf_len + 1 ))
+ fi
+ __mask_len=$((
+ $__tmp_size - $__tbuf_len * $__trimq
+ ))
+ __trim=$((
+ $__tmp_size - $__mask_len - $__size
+ ))
+ while [ $__trimq -gt 0 ]; do
+ __mask="${__mask#$__tbuf}"
+ __trimq=$(( $__trimq - 1 ))
+ done
+ __tmp="${__tmp%"$__mask"}"
fi
- __mask_len=$(( $__tmp_size - $__tbuf_len * $__trimq ))
- __trim=$(( $__tmp_size - $__mask_len - $__size ))
- while [ $__trimq -gt 0 ]; do
- __mask="${__mask#$__tbuf}"
- __trimq=$(( $__trimq - 1 ))
- done
- __f_snprintf_tmp="${__f_snprintf_tmp%"$__mask"}"
+ done
+
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__tmp"
+ else
+ echo "$__tmp"
fi
- done
- setvar "$__var_to_set" "$__f_snprintf_tmp"
-}
+ }
+esac
# f_sprintf $var_to_set $format [$arguments ...]
#
# Similar to sprintf(3), write a string into $var_to_set using printf(1) syntax
# (`$format [$arguments ...]').
#
-f_sprintf()
+case "$BASH_VERSION" in
+3.1*|4.*)
+ f_sprintf()
+ {
+ local __var_to_set="$1" __tmp
+ shift 1 # var_to_set
+ printf -v __tmp "$@"
+ eval "$__var_to_set"=\"\${__tmp%\$NL}\"
+ }
+ ;;
+*)
+ # NB: On FreeBSD, sh(1) runs this faster than bash(1) runs the above
+ f_sprintf()
+ {
+ local __var_to_set="$1"
+ shift 1 # var_to_set
+ eval "$__var_to_set"=\$\( printf -- \"\$@\" \)
+ }
+esac
+
+# f_vsprintf $var_to_set $format $format_args
+#
+# Similar to vsprintf(3), write a string into $var_to_set using printf(1)
+# syntax (`$format $format_args').
+#
+f_vsprintf()
{
- local __var_to_set="$1"
- shift 1 # var_to_set
- eval "$__var_to_set"=\$\( printf -- \"\$@\" \)
+ eval f_sprintf \"\$1\" \"\$2\" $3
+}
+
+# f_snprintf $var_to_set $size $format [$arguments ...]
+#
+# Similar to snprintf(3), write at most $size number of bytes into $var_to_set
+# using printf(1) syntax (`$format [$arguments ...]').
+#
+f_snprintf()
+{
+ local __var_to_set="$1" __size="$2"
+ shift 2 # var_to_set size
+
+ local __f_snprintf_tmp
+ f_sprintf __f_snprintf_tmp "$@"
+ f_substr "$__var_to_set" "$__f_snprintf_tmp" 1 "$__size"
}
# f_vsnprintf $var_to_set $size $format $format_args
@@ -176,140 +273,6 @@ f_vsnprintf()
eval f_snprintf \"\$1\" \"\$2\" \"\$3\" $4
}
-# f_vsprintf $var_to_set $format $format_args
-#
-# Similar to vsprintf(3), write a string into $var_to_set using printf(1)
-# syntax (`$format $format_args').
-#
-f_vsprintf()
-{
- eval f_sprintf \"\$1\" \"\$2\" $3
-}
-
-# f_longest_line_length
-#
-# Simple wrapper to an awk(1) script to print the length of the longest line of
-# input (read from stdin). Supports the newline escape-sequence `\n' for
-# splitting a single line into multiple lines.
-#
-f_longest_line_length_awk='
-BEGIN { longest = 0 }
-{
- if (split($0, lines, /\\n/) > 1)
- {
- for (n in lines)
- {
- len = length(lines[n])
- longest = ( len > longest ? len : longest )
- }
- }
- else
- {
- len = length($0)
- longest = ( len > longest ? len : longest )
- }
-}
-END { print longest }
-'
-f_longest_line_length()
-{
- awk "$f_longest_line_length_awk"
-}
-
-# f_number_of_lines
-#
-# Simple wrapper to an awk(1) script to print the number of lines read from
-# stdin. Supports newline escape-sequence `\n' for splitting a single line into
-# multiple lines.
-#
-f_number_of_lines_awk='
-BEGIN { num_lines = 0 }
-{
- num_lines += split(" "$0, unused, /\\n/)
-}
-END { print num_lines }
-'
-f_number_of_lines()
-{
- awk "$f_number_of_lines_awk"
-}
-
-# f_isinteger $arg
-#
-# Returns true if argument is a positive/negative whole integer.
-#
-f_isinteger()
-{
- local arg="${1#-}"
- [ "${arg:-x}" = "${arg%[!0-9]*}" ]
-}
-
-# f_uriencode [$text]
-#
-# Encode $text for the purpose of embedding safely into a URL. Non-alphanumeric
-# characters are converted to `%XX' sequence where XX represents the hexa-
-# decimal ordinal of the non-alphanumeric character. If $text is missing, data
-# is instead read from standard input.
-#
-f_uriencode_awk='
-BEGIN {
- output = ""
- for (n = 0; n < 256; n++) pack[sprintf("%c", n)] = sprintf("%%%02x", n)
-}
-{
- sline = ""
- slen = length($0)
- for (n = 1; n <= slen; n++) {
- char = substr($0, n, 1)
- if ( char !~ /^[[:alnum:]_]$/ ) char = pack[char]
- sline = sline char
- }
- output = output ( output ? "%0a" : "" ) sline
-}
-END { print output }
-'
-f_uriencode()
-{
- if [ $# -gt 0 ]; then
- echo "$1" | awk "$f_uriencode_awk"
- else
- awk "$f_uriencode_awk"
- fi
-}
-
-# f_uridecode [$text]
-#
-# Decode $text from a URI. Encoded characters are converted from their `%XX'
-# sequence into original unencoded ASCII sequences. If $text is missing, data
-# is instead read from standard input.
-#
-f_uridecode_awk='
-BEGIN { for (n = 0; n < 256; n++) chr[n] = sprintf("%c", n) }
-{
- sline = ""
- slen = length($0)
- for (n = 1; n <= slen; n++)
- {
- seq = substr($0, n, 3)
- if ( seq ~ /^%[[:xdigit:]][[:xdigit:]]$/ ) {
- hex = substr(seq, 2, 2)
- sline = sline chr[sprintf("%u", "0x"hex)]
- n += 2
- } else
- sline = sline substr(seq, 1, 1)
- }
- print sline
-}
-'
-f_uridecode()
-{
- if [ $# -gt 0 ]; then
- echo "$1" | awk "$f_uridecode_awk"
- else
- awk "$f_uridecode_awk"
- fi
-}
-
# f_replaceall $string $find $replace [$var_to_set]
#
# Replace all occurrences of $find in $string with $replace. If $var_to_set is
@@ -493,6 +456,120 @@ f_expand_number()
fi
}
+# f_longest_line_length
+#
+# Simple wrapper to an awk(1) script to print the length of the longest line of
+# input (read from stdin). Supports the newline escape-sequence `\n' for
+# splitting a single line into multiple lines.
+#
+f_longest_line_length_awk='
+BEGIN { longest = 0 }
+{
+ if (split($0, lines, /\\n/) > 1)
+ {
+ for (n in lines)
+ {
+ len = length(lines[n])
+ longest = ( len > longest ? len : longest )
+ }
+ }
+ else
+ {
+ len = length($0)
+ longest = ( len > longest ? len : longest )
+ }
+}
+END { print longest }
+'
+f_longest_line_length()
+{
+ awk "$f_longest_line_length_awk"
+}
+
+# f_number_of_lines
+#
+# Simple wrapper to an awk(1) script to print the number of lines read from
+# stdin. Supports newline escape-sequence `\n' for splitting a single line into
+# multiple lines.
+#
+f_number_of_lines_awk='
+BEGIN { num_lines = 0 }
+{
+ num_lines += split(" "$0, unused, /\\n/)
+}
+END { print num_lines }
+'
+f_number_of_lines()
+{
+ awk "$f_number_of_lines_awk"
+}
+
+# f_uriencode [$text]
+#
+# Encode $text for the purpose of embedding safely into a URL. Non-alphanumeric
+# characters are converted to `%XX' sequence where XX represents the hexa-
+# decimal ordinal of the non-alphanumeric character. If $text is missing, data
+# is instead read from standard input.
+#
+f_uriencode_awk='
+BEGIN {
+ output = ""
+ for (n = 0; n < 256; n++) pack[sprintf("%c", n)] = sprintf("%%%02x", n)
+}
+{
+ sline = ""
+ slen = length($0)
+ for (n = 1; n <= slen; n++) {
+ char = substr($0, n, 1)
+ if ( char !~ /^[[:alnum:]_]$/ ) char = pack[char]
+ sline = sline char
+ }
+ output = output ( output ? "%0a" : "" ) sline
+}
+END { print output }
+'
+f_uriencode()
+{
+ if [ $# -gt 0 ]; then
+ echo "$1" | awk "$f_uriencode_awk"
+ else
+ awk "$f_uriencode_awk"
+ fi
+}
+
+# f_uridecode [$text]
+#
+# Decode $text from a URI. Encoded characters are converted from their `%XX'
+# sequence into original unencoded ASCII sequences. If $text is missing, data
+# is instead read from standard input.
+#
+f_uridecode_awk='
+BEGIN { for (n = 0; n < 256; n++) chr[n] = sprintf("%c", n) }
+{
+ sline = ""
+ slen = length($0)
+ for (n = 1; n <= slen; n++)
+ {
+ seq = substr($0, n, 3)
+ if ( seq ~ /^%[[:xdigit:]][[:xdigit:]]$/ ) {
+ hex = substr(seq, 2, 2)
+ sline = sline chr[sprintf("%u", "0x"hex)]
+ n += 2
+ } else
+ sline = sline substr(seq, 1, 1)
+ }
+ print sline
+}
+'
+f_uridecode()
+{
+ if [ $# -gt 0 ]; then
+ echo "$1" | awk "$f_uridecode_awk"
+ else
+ awk "$f_uridecode_awk"
+ fi
+}
+
############################################################ MAIN
f_dprintf "%s: Successfully loaded." strings.subr
diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot
index 5c3fc8011aa5..ed93c370bf2b 100755
--- a/usr.sbin/bsdinstall/scripts/zfsboot
+++ b/usr.sbin/bsdinstall/scripts/zfsboot
@@ -109,7 +109,12 @@ f_include $BSDCFG_SHARE/variable.subr
#
# Default partitioning scheme to use on disks
#
-: ${ZFSBOOT_PARTITION_SCHEME:=GPT}
+: ${ZFSBOOT_PARTITION_SCHEME:=}
+
+#
+# Default partitioning scheme to use on disks
+#
+: ${ZFSBOOT_BOOT_TYPE:=}
#
# How much swap to put on each block device in the boot zpool
@@ -193,6 +198,7 @@ GPART_ADD_ALIGN_LABEL='gpart add %s -l %s -t %s "%s"'
GPART_ADD_ALIGN_LABEL_WITH_SIZE='gpart add %s -l %s -t %s -s %s "%s"'
GPART_BOOTCODE='gpart bootcode -b "%s" "%s"'
GPART_BOOTCODE_PART='gpart bootcode -b "%s" -p "%s" -i %s "%s"'
+GPART_BOOTCODE_PARTONLY='gpart bootcode -p "%s" -i %s "%s"'
GPART_CREATE='gpart create -s %s "%s"'
GPART_DESTROY_F='gpart destroy -F "%s"'
GPART_SET_ACTIVE='gpart set -a active -i %s "%s"'
@@ -297,7 +303,6 @@ msg_swap_size="Swap Size"
msg_swap_size_help="Customize how much swap space is allocated to each selected disk"
msg_swap_toosmall="The selected swap size (%s) is to small. Please enter a value greater than 100MB or enter 0 for no swap"
msg_these_disks_are_too_small="These disks are too small given the amount of requested\nswap (%s) and/or geli(8) (%s) partitions, which would\ntake 50%% or more of each of the following selected disk\ndevices (not recommended):\n\n %s\n\nRecommend changing partition size(s) and/or selecting a\ndifferent set of devices."
-msg_uefi_not_supported="The FreeBSD UEFI loader does not currently support booting root-on-ZFS. Your system will need to boot in legacy (CSM) mode.\nDo you want to continue?"
msg_unable_to_get_disk_capacity="Unable to get disk capacity of \`%s'"
msg_unsupported_partition_scheme="%s is an unsupported partition scheme"
msg_user_cancelled="User Cancelled."
@@ -345,7 +350,7 @@ dialog_menu_main()
'E $msg_encrypt_disks' '$usegeli'
'$msg_encrypt_disks_help'
'P $msg_partition_scheme'
- '$ZFSBOOT_PARTITION_SCHEME'
+ '$ZFSBOOT_PARTITION_SCHEME ($ZFSBOOT_BOOT_TYPE)'
'$msg_partition_scheme_help'
'S $msg_swap_size' '$ZFSBOOT_SWAP_SIZE'
'$msg_swap_size_help'
@@ -695,48 +700,6 @@ dialog_menu_layout()
return $DIALOG_OK
}
-# dialog_uefi_prompt
-#
-# Confirm that the user wants to continue with the installation on a BIOS
-# system when they have booted with UEFI
-#
-dialog_uefi_prompt()
-{
- local title="$DIALOG_TITLE"
- local btitle="$DIALOG_BACKTITLE"
- local prompt # Calculated below
- local hline="$hline_arrows_tab_enter"
-
- local height=8 width=50 prefix=" "
- local plen=${#prefix} list= line=
- local max_width=$(( $width - 3 - $plen ))
-
- local yes no defaultno extra_args format
- if [ "$USE_XDIALOG" ]; then
- yes=ok no=cancel defaultno=default-no
- extra_args="--wrap --left"
- format="$msg_uefi_not_supported"
- else
- yes=yes no=no defaultno=defaultno
- extra_args="--cr-wrap"
- format="$msg_uefi_not_supported"
- fi
-
- # Add height for Xdialog(1)
- [ "$USE_XDIALOG" ] && height=$(( $height + $height / 5 + 3 ))
-
- prompt=$( printf "$format" )
- f_dprintf "%s: UEFI prompt" "$0"
- $DIALOG \
- --title "$title" \
- --backtitle "$btitle" \
- --hline "$hline" \
- --$yes-label "$msg_yes" \
- --$no-label "$msg_no" \
- $extra_args \
- --yesno "$prompt" $height $width
-}
-
# zfs_create_diskpart $disk $index
#
# For each block device to be used in the zpool, rather than just create the
@@ -848,14 +811,25 @@ zfs_create_diskpart()
fi
#
- # 2. Add small freebsd-boot partition labeled `boot#'
+ # 2. Add small freebsd-boot or efi partition
#
- f_eval_catch $funcname gpart "$GPART_ADD_ALIGN_LABEL_WITH_SIZE" \
- "$align_small" gptboot$index freebsd-boot 512k $disk ||
- return $FAILURE
- f_eval_catch $funcname gpart "$GPART_BOOTCODE_PART" \
- /boot/pmbr /boot/gptzfsboot 1 $disk ||
- return $FAILURE
+ if [ "$ZFSBOOT_BOOT_TYPE" = "UEFI" ]; then
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_ALIGN_LABEL_WITH_SIZE" \
+ "$align_small" efiboot$index efi 800k $disk ||
+ return $FAILURE
+ f_eval_catch $funcname gpart "$GPART_BOOTCODE_PARTONLY" \
+ /boot/boot1.efifat 1 $disk ||
+ return $FAILURE
+ else
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_ALIGN_LABEL_WITH_SIZE" \
+ "$align_small" gptboot$index freebsd-boot \
+ 512k $disk || return $FAILURE
+ f_eval_catch $funcname gpart "$GPART_BOOTCODE_PART" \
+ /boot/pmbr /boot/gptzfsboot 1 $disk ||
+ return $FAILURE
+ fi
# NB: zpool will use the `zfs#' GPT labels
bootpart=p2 swappart=p2 targetpart=p2
@@ -1463,18 +1437,16 @@ f_dprintf "BSDINSTALL_TMPETC=[%s]" "$BSDINSTALL_TMPETC"
f_dprintf "FSTAB_FMT=[%s]" "$FSTAB_FMT"
#
-# If the system was booted with UEFI, warn the user that FreeBSD can't do
-# ZFS with UEFI yet
+# If the system was booted with UEFI, set the default boot type to UEFI
#
-if f_interactive; then
- bootmethod=$( sysctl -n machdep.bootmethod )
- f_dprintf "machdep.bootmethod=[%s]" "$bootmethod"
- if [ "$bootmethod" != "BIOS" ]; then
- dialog_uefi_prompt
- retval=$?
- f_dprintf "uefi_prompt=[%s]" "$retval"
- [ $retval -eq $DIALOG_OK ] || f_die
- fi
+bootmethod=$( sysctl -n machdep.bootmethod )
+f_dprintf "machdep.bootmethod=[%s]" "$bootmethod"
+if [ "$bootmethod" = "UEFI" ]; then
+ : ${ZFSBOOT_BOOT_TYPE:=UEFI}
+ : ${ZFSBOOT_PARTITION_SCHEME:=GPT}
+else
+ : ${ZFSBOOT_BOOT_TYPE:=BIOS}
+ : ${ZFSBOOT_PARTITION_SCHEME:=GPT}
fi
#
@@ -1596,15 +1568,22 @@ while :; do
fi
;;
?" $msg_partition_scheme")
- # Toggle between GPT and MBR
- if [ "$ZFSBOOT_PARTITION_SCHEME" = GPT ]; then
- ZFSBOOT_PARTITION_SCHEME=MBR
- elif [ "$ZFSBOOT_PARTITION_SCHEME" = MBR ]; then
+ # Toggle between GPT (BIOS), GPT (UEFI) and MBR
+ if [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT" -a "$ZFSBOOT_BOOT_TYPE" = "BIOS" ]; then
+ ZFSBOOT_PARTITION_SCHEME="GPT"
+ ZFSBOOT_BOOT_TYPE="UEFI"
+ elif [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT" ]; then
+ ZFSBOOT_PARTITION_SCHEME="MBR"
+ ZFSBOOT_BOOT_TYPE="BIOS"
+ elif [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then
ZFSBOOT_PARTITION_SCHEME="GPT + Active"
+ ZFSBOOT_BOOT_TYPE="BIOS"
elif [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT + Active" ]; then
ZFSBOOT_PARTITION_SCHEME="GPT + Lenovo Fix"
+ ZFSBOOT_BOOT_TYPE="BIOS"
else
- ZFSBOOT_PARTITION_SCHEME=GPT
+ ZFSBOOT_PARTITION_SCHEME="GPT"
+ ZFSBOOT_BOOT_TYPE="BIOS"
fi
;;
?" $msg_swap_size")
diff --git a/usr.sbin/ctld/Makefile b/usr.sbin/ctld/Makefile
index 6169d308ef2c..664dc22efbb1 100644
--- a/usr.sbin/ctld/Makefile
+++ b/usr.sbin/ctld/Makefile
@@ -1,8 +1,11 @@
# $FreeBSD$
+CFLAGS+=-I${.CURDIR}/../../contrib/libucl/include
+.PATH: ${.CURDIR}/../../contrib/libucl/include
+
PROG= ctld
SRCS= chap.c ctld.c discovery.c isns.c kernel.c keys.c log.c
-SRCS+= login.c parse.y pdu.c token.l y.tab.h
+SRCS+= login.c parse.y pdu.c token.l y.tab.h uclparse.c
CFLAGS+= -I${.CURDIR}
CFLAGS+= -I${.CURDIR}/../../sys
CFLAGS+= -I${.CURDIR}/../../sys/cam/ctl
@@ -10,7 +13,7 @@ CFLAGS+= -I${.CURDIR}/../../sys/dev/iscsi
#CFLAGS+= -DICL_KERNEL_PROXY
MAN= ctld.8 ctl.conf.5
-LIBADD= bsdxml l md sbuf util
+LIBADD= bsdxml l md sbuf util ucl m
YFLAGS+= -v
CLEANFILES= y.tab.c y.tab.h y.output
diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c
index 92fa5539f7f6..6c8b4a89fe93 100644
--- a/usr.sbin/ctld/ctld.c
+++ b/usr.sbin/ctld/ctld.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -2491,6 +2492,104 @@ register_signals(void)
log_err(1, "sigaction");
}
+static void
+check_perms(const char *path)
+{
+ struct stat sb;
+ int error;
+
+ error = stat(path, &sb);
+ if (error != 0) {
+ log_warn("stat");
+ return;
+ }
+ if (sb.st_mode & S_IWOTH) {
+ log_warnx("%s is world-writable", path);
+ } else if (sb.st_mode & S_IROTH) {
+ log_warnx("%s is world-readable", path);
+ } else if (sb.st_mode & S_IXOTH) {
+ /*
+ * Ok, this one doesn't matter, but still do it,
+ * just for consistency.
+ */
+ log_warnx("%s is world-executable", path);
+ }
+
+ /*
+ * XXX: Should we also check for owner != 0?
+ */
+}
+
+static struct conf *
+conf_new_from_file(const char *path, struct conf *oldconf, bool ucl)
+{
+ struct conf *conf;
+ struct auth_group *ag;
+ struct portal_group *pg;
+ struct pport *pp;
+ int error;
+
+ log_debugx("obtaining configuration from %s", path);
+
+ conf = conf_new();
+
+ TAILQ_FOREACH(pp, &oldconf->conf_pports, pp_next)
+ pport_copy(pp, conf);
+
+ ag = auth_group_new(conf, "default");
+ assert(ag != NULL);
+
+ ag = auth_group_new(conf, "no-authentication");
+ assert(ag != NULL);
+ ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
+
+ ag = auth_group_new(conf, "no-access");
+ assert(ag != NULL);
+ ag->ag_type = AG_TYPE_DENY;
+
+ pg = portal_group_new(conf, "default");
+ assert(pg != NULL);
+
+ if (ucl)
+ error = uclparse_conf(conf, path);
+ else
+ error = parse_conf(conf, path);
+
+ if (error != 0) {
+ conf_delete(conf);
+ return (NULL);
+ }
+
+ check_perms(path);
+
+ if (conf->conf_default_ag_defined == false) {
+ log_debugx("auth-group \"default\" not defined; "
+ "going with defaults");
+ ag = auth_group_find(conf, "default");
+ assert(ag != NULL);
+ ag->ag_type = AG_TYPE_DENY;
+ }
+
+ if (conf->conf_default_pg_defined == false) {
+ log_debugx("portal-group \"default\" not defined; "
+ "going with defaults");
+ pg = portal_group_find(conf, "default");
+ assert(pg != NULL);
+ portal_group_add_listen(pg, "0.0.0.0:3260", false);
+ portal_group_add_listen(pg, "[::]:3260", false);
+ }
+
+ conf->conf_kernel_port_on = true;
+
+ error = conf_verify(conf);
+ if (error != 0) {
+ conf_delete(conf);
+ return (NULL);
+ }
+
+ return (conf);
+}
+
int
main(int argc, char **argv)
{
@@ -2499,13 +2598,17 @@ main(int argc, char **argv)
const char *config_path = DEFAULT_CONFIG_PATH;
int debug = 0, ch, error;
bool dont_daemonize = false;
+ bool use_ucl = false;
- while ((ch = getopt(argc, argv, "df:R")) != -1) {
+ while ((ch = getopt(argc, argv, "duf:R")) != -1) {
switch (ch) {
case 'd':
dont_daemonize = true;
debug++;
break;
+ case 'u':
+ use_ucl = true;
+ break;
case 'f':
config_path = optarg;
break;
@@ -2529,7 +2632,8 @@ main(int argc, char **argv)
kernel_init();
oldconf = conf_new_from_kernel();
- newconf = conf_new_from_file(config_path, oldconf);
+ newconf = conf_new_from_file(config_path, oldconf, use_ucl);
+
if (newconf == NULL)
log_errx(1, "configuration error; exiting");
if (debug > 0) {
@@ -2564,7 +2668,9 @@ main(int argc, char **argv)
if (sighup_received) {
sighup_received = false;
log_debugx("received SIGHUP, reloading configuration");
- tmpconf = conf_new_from_file(config_path, newconf);
+ tmpconf = conf_new_from_file(config_path, newconf,
+ use_ucl);
+
if (tmpconf == NULL) {
log_warnx("configuration error, "
"continuing with old configuration");
diff --git a/usr.sbin/ctld/ctld.h b/usr.sbin/ctld/ctld.h
index 808b722aa542..e9152329121f 100644
--- a/usr.sbin/ctld/ctld.h
+++ b/usr.sbin/ctld/ctld.h
@@ -297,8 +297,10 @@ int rchap_receive(struct rchap *rchap,
char *rchap_get_response(struct rchap *rchap);
void rchap_delete(struct rchap *rchap);
+int parse_conf(struct conf *conf, const char *path);
+int uclparse_conf(struct conf *conf, const char *path);
+
struct conf *conf_new(void);
-struct conf *conf_new_from_file(const char *path, struct conf *old);
struct conf *conf_new_from_kernel(void);
void conf_delete(struct conf *conf);
int conf_verify(struct conf *conf);
diff --git a/usr.sbin/ctld/parse.y b/usr.sbin/ctld/parse.y
index afbf315bf02d..820b4c7d4bc1 100644
--- a/usr.sbin/ctld/parse.y
+++ b/usr.sbin/ctld/parse.y
@@ -1044,70 +1044,18 @@ yyerror(const char *str)
lineno, yytext, str);
}
-static void
-check_perms(const char *path)
+int
+parse_conf(struct conf *newconf, const char *path)
{
- struct stat sb;
int error;
- error = stat(path, &sb);
- if (error != 0) {
- log_warn("stat");
- return;
- }
- if (sb.st_mode & S_IWOTH) {
- log_warnx("%s is world-writable", path);
- } else if (sb.st_mode & S_IROTH) {
- log_warnx("%s is world-readable", path);
- } else if (sb.st_mode & S_IXOTH) {
- /*
- * Ok, this one doesn't matter, but still do it,
- * just for consistency.
- */
- log_warnx("%s is world-executable", path);
- }
-
- /*
- * XXX: Should we also check for owner != 0?
- */
-}
-
-struct conf *
-conf_new_from_file(const char *path, struct conf *oldconf)
-{
- struct auth_group *ag;
- struct portal_group *pg;
- struct pport *pp;
- int error;
-
- log_debugx("obtaining configuration from %s", path);
-
- conf = conf_new();
-
- TAILQ_FOREACH(pp, &oldconf->conf_pports, pp_next)
- pport_copy(pp, conf);
-
- ag = auth_group_new(conf, "default");
- assert(ag != NULL);
-
- ag = auth_group_new(conf, "no-authentication");
- assert(ag != NULL);
- ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
-
- ag = auth_group_new(conf, "no-access");
- assert(ag != NULL);
- ag->ag_type = AG_TYPE_DENY;
-
- pg = portal_group_new(conf, "default");
- assert(pg != NULL);
-
+ conf = newconf;
yyin = fopen(path, "r");
if (yyin == NULL) {
log_warn("unable to open configuration file %s", path);
- conf_delete(conf);
- return (NULL);
+ return (1);
}
- check_perms(path);
+
lineno = 1;
yyrestart(yyin);
error = yyparse();
@@ -1116,35 +1064,6 @@ conf_new_from_file(const char *path, struct conf *oldconf)
target = NULL;
lun = NULL;
fclose(yyin);
- if (error != 0) {
- conf_delete(conf);
- return (NULL);
- }
-
- if (conf->conf_default_ag_defined == false) {
- log_debugx("auth-group \"default\" not defined; "
- "going with defaults");
- ag = auth_group_find(conf, "default");
- assert(ag != NULL);
- ag->ag_type = AG_TYPE_DENY;
- }
-
- if (conf->conf_default_pg_defined == false) {
- log_debugx("portal-group \"default\" not defined; "
- "going with defaults");
- pg = portal_group_find(conf, "default");
- assert(pg != NULL);
- portal_group_add_listen(pg, "0.0.0.0:3260", false);
- portal_group_add_listen(pg, "[::]:3260", false);
- }
-
- conf->conf_kernel_port_on = true;
-
- error = conf_verify(conf);
- if (error != 0) {
- conf_delete(conf);
- return (NULL);
- }
- return (conf);
+ return (error);
}
diff --git a/usr.sbin/ctld/uclparse.c b/usr.sbin/ctld/uclparse.c
new file mode 100644
index 000000000000..fb2cce0a144e
--- /dev/null
+++ b/usr.sbin/ctld/uclparse.c
@@ -0,0 +1,900 @@
+/*-
+ * Copyright (c) 2015 iXsystems Inc.
+ * All rights reserved.
+ *
+ * This software was developed by Jakub Klama <jceel@FreeBSD.org>
+ * under sponsorship from iXsystems Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ucl.h>
+
+#include "ctld.h"
+
+static struct conf *conf = NULL;
+
+static int uclparse_toplevel(const ucl_object_t *);
+static int uclparse_chap(struct auth_group *, const ucl_object_t *);
+static int uclparse_chap_mutual(struct auth_group *, const ucl_object_t *);
+static int uclparse_lun(const char *, const ucl_object_t *);
+static int uclparse_auth_group(const char *, const ucl_object_t *);
+static int uclparse_portal_group(const char *, const ucl_object_t *);
+static int uclparse_target(const char *, const ucl_object_t *);
+static int uclparse_target_portal_group(struct target *, const ucl_object_t *);
+static int uclparse_target_lun(struct target *, const ucl_object_t *);
+
+static int
+uclparse_chap(struct auth_group *auth_group, const ucl_object_t *obj)
+{
+ const struct auth *ca;
+ const ucl_object_t *user, *secret;
+
+ user = ucl_object_find_key(obj, "user");
+ if (!user || user->type != UCL_STRING) {
+ log_warnx("chap section in auth-group \"%s\" is missing "
+ "\"user\" string key", auth_group->ag_name);
+ return (1);
+ }
+
+ secret = ucl_object_find_key(obj, "secret");
+ if (!secret || secret->type != UCL_STRING) {
+ log_warnx("chap section in auth-group \"%s\" is missing "
+ "\"secret\" string key", auth_group->ag_name);
+ }
+
+ ca = auth_new_chap(auth_group,
+ ucl_object_tostring(user),
+ ucl_object_tostring(secret));
+
+ if (ca == NULL)
+ return (1);
+
+ return (0);
+}
+
+static int
+uclparse_chap_mutual(struct auth_group *auth_group, const ucl_object_t *obj)
+{
+ const struct auth *ca;
+ const ucl_object_t *user, *secret, *mutual_user;
+ const ucl_object_t *mutual_secret;
+
+ user = ucl_object_find_key(obj, "user");
+ if (!user || user->type != UCL_STRING) {
+ log_warnx("chap-mutual section in auth-group \"%s\" is missing "
+ "\"user\" string key", auth_group->ag_name);
+ return (1);
+ }
+
+ secret = ucl_object_find_key(obj, "secret");
+ if (!secret || secret->type != UCL_STRING) {
+ log_warnx("chap-mutual section in auth-group \"%s\" is missing "
+ "\"secret\" string key", auth_group->ag_name);
+ return (1);
+ }
+
+ mutual_user = ucl_object_find_key(obj, "mutual-user");
+ if (!user || user->type != UCL_STRING) {
+ log_warnx("chap-mutual section in auth-group \"%s\" is missing "
+ "\"mutual-user\" string key", auth_group->ag_name);
+ return (1);
+ }
+
+ mutual_secret = ucl_object_find_key(obj, "mutual-secret");
+ if (!secret || secret->type != UCL_STRING) {
+ log_warnx("chap-mutual section in auth-group \"%s\" is missing "
+ "\"mutual-secret\" string key", auth_group->ag_name);
+ return (1);
+ }
+
+ ca = auth_new_chap_mutual(auth_group,
+ ucl_object_tostring(user),
+ ucl_object_tostring(secret),
+ ucl_object_tostring(mutual_user),
+ ucl_object_tostring(mutual_secret));
+
+ if (ca == NULL)
+ return (1);
+
+ return (0);
+}
+
+static int
+uclparse_target_portal_group(struct target *target, const ucl_object_t *obj)
+{
+ struct portal_group *tpg;
+ struct auth_group *tag = NULL;
+ struct port *tp;
+ const ucl_object_t *portal_group, *auth_group;
+
+ portal_group = ucl_object_find_key(obj, "name");
+ if (!portal_group || portal_group->type != UCL_STRING) {
+ log_warnx("portal-group section in target \"%s\" is missing "
+ "\"name\" string key", target->t_name);
+ return (1);
+ }
+
+ auth_group = ucl_object_find_key(obj, "auth-group-name");
+ if (auth_group && auth_group->type != UCL_STRING) {
+ log_warnx("portal-group section in target \"%s\" is missing "
+ "\"auth-group-name\" string key", target->t_name);
+ return (1);
+ }
+
+
+ tpg = portal_group_find(conf, ucl_object_tostring(portal_group));
+ if (tpg == NULL) {
+ log_warnx("unknown portal-group \"%s\" for target "
+ "\"%s\"", ucl_object_tostring(portal_group), target->t_name);
+ return (1);
+ }
+
+ if (auth_group) {
+ tag = auth_group_find(conf, ucl_object_tostring(auth_group));
+ if (tag == NULL) {
+ log_warnx("unknown auth-group \"%s\" for target "
+ "\"%s\"", ucl_object_tostring(auth_group),
+ target->t_name);
+ return (1);
+ }
+ }
+
+ tp = port_new(conf, target, tpg);
+ if (tp == NULL) {
+ log_warnx("can't link portal-group \"%s\" to target "
+ "\"%s\"", ucl_object_tostring(portal_group), target->t_name);
+ return (1);
+ }
+ tp->p_auth_group = tag;
+
+ return (0);
+}
+
+static int
+uclparse_target_lun(struct target *target, const ucl_object_t *obj)
+{
+ struct lun *lun;
+
+ if (obj->type == UCL_INT) {
+ char *name;
+
+ asprintf(&name, "%s,lun,%ju", target->t_name,
+ ucl_object_toint(obj));
+ lun = lun_new(conf, name);
+ if (lun == NULL)
+ return (1);
+
+ lun_set_scsiname(lun, name);
+ target->t_luns[ucl_object_toint(obj)] = lun;
+ return (0);
+ }
+
+ if (obj->type == UCL_OBJECT) {
+ const ucl_object_t *num = ucl_object_find_key(obj, "number");
+ const ucl_object_t *name = ucl_object_find_key(obj, "name");
+
+ if (num == NULL || num->type != UCL_INT) {
+ log_warnx("lun section in target \"%s\" is missing "
+ "\"number\" integer property", target->t_name);
+ return (1);
+ }
+
+ if (name == NULL || name->type != UCL_STRING) {
+ log_warnx("lun section in target \"%s\" is missing "
+ "\"name\" string property", target->t_name);
+ return (1);
+ }
+
+ lun = lun_find(conf, ucl_object_tostring(name));
+ if (lun == NULL)
+ return (1);
+
+ target->t_luns[ucl_object_toint(num)] = lun;
+ }
+
+ return (0);
+}
+
+static int
+uclparse_toplevel(const ucl_object_t *top)
+{
+ ucl_object_iter_t it = NULL, iter = NULL;
+ const ucl_object_t *obj = NULL, *child = NULL;
+ int err = 0;
+
+ /* Pass 1 - everything except targets */
+ while ((obj = ucl_iterate_object(top, &it, true))) {
+ const char *key = ucl_object_key(obj);
+
+ if (!strcmp(key, "debug")) {
+ if (obj->type == UCL_INT)
+ conf->conf_debug = ucl_object_toint(obj);
+ else {
+ log_warnx("\"debug\" property value is not integer");
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "timeout")) {
+ if (obj->type == UCL_INT)
+ conf->conf_timeout = ucl_object_toint(obj);
+ else {
+ log_warnx("\"timeout\" property value is not integer");
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "maxproc")) {
+ if (obj->type == UCL_INT)
+ conf->conf_maxproc = ucl_object_toint(obj);
+ else {
+ log_warnx("\"maxproc\" property value is not integer");
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "pidfile")) {
+ if (obj->type == UCL_STRING)
+ conf->conf_pidfile_path = strdup(
+ ucl_object_tostring(obj));
+ else {
+ log_warnx("\"pidfile\" property value is not string");
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "isns-server")) {
+ if (obj->type == UCL_ARRAY) {
+ iter = NULL;
+ while ((child = ucl_iterate_object(obj, &iter,
+ true))) {
+ if (child->type != UCL_STRING)
+ return (1);
+
+ err = isns_new(conf,
+ ucl_object_tostring(child));
+ if (err != 0) {
+ return (1);
+ }
+ }
+ } else {
+ log_warnx("\"isns-server\" property value is "
+ "not an array");
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "isns-period")) {
+ if (obj->type == UCL_INT)
+ conf->conf_timeout = ucl_object_toint(obj);
+ else {
+ log_warnx("\"isns-period\" property value is not integer");
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "isns-timeout")) {
+ if (obj->type == UCL_INT)
+ conf->conf_timeout = ucl_object_toint(obj);
+ else {
+ log_warnx("\"isns-timeout\" property value is not integer");
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "auth-group")) {
+ if (obj->type == UCL_OBJECT) {
+ iter = NULL;
+ while ((child = ucl_iterate_object(obj, &iter, true))) {
+ uclparse_auth_group(ucl_object_key(child), child);
+ }
+ } else {
+ log_warnx("\"auth-group\" section is not an object");
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "portal-group")) {
+ if (obj->type == UCL_OBJECT) {
+ iter = NULL;
+ while ((child = ucl_iterate_object(obj, &iter, true))) {
+ uclparse_portal_group(ucl_object_key(child), child);
+ }
+ } else {
+ log_warnx("\"portal-group\" section is not an object");
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "lun")) {
+ if (obj->type == UCL_OBJECT) {
+ iter = NULL;
+ while ((child = ucl_iterate_object(obj, &iter, true))) {
+ uclparse_lun(ucl_object_key(child), child);
+ }
+ } else {
+ log_warnx("\"lun\" section is not an object");
+ return (1);
+ }
+ }
+ }
+
+ /* Pass 2 - targets */
+ it = NULL;
+ while ((obj = ucl_iterate_object(top, &it, true))) {
+ const char *key = ucl_object_key(obj);
+
+ if (!strcmp(key, "target")) {
+ if (obj->type == UCL_OBJECT) {
+ iter = NULL;
+ while ((child = ucl_iterate_object(obj, &iter,
+ true))) {
+ uclparse_target(ucl_object_key(child),
+ child);
+ }
+ } else {
+ log_warnx("\"target\" section is not an object");
+ return (1);
+ }
+ }
+ }
+
+ return (0);
+}
+
+static int
+uclparse_auth_group(const char *name, const ucl_object_t *top)
+{
+ struct auth_group *auth_group;
+ const struct auth_name *an;
+ const struct auth_portal *ap;
+ ucl_object_iter_t it = NULL, it2 = NULL;
+ const ucl_object_t *obj = NULL, *tmp = NULL;
+ const char *key;
+ int err;
+
+ if (!strcmp(name, "default") &&
+ conf->conf_default_ag_defined == false) {
+ auth_group = auth_group_find(conf, name);
+ conf->conf_default_ag_defined = true;
+ } else {
+ auth_group = auth_group_new(conf, name);
+ }
+
+ if (auth_group == NULL)
+ return (1);
+
+ while ((obj = ucl_iterate_object(top, &it, true))) {
+ key = ucl_object_key(obj);
+
+ if (!strcmp(key, "auth-type")) {
+ const char *value = ucl_object_tostring(obj);
+
+ err = auth_group_set_type(auth_group, value);
+ if (err)
+ return (1);
+ }
+
+ if (!strcmp(key, "chap")) {
+ if (obj->type != UCL_ARRAY) {
+ log_warnx("\"chap\" property of "
+ "auth-group \"%s\" is not an array",
+ name);
+ return (1);
+ }
+
+ it2 = NULL;
+ while ((tmp = ucl_iterate_object(obj, &it2, true))) {
+ if (uclparse_chap(auth_group, tmp) != 0)
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "chap-mutual")) {
+ if (obj->type != UCL_ARRAY) {
+ log_warnx("\"chap-mutual\" property of "
+ "auth-group \"%s\" is not an array",
+ name);
+ return (1);
+ }
+
+ it2 = NULL;
+ while ((tmp = ucl_iterate_object(obj, &it2, true))) {
+ if (uclparse_chap_mutual(auth_group, tmp) != 0)
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "initiator-name")) {
+ if (obj->type != UCL_ARRAY) {
+ log_warnx("\"initiator-name\" property of "
+ "auth-group \"%s\" is not an array",
+ name);
+ return (1);
+ }
+
+ it2 = NULL;
+ while ((tmp = ucl_iterate_object(obj, &it2, true))) {
+ const char *value = ucl_object_tostring(tmp);
+
+ an = auth_name_new(auth_group, value);
+ if (an == NULL)
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "initiator-portal")) {
+ if (obj->type != UCL_ARRAY) {
+ log_warnx("\"initiator-portal\" property of "
+ "auth-group \"%s\" is not an array",
+ name);
+ return (1);
+ }
+
+ it2 = NULL;
+ while ((tmp = ucl_iterate_object(obj, &it2, true))) {
+ const char *value = ucl_object_tostring(tmp);
+
+ ap = auth_portal_new(auth_group, value);
+ if (ap == NULL)
+ return (1);
+ }
+ }
+ }
+
+ return (0);
+}
+
+static int
+uclparse_portal_group(const char *name, const ucl_object_t *top)
+{
+ struct portal_group *portal_group;
+ ucl_object_iter_t it = NULL, it2 = NULL;
+ const ucl_object_t *obj = NULL, *tmp = NULL;
+ const char *key;
+
+ if (strcmp(name, "default") == 0 &&
+ conf->conf_default_pg_defined == false) {
+ portal_group = portal_group_find(conf, name);
+ conf->conf_default_pg_defined = true;
+ } else {
+ portal_group = portal_group_new(conf, name);
+ }
+
+ if (portal_group == NULL)
+ return (1);
+
+ while ((obj = ucl_iterate_object(top, &it, true))) {
+ key = ucl_object_key(obj);
+
+ if (!strcmp(key, "discovery-auth-group")) {
+ portal_group->pg_discovery_auth_group =
+ auth_group_find(conf, ucl_object_tostring(obj));
+ if (portal_group->pg_discovery_auth_group == NULL) {
+ log_warnx("unknown discovery-auth-group \"%s\" "
+ "for portal-group \"%s\"",
+ ucl_object_tostring(obj),
+ portal_group->pg_name);
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "discovery-filter")) {
+ if (obj->type != UCL_STRING) {
+ log_warnx("\"discovery-filter\" property of "
+ "portal-group \"%s\" is not a string",
+ portal_group->pg_name);
+ return (1);
+ }
+
+ if (portal_group_set_filter(portal_group,
+ ucl_object_tostring(obj)) != 0)
+ return (1);
+ }
+
+ if (!strcmp(key, "listen")) {
+ if (obj->type == UCL_STRING) {
+ if (portal_group_add_listen(portal_group,
+ ucl_object_tostring(obj), false) != 0)
+ return (1);
+ } else if (obj->type == UCL_ARRAY) {
+ while ((tmp = ucl_iterate_object(obj, &it2,
+ true))) {
+ if (portal_group_add_listen(
+ portal_group,
+ ucl_object_tostring(tmp),
+ false) != 0)
+ return (1);
+ }
+ } else {
+ log_warnx("\"listen\" property of "
+ "portal-group \"%s\" is not a string",
+ portal_group->pg_name);
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "listen-iser")) {
+ if (obj->type == UCL_STRING) {
+ if (portal_group_add_listen(portal_group,
+ ucl_object_tostring(obj), true) != 0)
+ return (1);
+ } else if (obj->type == UCL_ARRAY) {
+ while ((tmp = ucl_iterate_object(obj, &it2,
+ true))) {
+ if (portal_group_add_listen(
+ portal_group,
+ ucl_object_tostring(tmp),
+ true) != 0)
+ return (1);
+ }
+ } else {
+ log_warnx("\"listen\" property of "
+ "portal-group \"%s\" is not a string",
+ portal_group->pg_name);
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "redirect")) {
+ if (obj->type != UCL_STRING) {
+ log_warnx("\"listen\" property of "
+ "portal-group \"%s\" is not a string",
+ portal_group->pg_name);
+ return (1);
+ }
+
+ if (portal_group_set_redirection(portal_group,
+ ucl_object_tostring(obj)) != 0)
+ return (1);
+ }
+
+ if (!strcmp(key, "options")) {
+ if (obj->type != UCL_OBJECT) {
+ log_warnx("\"options\" property of portal group "
+ "\"%s\" is not an object", portal_group->pg_name);
+ return (1);
+ }
+
+ while ((tmp = ucl_iterate_object(obj, &it2,
+ true))) {
+ option_new(&portal_group->pg_options,
+ ucl_object_key(tmp),
+ ucl_object_tostring_forced(tmp));
+ }
+ }
+ }
+
+ return (0);
+}
+
+static int
+uclparse_target(const char *name, const ucl_object_t *top)
+{
+ struct target *target;
+ ucl_object_iter_t it = NULL, it2 = NULL;
+ const ucl_object_t *obj = NULL, *tmp = NULL;
+ const char *key;
+
+ target = target_new(conf, name);
+
+ while ((obj = ucl_iterate_object(top, &it, true))) {
+ key = ucl_object_key(obj);
+
+ if (!strcmp(key, "alias")) {
+ if (obj->type != UCL_STRING) {
+ log_warnx("\"alias\" property of target "
+ "\"%s\" is not a string", target->t_name);
+ return (1);
+ }
+
+ target->t_alias = strdup(ucl_object_tostring(obj));
+ }
+
+ if (!strcmp(key, "auth-group")) {
+ if (target->t_auth_group != NULL) {
+ if (target->t_auth_group->ag_name != NULL)
+ log_warnx("auth-group for target \"%s\" "
+ "specified more than once",
+ target->t_name);
+ else
+ log_warnx("cannot use both auth-group "
+ "and explicit authorisations for "
+ "target \"%s\"", target->t_name);
+ return (1);
+ }
+ target->t_auth_group = auth_group_find(conf,
+ ucl_object_tostring(obj));
+ if (target->t_auth_group == NULL) {
+ log_warnx("unknown auth-group \"%s\" for target "
+ "\"%s\"", ucl_object_tostring(obj),
+ target->t_name);
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "auth-type")) {
+ int error;
+
+ if (target->t_auth_group != NULL) {
+ if (target->t_auth_group->ag_name != NULL) {
+ log_warnx("cannot use both auth-group and "
+ "auth-type for target \"%s\"",
+ target->t_name);
+ return (1);
+ }
+ } else {
+ target->t_auth_group = auth_group_new(conf, NULL);
+ if (target->t_auth_group == NULL)
+ return (1);
+
+ target->t_auth_group->ag_target = target;
+ }
+ error = auth_group_set_type(target->t_auth_group,
+ ucl_object_tostring(obj));
+ if (error != 0)
+ return (1);
+ }
+
+ if (!strcmp(key, "chap")) {
+ if (uclparse_chap(target->t_auth_group, obj) != 0)
+ return (1);
+ }
+
+ if (!strcmp(key, "chap-mutual")) {
+ if (uclparse_chap_mutual(target->t_auth_group, obj) != 0)
+ return (1);
+ }
+
+ if (!strcmp(key, "initiator-name")) {
+ const struct auth_name *an;
+
+ if (target->t_auth_group != NULL) {
+ if (target->t_auth_group->ag_name != NULL) {
+ log_warnx("cannot use both auth-group and "
+ "initiator-name for target \"%s\"",
+ target->t_name);
+ return (1);
+ }
+ } else {
+ target->t_auth_group = auth_group_new(conf, NULL);
+ if (target->t_auth_group == NULL)
+ return (1);
+
+ target->t_auth_group->ag_target = target;
+ }
+ an = auth_name_new(target->t_auth_group,
+ ucl_object_tostring(obj));
+ if (an == NULL)
+ return (1);
+ }
+
+ if (!strcmp(key, "initiator-portal")) {
+ const struct auth_portal *ap;
+
+ if (target->t_auth_group != NULL) {
+ if (target->t_auth_group->ag_name != NULL) {
+ log_warnx("cannot use both auth-group and "
+ "initiator-portal for target \"%s\"",
+ target->t_name);
+ return (1);
+ }
+ } else {
+ target->t_auth_group = auth_group_new(conf, NULL);
+ if (target->t_auth_group == NULL)
+ return (1);
+
+ target->t_auth_group->ag_target = target;
+ }
+ ap = auth_portal_new(target->t_auth_group,
+ ucl_object_tostring(obj));
+ if (ap == NULL)
+ return (1);
+ }
+
+ if (!strcmp(key, "portal-group")) {
+ if (obj->type == UCL_OBJECT) {
+ if (uclparse_target_portal_group(target, obj) != 0)
+ return (1);
+ }
+
+ if (obj->type == UCL_ARRAY) {
+ while ((tmp = ucl_iterate_object(obj, &it2,
+ true))) {
+ if (uclparse_target_portal_group(target,
+ tmp) != 0)
+ return (1);
+ }
+ }
+ }
+
+ if (!strcmp(key, "port")) {
+ struct pport *pp;
+ struct port *tp;
+ const char *value = ucl_object_tostring(obj);
+
+ pp = pport_find(conf, value);
+ if (pp == NULL) {
+ log_warnx("unknown port \"%s\" for target \"%s\"",
+ value, target->t_name);
+ return (1);
+ }
+ if (!TAILQ_EMPTY(&pp->pp_ports)) {
+ log_warnx("can't link port \"%s\" to target \"%s\", "
+ "port already linked to some target",
+ value, target->t_name);
+ return (1);
+ }
+ tp = port_new_pp(conf, target, pp);
+ if (tp == NULL) {
+ log_warnx("can't link port \"%s\" to target \"%s\"",
+ value, target->t_name);
+ return (1);
+ }
+ }
+
+ if (!strcmp(key, "redirect")) {
+ if (obj->type != UCL_STRING) {
+ log_warnx("\"redirect\" property of target "
+ "\"%s\" is not a string", target->t_name);
+ return (1);
+ }
+
+ if (target_set_redirection(target,
+ ucl_object_tostring(obj)) != 0)
+ return (1);
+ }
+
+ if (!strcmp(key, "lun")) {
+ while ((tmp = ucl_iterate_object(obj, &it2, true))) {
+ if (uclparse_target_lun(target, tmp) != 0)
+ return (1);
+ }
+ }
+ }
+
+ return (0);
+}
+
+static int
+uclparse_lun(const char *name, const ucl_object_t *top)
+{
+ struct lun *lun;
+ ucl_object_iter_t it = NULL, child_it = NULL;
+ const ucl_object_t *obj = NULL, *child = NULL;
+ const char *key;
+
+ lun = lun_new(conf, name);
+
+ while ((obj = ucl_iterate_object(top, &it, true))) {
+ key = ucl_object_key(obj);
+
+ if (!strcmp(key, "backend")) {
+ if (obj->type != UCL_STRING) {
+ log_warnx("\"backend\" property of lun "
+ "\"%s\" is not a string",
+ lun->l_name);
+ return (1);
+ }
+
+ lun_set_backend(lun, ucl_object_tostring(obj));
+ }
+
+ if (!strcmp(key, "blocksize")) {
+ if (obj->type != UCL_INT) {
+ log_warnx("\"blocksize\" property of lun "
+ "\"%s\" is not an integer", lun->l_name);
+ return (1);
+ }
+
+ lun_set_blocksize(lun, ucl_object_toint(obj));
+ }
+
+ if (!strcmp(key, "device-id")) {
+ if (obj->type != UCL_STRING) {
+ log_warnx("\"device-id\" property of lun "
+ "\"%s\" is not an integer", lun->l_name);
+ return (1);
+ }
+
+ lun_set_device_id(lun, ucl_object_tostring(obj));
+ }
+
+ if (!strcmp(key, "options")) {
+ if (obj->type != UCL_OBJECT) {
+ log_warnx("\"options\" property of lun "
+ "\"%s\" is not an object", lun->l_name);
+ return (1);
+ }
+
+ while ((child = ucl_iterate_object(obj, &child_it,
+ true))) {
+ option_new(&lun->l_options,
+ ucl_object_key(child),
+ ucl_object_tostring_forced(child));
+ }
+ }
+
+ if (!strcmp(key, "path")) {
+ if (obj->type != UCL_STRING) {
+ log_warnx("\"path\" property of lun "
+ "\"%s\" is not a string", lun->l_name);
+ return (1);
+ }
+
+ lun_set_path(lun, ucl_object_tostring(obj));
+ }
+
+ if (!strcmp(key, "serial")) {
+ if (obj->type != UCL_STRING) {
+ log_warnx("\"serial\" property of lun "
+ "\"%s\" is not a string", lun->l_name);
+ return (1);
+ }
+
+ lun_set_serial(lun, ucl_object_tostring(obj));
+ }
+
+ if (!strcmp(key, "size")) {
+ if (obj->type != UCL_INT) {
+ log_warnx("\"size\" property of lun "
+ "\"%s\" is not an integer", lun->l_name);
+ return (1);
+ }
+
+ lun_set_size(lun, ucl_object_toint(obj));
+ }
+ }
+
+ return (0);
+}
+
+int
+uclparse_conf(struct conf *newconf, const char *path)
+{
+ struct ucl_parser *parser;
+ int error;
+
+ conf = newconf;
+ parser = ucl_parser_new(0);
+ ucl_parser_add_file(parser, path);
+
+ if (ucl_parser_get_error(parser)) {
+ log_warn("unable to parse configuration file %s: %s", path,
+ ucl_parser_get_error(parser));
+ return (1);
+ }
+
+ error = uclparse_toplevel(ucl_parser_get_object(parser));
+
+ return (error);
+}
diff --git a/usr.sbin/devctl/devctl.8 b/usr.sbin/devctl/devctl.8
index fef42be13073..2257cb63cc3d 100644
--- a/usr.sbin/devctl/devctl.8
+++ b/usr.sbin/devctl/devctl.8
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 5, 2015
+.Dd February 2, 2016
.Dt DEVCTL 8
.Os
.Sh NAME
@@ -134,4 +134,4 @@ the device will not be changed.
The
.Nm
utility first appeared in
-.Fx 11.0 .
+.Fx 10.3 .
diff --git a/usr.sbin/freebsd-update/freebsd-update.sh b/usr.sbin/freebsd-update/freebsd-update.sh
index cce2af574f61..feb8db6a6b3c 100644
--- a/usr.sbin/freebsd-update/freebsd-update.sh
+++ b/usr.sbin/freebsd-update/freebsd-update.sh
@@ -45,7 +45,7 @@ Options:
(default: /etc/freebsd-update.conf)
-F -- Force a fetch operation to proceed
-k KEY -- Trust an RSA key with SHA256 hash of KEY
- -r release -- Target for upgrade (e.g., 6.2-RELEASE)
+ -r release -- Target for upgrade (e.g., 11.1-RELEASE)
-s server -- Server from which to fetch updates
(default: update.FreeBSD.org)
-t address -- Mail output of cron command, if any, to address
diff --git a/usr.sbin/sysrc/sysrc b/usr.sbin/sysrc/sysrc
index e384dff93f6c..1da537fd5992 100644
--- a/usr.sbin/sysrc/sysrc
+++ b/usr.sbin/sysrc/sysrc
@@ -1,6 +1,6 @@
#!/bin/sh
#-
-# Copyright (c) 2010-2015 Devin Teske
+# Copyright (c) 2010-2016 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
#
# Version information
#
-SYSRC_VERSION="7.0 Sep-13,2015"
+SYSRC_VERSION="7.1 Feb-2,2016"
#
# Options
@@ -595,7 +595,7 @@ fi
if [ "$SHOW_ALL" ]; then
#
# Get a list of variables that are currently set in the rc.conf(5)
- # files (included `/etc/defaults/rc.conf') by performing a call to
+ # files (including `/etc/defaults/rc.conf') by performing a call to
# source_rc_confs() in a clean environment.
#
( # Operate in a sub-shell to protect the parent environment
@@ -790,7 +790,7 @@ while [ $# -gt 0 ]; do
delim="${add%"${add#?}"}" # first character
oldIFS="$IFS"
case "$delim" in
- ""|[$IFS]|[a-zA-Z0-9]) delim=" " ;;
+ ""|[$IFS]|[a-zA-Z0-9./]) delim=" " ;;
*) IFS="$delim"
esac
new="$before"
@@ -812,7 +812,7 @@ while [ $# -gt 0 ]; do
delim="${remove%"${remove#?}"}" # first character
oldIFS="$IFS"
case "$delim" in
- ""|[$IFS]|[a-zA-Z0-9]) delim=" " ;;
+ ""|[$IFS]|[a-zA-Z0-9./]) delim=" " ;;
*) IFS="$delim"
esac
new=
diff --git a/usr.sbin/sysrc/sysrc.8 b/usr.sbin/sysrc/sysrc.8
index dbd0e4b3c326..075fc3bd8a1e 100644
--- a/usr.sbin/sysrc/sysrc.8
+++ b/usr.sbin/sysrc/sysrc.8
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2011-2015 Devin Teske
+.\" Copyright (c) 2011-2016 Devin Teske
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 12, 2015
+.Dd February 2, 2016
.Dt SYSRC 8
.Os
.Sh NAME
@@ -255,7 +255,7 @@ When using the
.Ql key+=value
syntax to add items to existing values,
the first character of the value is taken as the delimiter separating items
-.Pq usually Qo \ Qc or Qo , Qc .
+.Pq usually Qo " " Qc or Qo , Qc .
For example, in the following statement:
.Bl -item -offset indent
.It
@@ -275,6 +275,10 @@ it is added
.Pp
For convenience, if the first character is alpha-numeric
.Pq letters A-Z, a-z, or numbers 0-9 ,
+dot
+.Pq Li . ,
+or slash
+.Pq Li / ,
.Nm
uses the default setting of whitespace as separator.
For example, the above and below statements are equivalent since
@@ -312,7 +316,7 @@ When using the
.Ql key-=value
syntax to remove items from existing values,
the first character of the value is taken as the delimiter separating items
-.Pq usually Qo \ Qc or Qo , Qc .
+.Pq usually Qo " " Qc or Qo , Qc .
For example, in the following statement:
.Pp
.Dl Nm cloned_interfaces-=" gif0"
@@ -329,6 +333,10 @@ it is removed
.Pp
For convenience, if the first character is alpha-numeric
.Pq letters A-Z, a-z, or numbers 0-9 ,
+dot
+.Pq Li . ,
+or slash
+.Pq Li / ,
.Nm
uses the default setting of whitespace as separator.
For example, the above and below statements are equivalent since