Implement MAP_32BIT.
PiperOrigin-RevId: 196281052 Change-Id: Ie620a0f983a1bf2570d0003d4754611879335c1c
This commit is contained in:
parent
f24db99498
commit
12c161f278
|
@ -31,6 +31,7 @@ const (
|
|||
MAP_PRIVATE = 1 << 1
|
||||
MAP_FIXED = 1 << 4
|
||||
MAP_ANONYMOUS = 1 << 5
|
||||
MAP_32BIT = 1 << 6 // arch/x86/include/uapi/asm/mman.h
|
||||
MAP_GROWSDOWN = 1 << 8
|
||||
MAP_DENYWRITE = 1 << 11
|
||||
MAP_EXECUTABLE = 1 << 12
|
||||
|
|
|
@ -266,6 +266,12 @@ type MMapOpts struct {
|
|||
// be replaced. If Unmap is true, Fixed must be true.
|
||||
Unmap bool
|
||||
|
||||
// If Map32Bit is true, all addresses in the created mapping must fit in a
|
||||
// 32-bit integer. (Note that the "end address" of the mapping, i.e. the
|
||||
// address of the first byte *after* the mapping, need not fit in a 32-bit
|
||||
// integer.) Map32Bit is ignored if Fixed is true.
|
||||
Map32Bit bool
|
||||
|
||||
// Perms is the set of permissions to the applied to this mapping.
|
||||
Perms usermem.AccessType
|
||||
|
||||
|
|
|
@ -34,9 +34,10 @@ func (mm *MemoryManager) createVMALocked(ctx context.Context, opts memmap.MMapOp
|
|||
|
||||
// Find a useable range.
|
||||
addr, err := mm.findAvailableLocked(opts.Length, findAvailableOpts{
|
||||
Addr: opts.Addr,
|
||||
Fixed: opts.Fixed,
|
||||
Unmap: opts.Unmap,
|
||||
Addr: opts.Addr,
|
||||
Fixed: opts.Fixed,
|
||||
Unmap: opts.Unmap,
|
||||
Map32Bit: opts.Map32Bit,
|
||||
})
|
||||
if err != nil {
|
||||
return vmaIterator{}, usermem.AddrRange{}, err
|
||||
|
@ -93,24 +94,40 @@ func (mm *MemoryManager) createVMALocked(ctx context.Context, opts memmap.MMapOp
|
|||
}
|
||||
|
||||
type findAvailableOpts struct {
|
||||
// Addr is a suggested address. Addr must be page-aligned.
|
||||
Addr usermem.Addr
|
||||
// These fields are equivalent to those in memmap.MMapOpts, except that:
|
||||
//
|
||||
// - Addr must be page-aligned.
|
||||
//
|
||||
// - Unmap allows existing guard pages in the returned range.
|
||||
|
||||
// Fixed is true if only the suggested address is acceptable.
|
||||
Fixed bool
|
||||
|
||||
// Unmap is true if existing vmas and guard pages may exist in the returned
|
||||
// range.
|
||||
Unmap bool
|
||||
Addr usermem.Addr
|
||||
Fixed bool
|
||||
Unmap bool
|
||||
Map32Bit bool
|
||||
}
|
||||
|
||||
// map32Start/End are the bounds to which MAP_32BIT mappings are constrained,
|
||||
// and are equivalent to Linux's MAP32_BASE and MAP32_MAX respectively.
|
||||
const (
|
||||
map32Start = 0x40000000
|
||||
map32End = 0x80000000
|
||||
)
|
||||
|
||||
// findAvailableLocked finds an allocatable range.
|
||||
//
|
||||
// Preconditions: mm.mappingMu must be locked.
|
||||
func (mm *MemoryManager) findAvailableLocked(length uint64, opts findAvailableOpts) (usermem.Addr, error) {
|
||||
if opts.Fixed {
|
||||
opts.Map32Bit = false
|
||||
}
|
||||
allowedAR := mm.applicationAddrRange()
|
||||
if opts.Map32Bit {
|
||||
allowedAR = allowedAR.Intersect(usermem.AddrRange{map32Start, map32End})
|
||||
}
|
||||
|
||||
// Does the provided suggestion work?
|
||||
if ar, ok := opts.Addr.ToRange(length); ok {
|
||||
if mm.applicationAddrRange().IsSupersetOf(ar) {
|
||||
if allowedAR.IsSupersetOf(ar) {
|
||||
if opts.Unmap {
|
||||
return ar.Start, nil
|
||||
}
|
||||
|
@ -132,6 +149,9 @@ func (mm *MemoryManager) findAvailableLocked(length uint64, opts findAvailableOp
|
|||
alignment = usermem.HugePageSize
|
||||
}
|
||||
|
||||
if opts.Map32Bit {
|
||||
return mm.findLowestAvailableLocked(length, alignment, allowedAR)
|
||||
}
|
||||
if mm.layout.DefaultDirection == arch.MmapBottomUp {
|
||||
return mm.findLowestAvailableLocked(length, alignment, usermem.AddrRange{mm.layout.BottomUpBase, mm.layout.MaxAddr})
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ func Mmap(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
|
|||
private := flags&linux.MAP_PRIVATE != 0
|
||||
shared := flags&linux.MAP_SHARED != 0
|
||||
anon := flags&linux.MAP_ANONYMOUS != 0
|
||||
map32bit := flags&linux.MAP_32BIT != 0
|
||||
|
||||
// Require exactly one of MAP_PRIVATE and MAP_SHARED.
|
||||
if private == shared {
|
||||
|
@ -52,12 +53,13 @@ func Mmap(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
|
|||
}
|
||||
|
||||
opts := memmap.MMapOpts{
|
||||
Length: args[1].Uint64(),
|
||||
Offset: args[5].Uint64(),
|
||||
Addr: args[0].Pointer(),
|
||||
Fixed: fixed,
|
||||
Unmap: fixed,
|
||||
Private: private,
|
||||
Length: args[1].Uint64(),
|
||||
Offset: args[5].Uint64(),
|
||||
Addr: args[0].Pointer(),
|
||||
Fixed: fixed,
|
||||
Unmap: fixed,
|
||||
Map32Bit: map32bit,
|
||||
Private: private,
|
||||
Perms: usermem.AccessType{
|
||||
Read: linux.PROT_READ&prot != 0,
|
||||
Write: linux.PROT_WRITE&prot != 0,
|
||||
|
|
Loading…
Reference in New Issue