mm.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. use super::{define_syscall32, register_syscall, MapArgument, MapArgumentImpl};
  2. use crate::{
  3. kernel::{
  4. constants::{UserMmapFlags, UserMmapProtocol},
  5. mem::{Mapping, Permission},
  6. task::Thread,
  7. },
  8. prelude::*,
  9. };
  10. use bindings::{EINVAL, ENOMEM};
  11. use eonix_mm::address::{Addr as _, AddrOps as _, VAddr};
  12. use eonix_runtime::task::Task;
  13. /// Check whether we are doing an implemented function.
  14. /// If `condition` is false, return `Err(err)`.
  15. fn check_impl(condition: bool, err: u32) -> KResult<()> {
  16. if !condition {
  17. Err(err)
  18. } else {
  19. Ok(())
  20. }
  21. }
  22. fn do_mmap_pgoff(
  23. addr: usize,
  24. len: usize,
  25. prot: UserMmapProtocol,
  26. flags: UserMmapFlags,
  27. fd: u32,
  28. pgoffset: usize,
  29. ) -> KResult<usize> {
  30. let addr = VAddr::from(addr);
  31. if !addr.is_page_aligned() || len == 0 {
  32. return Err(EINVAL);
  33. }
  34. let len = (len + 0xfff) & !0xfff;
  35. check_impl(flags.contains(UserMmapFlags::MAP_ANONYMOUS), ENOMEM)?;
  36. check_impl(flags.contains(UserMmapFlags::MAP_PRIVATE), EINVAL)?;
  37. if fd != u32::MAX || pgoffset != 0 {
  38. return Err(EINVAL);
  39. }
  40. let mm_list = &Thread::current().process.mm_list;
  41. // PROT_NONE, we do unmapping.
  42. if prot.is_empty() {
  43. Task::block_on(mm_list.unmap(addr, len)).map(|_| 0)?;
  44. return Ok(0);
  45. }
  46. // Otherwise, do mmapping.
  47. // TODO!!!: If we are doing mmap's in 32-bit mode, we should check whether
  48. // `addr` is above user reachable memory.
  49. let addr = if flags.contains(UserMmapFlags::MAP_FIXED) {
  50. mm_list.mmap_fixed(
  51. addr,
  52. len,
  53. Mapping::Anonymous,
  54. Permission {
  55. write: prot.contains(UserMmapProtocol::PROT_WRITE),
  56. execute: prot.contains(UserMmapProtocol::PROT_EXEC),
  57. },
  58. )
  59. } else {
  60. mm_list.mmap_hint(
  61. addr,
  62. len,
  63. Mapping::Anonymous,
  64. Permission {
  65. write: prot.contains(UserMmapProtocol::PROT_WRITE),
  66. execute: prot.contains(UserMmapProtocol::PROT_EXEC),
  67. },
  68. )
  69. };
  70. addr.map(|addr| addr.addr())
  71. }
  72. fn do_munmap(addr: usize, len: usize) -> KResult<usize> {
  73. let addr = VAddr::from(addr);
  74. if !addr.is_page_aligned() || len == 0 {
  75. return Err(EINVAL);
  76. }
  77. let len = (len + 0xfff) & !0xfff;
  78. Task::block_on(Thread::current().process.mm_list.unmap(addr, len)).map(|_| 0)
  79. }
  80. fn do_brk(addr: usize) -> KResult<usize> {
  81. let vaddr = if addr == 0 { None } else { Some(VAddr::from(addr)) };
  82. Ok(Thread::current().process.mm_list.set_break(vaddr).addr())
  83. }
  84. impl MapArgument<'_, UserMmapProtocol> for MapArgumentImpl {
  85. fn map_arg(value: u64) -> UserMmapProtocol {
  86. UserMmapProtocol::from_bits_truncate(value as u32)
  87. }
  88. }
  89. impl MapArgument<'_, UserMmapFlags> for MapArgumentImpl {
  90. fn map_arg(value: u64) -> UserMmapFlags {
  91. UserMmapFlags::from_bits_truncate(value as u32)
  92. }
  93. }
  94. #[allow(unused_variables)]
  95. fn do_madvise(addr: usize, len: usize, advice: u32) -> KResult<()> {
  96. Ok(())
  97. }
  98. define_syscall32!(sys_brk, do_brk, addr: usize);
  99. define_syscall32!(sys_munmap, do_munmap, addr: usize, len: usize);
  100. define_syscall32!(sys_madvise, do_madvise, addr: usize, len: usize, advice: u32);
  101. define_syscall32!(sys_mmap_pgoff, do_mmap_pgoff,
  102. addr: usize, len: usize,
  103. prot: UserMmapProtocol,
  104. flags: UserMmapFlags,
  105. fd: u32, pgoffset: usize);
  106. pub(super) fn register() {
  107. register_syscall!(0x2d, brk);
  108. register_syscall!(0x5b, munmap);
  109. register_syscall!(0xc0, mmap_pgoff);
  110. register_syscall!(0xdb, madvise);
  111. }