42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/user.h>
45 #include <sys/proc.h>
46 #include <sys/kmem.h>
47 #include <sys/vmem.h>
48 #include <sys/buf.h>
49 #include <sys/cpuvar.h>
50 #include <sys/lgrp.h>
51 #include <sys/disp.h>
52 #include <sys/vm.h>
53 #include <sys/mman.h>
54 #include <sys/vnode.h>
55 #include <sys/cred.h>
56 #include <sys/exec.h>
57 #include <sys/exechdr.h>
58 #include <sys/debug.h>
59 #include <sys/vmsystm.h>
60 #include <sys/swap.h>
61 #include <sys/dumphdr.h>
62
63 #include <vm/hat.h>
64 #include <vm/as.h>
65 #include <vm/seg.h>
66 #include <vm/seg_kp.h>
67 #include <vm/seg_vn.h>
68 #include <vm/page.h>
69 #include <vm/seg_kmem.h>
70 #include <vm/seg_kpm.h>
71 #include <vm/vm_dep.h>
72
73 #include <sys/cpu.h>
74 #include <sys/vm_machparam.h>
75 #include <sys/memlist.h>
76 #include <sys/bootconf.h> /* XXX the memlist stuff belongs in memlist_plat.h */
77 #include <vm/hat_i86.h>
78 #include <sys/x86_archext.h>
79 #include <sys/elf_386.h>
80 #include <sys/cmn_err.h>
81 #include <sys/archsystm.h>
620 }
621
622 void
623 map_addr(caddr_t *addrp, size_t len, offset_t off, int vacalign, uint_t flags)
624 {
625 struct proc *p = curproc;
626 caddr_t userlimit = (flags & _MAP_LOW32) ?
627 (caddr_t)_userlimit32 : p->p_as->a_userlimit;
628
629 map_addr_proc(addrp, len, off, vacalign, userlimit, curproc, flags);
630 }
631
632 /*ARGSUSED*/
633 int
634 map_addr_vacalign_check(caddr_t addr, u_offset_t off)
635 {
636 return (0);
637 }
638
639 /*
640 * map_addr_proc() is the routine called when the system is to
641 * choose an address for the user. We will pick an address
642 * range which is the highest available below userlimit.
643 *
644 * Every mapping will have a redzone of a single page on either side of
645 * the request. This is done to leave one page unmapped between segments.
646 * This is not required, but it's useful for the user because if their
647 * program strays across a segment boundary, it will catch a fault
648 * immediately making debugging a little easier. Currently the redzone
649 * is mandatory.
650 *
651 * addrp is a value/result parameter.
652 * On input it is a hint from the user to be used in a completely
653 * machine dependent fashion. We decide to completely ignore this hint.
654 * If MAP_ALIGN was specified, addrp contains the minimal alignment, which
655 * must be some "power of two" multiple of pagesize.
656 *
657 * On output it is NULL if no address can be found in the current
658 * processes address space or else an address that is currently
659 * not mapped for len bytes with a page of red zone on either side.
735 * For 32-bit processes, only those which have specified
736 * MAP_ALIGN and an addr will be aligned on a larger page size.
737 * Not doing so can potentially waste up to 1G of process
738 * address space.
739 */
740 int lvl = (p->p_model == DATAMODEL_ILP32) ? 1 :
741 mmu.umax_page_level;
742
743 while (lvl && len < LEVEL_SIZE(lvl))
744 --lvl;
745
746 align_amount = LEVEL_SIZE(lvl);
747 }
748 if ((flags & MAP_ALIGN) && ((uintptr_t)*addrp > align_amount))
749 align_amount = (uintptr_t)*addrp;
750
751 ASSERT(ISP2(align_amount));
752 ASSERT(align_amount == 0 || align_amount >= PAGESIZE);
753
754 off = off & (align_amount - 1);
755 /*
756 * Look for a large enough hole starting below userlimit.
757 * After finding it, use the upper part.
758 */
759 if (as_gap_aligned(as, len, &base, &slen, AH_HI, NULL, align_amount,
760 PAGESIZE, off) == 0) {
761 caddr_t as_addr;
762
763 /*
764 * addr is the highest possible address to use since we have
765 * a PAGESIZE redzone at the beginning and end.
766 */
767 addr = base + slen - (PAGESIZE + len);
768 as_addr = addr;
769 /*
770 * Round address DOWN to the alignment amount and
771 * add the offset in.
772 * If addr is greater than as_addr, len would not be large
773 * enough to include the redzone, so we must adjust down
774 * by the alignment amount.
775 */
776 addr = (caddr_t)((uintptr_t)addr & (~(align_amount - 1)));
777 addr += (uintptr_t)off;
778 if (addr > as_addr) {
779 addr -= align_amount;
780 }
781
782 ASSERT(addr > base);
783 ASSERT(addr + len < base + slen);
784 ASSERT(((uintptr_t)addr & (align_amount - 1)) ==
785 ((uintptr_t)(off)));
786 *addrp = addr;
787 } else {
788 *addrp = NULL; /* no more virtual space */
789 }
790 }
791
792 int valid_va_range_aligned_wraparound;
793
794 /*
795 * Determine whether [*basep, *basep + *lenp) contains a mappable range of
796 * addresses at least "minlen" long, where the base of the range is at "off"
797 * phase from an "align" boundary and there is space for a "redzone"-sized
798 * redzone on either side of the range. On success, 1 is returned and *basep
799 * and *lenp are adjusted to describe the acceptable range (including
800 * the redzone). On failure, 0 is returned.
801 */
3909
3910 hat_mempte_release(cpup->cpu_caddr2, cpup->cpu_caddr2pte);
3911 cpup->cpu_caddr2pte = 0;
3912 vmem_free(heap_arena, cpup->cpu_caddr2, mmu_ptob(1));
3913 cpup->cpu_caddr2 = 0;
3914
3915 hat_mempte_release(cpup->cpu_caddr1, cpup->cpu_caddr1pte);
3916 cpup->cpu_caddr1pte = 0;
3917 vmem_free(heap_arena, cpup->cpu_caddr1, mmu_ptob(1));
3918 cpup->cpu_caddr1 = 0;
3919 }
3920
3921 /*
3922 * Function for flushing D-cache when performing module relocations
3923 * to an alternate mapping. Unnecessary on Intel / AMD platforms.
3924 */
3925 void
3926 dcache_flushall()
3927 {}
3928
3929 size_t
3930 exec_get_spslew(void)
3931 {
3932 return (0);
3933 }
3934
3935 /*
3936 * Allocate a memory page. The argument 'seed' can be any pseudo-random
3937 * number to vary where the pages come from. This is quite a hacked up
3938 * method -- it works for now, but really needs to be fixed up a bit.
3939 *
3940 * We currently use page_create_va() on the kvp with fake offsets,
3941 * segments and virt address. This is pretty bogus, but was copied from the
3942 * old hat_i86.c code. A better approach would be to specify either mnode
3943 * random or mnode local and takes a page from whatever color has the MOST
3944 * available - this would have a minimal impact on page coloring.
3945 */
3946 page_t *
3947 page_get_physical(uintptr_t seed)
3948 {
3949 page_t *pp;
3950 u_offset_t offset;
3951 static struct seg tmpseg;
3952 static uintptr_t ctr = 0;
3953
3954 /*
|
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/user.h>
45 #include <sys/proc.h>
46 #include <sys/kmem.h>
47 #include <sys/vmem.h>
48 #include <sys/buf.h>
49 #include <sys/cpuvar.h>
50 #include <sys/lgrp.h>
51 #include <sys/disp.h>
52 #include <sys/vm.h>
53 #include <sys/mman.h>
54 #include <sys/vnode.h>
55 #include <sys/cred.h>
56 #include <sys/exec.h>
57 #include <sys/exechdr.h>
58 #include <sys/debug.h>
59 #include <sys/vmsystm.h>
60 #include <sys/swap.h>
61 #include <sys/dumphdr.h>
62 #include <sys/random.h>
63
64 #include <vm/hat.h>
65 #include <vm/as.h>
66 #include <vm/seg.h>
67 #include <vm/seg_kp.h>
68 #include <vm/seg_vn.h>
69 #include <vm/page.h>
70 #include <vm/seg_kmem.h>
71 #include <vm/seg_kpm.h>
72 #include <vm/vm_dep.h>
73
74 #include <sys/cpu.h>
75 #include <sys/vm_machparam.h>
76 #include <sys/memlist.h>
77 #include <sys/bootconf.h> /* XXX the memlist stuff belongs in memlist_plat.h */
78 #include <vm/hat_i86.h>
79 #include <sys/x86_archext.h>
80 #include <sys/elf_386.h>
81 #include <sys/cmn_err.h>
82 #include <sys/archsystm.h>
621 }
622
623 void
624 map_addr(caddr_t *addrp, size_t len, offset_t off, int vacalign, uint_t flags)
625 {
626 struct proc *p = curproc;
627 caddr_t userlimit = (flags & _MAP_LOW32) ?
628 (caddr_t)_userlimit32 : p->p_as->a_userlimit;
629
630 map_addr_proc(addrp, len, off, vacalign, userlimit, curproc, flags);
631 }
632
633 /*ARGSUSED*/
634 int
635 map_addr_vacalign_check(caddr_t addr, u_offset_t off)
636 {
637 return (0);
638 }
639
640 /*
641 * The maximum amount a randomized mapping will be slewed. We should perhaps
642 * arrange things so these tunables can be separate for mmap, mmapobj, and
643 * ld.so
644 */
645 volatile size_t aslr_max_map_skew = 256 * 1024 * 1024; /* 256MB */
646
647 /*
648 * map_addr_proc() is the routine called when the system is to
649 * choose an address for the user. We will pick an address
650 * range which is the highest available below userlimit.
651 *
652 * Every mapping will have a redzone of a single page on either side of
653 * the request. This is done to leave one page unmapped between segments.
654 * This is not required, but it's useful for the user because if their
655 * program strays across a segment boundary, it will catch a fault
656 * immediately making debugging a little easier. Currently the redzone
657 * is mandatory.
658 *
659 * addrp is a value/result parameter.
660 * On input it is a hint from the user to be used in a completely
661 * machine dependent fashion. We decide to completely ignore this hint.
662 * If MAP_ALIGN was specified, addrp contains the minimal alignment, which
663 * must be some "power of two" multiple of pagesize.
664 *
665 * On output it is NULL if no address can be found in the current
666 * processes address space or else an address that is currently
667 * not mapped for len bytes with a page of red zone on either side.
743 * For 32-bit processes, only those which have specified
744 * MAP_ALIGN and an addr will be aligned on a larger page size.
745 * Not doing so can potentially waste up to 1G of process
746 * address space.
747 */
748 int lvl = (p->p_model == DATAMODEL_ILP32) ? 1 :
749 mmu.umax_page_level;
750
751 while (lvl && len < LEVEL_SIZE(lvl))
752 --lvl;
753
754 align_amount = LEVEL_SIZE(lvl);
755 }
756 if ((flags & MAP_ALIGN) && ((uintptr_t)*addrp > align_amount))
757 align_amount = (uintptr_t)*addrp;
758
759 ASSERT(ISP2(align_amount));
760 ASSERT(align_amount == 0 || align_amount >= PAGESIZE);
761
762 off = off & (align_amount - 1);
763
764 /*
765 * Look for a large enough hole starting below userlimit.
766 * After finding it, use the upper part.
767 */
768 if (as_gap_aligned(as, len, &base, &slen, AH_HI, NULL, align_amount,
769 PAGESIZE, off) == 0) {
770 caddr_t as_addr;
771
772 /*
773 * addr is the highest possible address to use since we have
774 * a PAGESIZE redzone at the beginning and end.
775 */
776 addr = base + slen - (PAGESIZE + len);
777 as_addr = addr;
778 /*
779 * Round address DOWN to the alignment amount and
780 * add the offset in.
781 * If addr is greater than as_addr, len would not be large
782 * enough to include the redzone, so we must adjust down
783 * by the alignment amount.
784 */
785 addr = (caddr_t)((uintptr_t)addr & (~(align_amount - 1)));
786 addr += (uintptr_t)off;
787 if (addr > as_addr) {
788 addr -= align_amount;
789 }
790
791 /*
792 * If randomization is requested, slew the allocation
793 * backwards, within the same gap, by a random amount.
794 *
795 * XXX: This will fall over in processes like Java, which
796 * commonly have a great many small mappings.
797 */
798 if (flags & _MAP_RANDOMIZE) {
799 uint32_t slew;
800
801 (void) random_get_pseudo_bytes((uint8_t *)&slew,
802 sizeof (slew));
803
804 slew = slew % MIN(aslr_max_map_skew, (addr - base));
805 addr -= P2ALIGN(slew, align_amount);
806 }
807
808 ASSERT(addr > base);
809 ASSERT(addr + len < base + slen);
810 ASSERT(((uintptr_t)addr & (align_amount - 1)) ==
811 ((uintptr_t)(off)));
812 *addrp = addr;
813 } else {
814 *addrp = NULL; /* no more virtual space */
815 }
816 }
817
818 int valid_va_range_aligned_wraparound;
819
820 /*
821 * Determine whether [*basep, *basep + *lenp) contains a mappable range of
822 * addresses at least "minlen" long, where the base of the range is at "off"
823 * phase from an "align" boundary and there is space for a "redzone"-sized
824 * redzone on either side of the range. On success, 1 is returned and *basep
825 * and *lenp are adjusted to describe the acceptable range (including
826 * the redzone). On failure, 0 is returned.
827 */
3935
3936 hat_mempte_release(cpup->cpu_caddr2, cpup->cpu_caddr2pte);
3937 cpup->cpu_caddr2pte = 0;
3938 vmem_free(heap_arena, cpup->cpu_caddr2, mmu_ptob(1));
3939 cpup->cpu_caddr2 = 0;
3940
3941 hat_mempte_release(cpup->cpu_caddr1, cpup->cpu_caddr1pte);
3942 cpup->cpu_caddr1pte = 0;
3943 vmem_free(heap_arena, cpup->cpu_caddr1, mmu_ptob(1));
3944 cpup->cpu_caddr1 = 0;
3945 }
3946
3947 /*
3948 * Function for flushing D-cache when performing module relocations
3949 * to an alternate mapping. Unnecessary on Intel / AMD platforms.
3950 */
3951 void
3952 dcache_flushall()
3953 {}
3954
3955 /*
3956 * Allocate a memory page. The argument 'seed' can be any pseudo-random
3957 * number to vary where the pages come from. This is quite a hacked up
3958 * method -- it works for now, but really needs to be fixed up a bit.
3959 *
3960 * We currently use page_create_va() on the kvp with fake offsets,
3961 * segments and virt address. This is pretty bogus, but was copied from the
3962 * old hat_i86.c code. A better approach would be to specify either mnode
3963 * random or mnode local and takes a page from whatever color has the MOST
3964 * available - this would have a minimal impact on page coloring.
3965 */
3966 page_t *
3967 page_get_physical(uintptr_t seed)
3968 {
3969 page_t *pp;
3970 u_offset_t offset;
3971 static struct seg tmpseg;
3972 static uintptr_t ctr = 0;
3973
3974 /*
|