mm.rs 3.8 KB

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