Browse Source

完善Tty的RawMode (#577)

* 完善rowmode,改掉一部分bug

* 增加两个ansi拓展功能功能,以及标记部分函数nerve inline

* 修改do_signal和其他中断上下文锁未关中断,以及拓展tty功能,修改tty几个算法bug

* 修改两个锁

* 修改syscall_64

* update
GnoCiYeH 1 year ago
parent
commit
52bcb59e92

+ 3 - 0
kernel/src/arch/x86_64/asm/entry.S

@@ -327,6 +327,7 @@ ENTRY(ignore_int)
 
 ENTRY(syscall_64)
     // 切换用户栈和内核栈
+    cli
     swapgs
     movq %rsp, %gs:0x8
     movq %gs:0x0, %rsp
@@ -372,10 +373,12 @@ ENTRY(syscall_64)
 
     movq %rsp, %rdi // 把栈指针装入rdi,作为函数的第一个的参数
 
+    sti
     callq *%rdx //调用服务程序
 
     // 将原本要返回的栈帧的栈指针传入do_signal的第一个参数
     movq %rsp, %rdi
+
     callq do_signal
 
     cli

+ 3 - 2
kernel/src/arch/x86_64/ipc/signal.rs

@@ -415,7 +415,8 @@ pub struct X86_64SignalArch;
 impl SignalArch for X86_64SignalArch {
     unsafe fn do_signal(frame: &mut TrapFrame) {
         let pcb = ProcessManager::current_pcb();
-        let siginfo = pcb.try_siginfo(5);
+
+        let siginfo = pcb.try_siginfo_irqsave(5);
 
         if unlikely(siginfo.is_none()) {
             return;
@@ -437,7 +438,7 @@ impl SignalArch for X86_64SignalArch {
         let sig_block: SigSet = siginfo_read_guard.sig_block().clone();
         drop(siginfo_read_guard);
 
-        let sig_guard = pcb.try_sig_struct_irq(5);
+        let sig_guard = pcb.try_sig_struct_irqsave(5);
         if unlikely(sig_guard.is_none()) {
             return;
         }

+ 68 - 69
kernel/src/driver/tty/termios.rs

@@ -140,12 +140,12 @@ bitflags! {
     /// termios输入特性
     pub struct InputMode: u32 {
         /// 如果设置了该标志,表示启用软件流控制。
-        const IXON = 0x0200;
+        const IXON = 0x0400;
         /// 如果设置了该标志,表示启用输入流控制。
-        const IXOFF = 0x0400;
+        const IXOFF = 0x1000;
         /// Map Uppercase to Lowercase on Input 将大写转换为小写
         /// 表示不区分大小写
-        const IUCLC = 0x1000;
+        const IUCLC = 0x0200;
         /// 如果设置了该标志,表示当输入队列满时,产生一个响铃信号。
         const IMAXBEL = 0x2000;
         /// 如果设置了该标志,表示输入数据被视为 UTF-8 编码。
@@ -176,46 +176,44 @@ bitflags! {
     /// termios输出特性
     pub struct OutputMode: u32 {
         /// 在输出时将换行符替换\r\n
-        const ONLCR	= 0x00002;
+        const ONLCR	= 0x00004;
         /// Map Lowercase to Uppercase on Output 输出字符时将小写字母映射为大写字母
-        const OLCUC	= 0x00004;
+        const OLCUC	= 0x00002;
 
         /// 与NL协同 配置换行符的处理方式
-        const NLDLY	= 0x00300;
+        const NLDLY	= 0x00100;
         const   NL0	= 0x00000;  // 不延迟换行
         const   NL1	= 0x00100;  // 延迟换行(输出回车后等待一段时间再输出换行)
-        const   NL2	= 0x00200;  // NL2 和 NL3保留,暂未使用
-        const   NL3	= 0x00300;
 
         /// 配置水平制表符的处理方式
-        const TABDLY = 0x00c00;
+        const TABDLY = 0x01800;
         const  TAB0 = 0x00000;  // 不延迟水平制表符
-        const  TAB1 = 0x00400;  // 在输出水平制表符时,延迟到下一个设置的水平制表符位置
-        const  TAB2 = 0x00800;  // 在输出水平制表符时,延迟到下一个设置的 8 的倍数的位置
-        const  TAB3 = 0x00c00;  // TAB3 和 XTABS(与 TAB3 等效)保留,暂未使用
-        const XTABS = 0x00c00;
+        const  TAB1 = 0x00800;  // 在输出水平制表符时,延迟到下一个设置的水平制表符位置
+        const  TAB2 = 0x01000;  // 在输出水平制表符时,延迟到下一个设置的 8 的倍数的位置
+        const  TAB3 = 0x01800;  // TAB3 和 XTABS(与 TAB3 等效)保留,暂未使用
+        const XTABS = 0x01800;
 
         /// 配置回车符的处理方式
-        const CRDLY	= 0x03000;
+        const CRDLY	= 0x00600;
         const   CR0	= 0x00000;  // 不延迟回车
-        const   CR1	= 0x01000;  //  延迟回车(输出回车后等待一段时间再输出换行)
-        const   CR2	= 0x02000;  // CR2 和 CR3保留,暂未使用
-        const   CR3	= 0x03000;
+        const   CR1	= 0x02000;  //  延迟回车(输出回车后等待一段时间再输出换行)
+        const   CR2	= 0x04000;  // CR2 和 CR3保留,暂未使用
+        const   CR3	= 0x06000;
 
         /// 配置换页符(form feed)的处理方式
-        const FFDLY	= 0x04000;
+        const FFDLY	= 0x08000;
         const   FF0	= 0x00000;  // 不延迟换页
-        const   FF1	= 0x04000;  // 延迟换页
+        const   FF1	= 0x08000;  // 延迟换页
 
         /// 配置退格符(backspace)的处理方式
-        const BSDLY	= 0x08000;
+        const BSDLY	= 0x02000;
         const   BS0	= 0x00000;  // 不延迟退格
-        const   BS1	= 0x08000;  // 延迟退格
+        const   BS1	= 0x02000;  // 延迟退格
 
         /// 配置垂直制表符(vertical tab)的处理方式
-        const VTDLY	= 0x10000;
+        const VTDLY	= 0x04000;
         const   VT0	= 0x00000;  // 不延迟垂直制表符
-        const   VT1	= 0x10000;  // 延迟垂直制表符
+        const   VT1	= 0x04000;  // 延迟垂直制表符
 
         /// 表示执行输出处理,即启用输出处理函数
         const OPOST	= 0x01;
@@ -234,13 +232,14 @@ bitflags! {
     /// 配置终端设备的基本特性和控制参数
     pub struct ControlMode: u32 {
         /// Baud Rate Mask 指定波特率的掩码
-        const CBAUD		= 0x000000ff;
+        const CBAUD		= 0x0000100f;
         /// Extra Baud Bits 指定更高的波特率位
-        const CBAUDEX	= 0x00000000;
+        const CBAUDEX	= 0x00001000;
         /// Custom Baud Rate 指定自定义波特率 如果设置了 BOTHER,则通过以下位来设置自定义的波特率值
-        const BOTHER	= 0x0000001f;
+        const BOTHER	= 0x00001000;
 
-        const     B0	= 0x00000000;
+        /* Common CBAUD rates */
+        const     B0	= 0x00000000;	/* hang up */
         const    B50	= 0x00000001;
         const    B75	= 0x00000002;
         const   B110	= 0x00000003;
@@ -257,43 +256,43 @@ bitflags! {
         const B19200	= 0x0000000e;
         const B38400	= 0x0000000f;
 
-        const    B57600	= 0x00000010;
-        const   B115200	= 0x00000011;
-        const   B230400	= 0x00000012;
-        const   B460800	= 0x00000013;
-        const   B500000	= 0x00000014;
-        const   B576000	= 0x00000015;
-        const   B921600	= 0x00000016;
-        const  B1000000	= 0x00000017;
-        const  B1152000	= 0x00000018;
-        const  B1500000	= 0x00000019;
-        const  B2000000	= 0x0000001a;
-        const  B2500000	= 0x0000001b;
-        const  B3000000	= 0x0000001c;
-        const  B3500000	= 0x0000001d;
-        const  B4000000	= 0x0000001e;
+        const     B57600 = 0x00001001;
+        const    B115200 = 0x00001002;
+        const    B230400 = 0x00001003;
+        const    B460800 = 0x00001004;
+        const    B500000 = 0x00001005;
+        const    B576000 = 0x00001006;
+        const    B921600 = 0x00001007;
+        const   B1000000 = 0x00001008;
+        const   B1152000 = 0x00001009;
+        const   B1500000 = 0x0000100a;
+        const   B2000000 = 0x0000100b;
+        const   B2500000 = 0x0000100c;
+        const   B3000000 = 0x0000100d;
+        const   B3500000 = 0x0000100e;
+        const   B4000000 = 0x0000100f;
 
         /// 指定字符大小的掩码 以下位为特定字符大小
-        const CSIZE		= 0x00000300;
+        const CSIZE		= 0x00000030;
         const   CS5		= 0x00000000;
-        const   CS6		= 0x00000100;
-        const   CS7		= 0x00000200;
-        const   CS8		= 0x00000300;
+        const   CS6		= 0x00000010;
+        const   CS7		= 0x00000020;
+        const   CS8		= 0x00000030;
 
         /// Stop Bit Select 表示使用两个停止位;否则,表示使用一个停止位
-        const CSTOPB	= 0x00000400;
+        const CSTOPB	= 0x00000040;
         /// 表示启用接收器。如果未设置,则禁用接收器。
-        const CREAD		= 0x00000800;
+        const CREAD		= 0x00000080;
         /// 表示启用奇偶校验。如果未设置,则禁用奇偶校验。
-        const PARENB	= 0x00001000;
+        const PARENB	= 0x00000100;
         /// 表示启用奇校验。如果未设置,则表示启用偶校验。
-        const PARODD	= 0x00002000;
+        const PARODD	= 0x00000200;
         /// 表示在终端设备被关闭时挂断线路(执行挂断操作)
-        const HUPCL		= 0x00004000;
+        const HUPCL		= 0x00000400;
         /// 表示忽略调制解调器的状态(DCD、DSR、CTS 等)
-        const CLOCAL	= 0x00008000;
+        const CLOCAL	= 0x00000800;
         /// 指定输入波特率的掩码
-        const CIBAUD	= 0x00ff0000;
+        const CIBAUD	= 0x100f0000;
 
         const ADDRB = 0x20000000;
     }
@@ -301,37 +300,37 @@ bitflags! {
     /// 配置终端设备的本地模式(local mode)或控制输入处理的行为
     pub struct LocalMode: u32 {
         /// 启用中断字符(Ctrl-C、Ctrl-Z)
-        const ISIG	 = 0x00000080;
+        const ISIG	 = 0x00001;
         /// 表示启用规范模式,即启用行缓冲和回显。在规范模式下,输入被缓冲,并且只有在输入回车符时才会传递给应用程序。
-        const ICANON = 0x00000100;
+        const ICANON = 0x00002;
         /// 表示启用大写模式,即输入输出都将被转换为大写。
-        const XCASE	 = 0x00004000;
+        const XCASE	 = 0x00004;
         /// 表示启用回显(显示用户输入的字符)
-        const ECHO	 = 0x00000008;
+        const ECHO	 = 0x00008;
         /// 表示在回显时将擦除的字符用 backspace 和空格字符显示。
-        const ECHOE	 = 0x00000002;
+        const ECHOE	 = 0x00010;
         /// 表示在回显时将换行符后的字符用空格字符显示。
-        const ECHOK	 = 0x00000004;
+        const ECHOK	 = 0x00020;
         /// 表示在回显时将换行符显示为换行和回车符。
-        const ECHONL = 0x00000010;
+        const ECHONL = 0x00040;
         /// 表示在收到中断(Ctrl-C)和退出(Ctrl-\)字符后,不清空输入和输出缓冲区。
-        const NOFLSH = 0x80000000;
+        const NOFLSH = 0x00080;
         /// 表示在后台进程尝试写入终端时,发送停止信号(Ctrl-S)
-        const TOSTOP = 0x00400000;
+        const TOSTOP = 0x00100;
         /// 表示在回显时,显示控制字符为 ^ 加字符。
-        const ECHOCTL= 0x00000040;
+        const ECHOCTL= 0x00200;
         /// 表示在回显时显示带有 # 的换行符(为了与 echo -n 命令兼容)。
-        const ECHOPRT= 0x00000020;
+        const ECHOPRT= 0x00400;
         /// 表示在回显时将 KILL 字符(Ctrl-U)用空格字符显示。
-        const ECHOKE = 0x00000001;
+        const ECHOKE = 0x00800;
         /// 表示输出正在被冲刷(flush),通常是由于输入/输出流的状态变化。
-        const FLUSHO = 0x00800000;
+        const FLUSHO = 0x01000;
         /// 表示在规范模式下,存在需要重新打印的字符。
-        const PENDIN = 0x20000000;
+        const PENDIN = 0x04000;
         /// 表示启用实现定义的输入处理。
-        const IEXTEN = 0x00000400;
+        const IEXTEN = 0x08000;
         /// 表示启用扩展的处理函数
-        const EXTPROC= 0x10000000;
+        const EXTPROC= 0x10000;
     }
 
     pub struct TtySetTermiosOpt: u8 {

+ 20 - 7
kernel/src/driver/tty/tty_core.rs

@@ -1,6 +1,6 @@
 use core::{fmt::Debug, sync::atomic::AtomicBool};
 
-use alloc::{string::String, sync::Arc, vec::Vec};
+use alloc::{collections::LinkedList, string::String, sync::Arc, vec::Vec};
 use system_error::SystemError;
 
 use crate::{
@@ -11,7 +11,7 @@ use crate::{
         wait_queue::EventWaitQueue,
     },
     mm::VirtAddr,
-    net::event_poll::EPollEventType,
+    net::event_poll::{EPollEventType, EPollItem},
     process::Pid,
     syscall::user_access::{UserBufferReader, UserBufferWriter},
 };
@@ -53,6 +53,7 @@ impl TtyCore {
             closing: AtomicBool::new(false),
             flow: SpinLock::new(TtyFlowState::default()),
             link: None,
+            epitems: SpinLock::new(LinkedList::new()),
         };
 
         return Arc::new(Self {
@@ -159,6 +160,13 @@ impl TtyCore {
                 user_writer.copy_one_to_user(&termios, 0)?;
                 return Ok(0);
             }
+            TtyIoctlCmd::TCSETS => {
+                return TtyCore::core_set_termios(
+                    real_tty,
+                    VirtAddr::new(arg),
+                    TtySetTermiosOpt::TERMIOS_OLD,
+                );
+            }
             TtyIoctlCmd::TCSETSW => {
                 return TtyCore::core_set_termios(
                     real_tty,
@@ -213,9 +221,7 @@ impl TtyCore {
         let mut termios = tty.core().termios_write();
 
         let old_termios = termios.clone();
-
         *termios = new_termios;
-
         let tmp = termios.control_mode;
         termios.control_mode ^= (tmp ^ old_termios.control_mode) & ControlMode::ADDRB;
 
@@ -300,6 +306,8 @@ pub struct TtyCoreData {
     flow: SpinLock<TtyFlowState>,
     /// 链接tty
     link: Option<Arc<TtyCore>>,
+    /// epitems
+    epitems: SpinLock<LinkedList<Arc<EPollItem>>>,
 }
 
 impl TtyCoreData {
@@ -335,17 +343,17 @@ impl TtyCoreData {
 
     #[inline]
     pub fn termios(&self) -> RwLockReadGuard<'_, Termios> {
-        self.termios.read()
+        self.termios.read_irqsave()
     }
 
     #[inline]
     pub fn termios_write(&self) -> RwLockWriteGuard<Termios> {
-        self.termios.write()
+        self.termios.write_irqsave()
     }
 
     #[inline]
     pub fn set_termios(&self, termios: Termios) {
-        let mut termios_guard = self.termios.write();
+        let mut termios_guard = self.termios.write_irqsave();
         *termios_guard = termios;
     }
 
@@ -394,6 +402,11 @@ impl TtyCoreData {
     pub fn link(&self) -> Option<Arc<TtyCore>> {
         self.link.clone()
     }
+
+    #[inline]
+    pub fn add_epitem(&self, epitem: Arc<EPollItem>) {
+        self.epitems.lock().push_back(epitem)
+    }
 }
 
 /// TTY 核心接口,不同的tty需要各自实现这个trait

+ 29 - 4
kernel/src/driver/tty/tty_device.rs

@@ -30,8 +30,9 @@ use crate::{
     init::initcall::INITCALL_DEVICE,
     libs::rwlock::RwLock,
     mm::VirtAddr,
+    net::event_poll::{EPollItem, EventPoll},
     process::ProcessManager,
-    syscall::user_access::UserBufferWriter,
+    syscall::user_access::{UserBufferReader, UserBufferWriter},
 };
 
 use super::{
@@ -131,7 +132,7 @@ impl IndexNode for TtyDevice {
                 && driver.tty_driver_sub_type() == TtyDriverSubType::PtyMaster))
         {
             let pcb = ProcessManager::current_pcb();
-            let pcb_tty = pcb.sig_info().tty();
+            let pcb_tty = pcb.sig_info_irqsave().tty();
             if pcb_tty.is_none() && tty.core().contorl_info_irqsave().session.is_none() {
                 TtyJobCtrlManager::proc_set_tty(tty);
             }
@@ -210,7 +211,7 @@ impl IndexNode for TtyDevice {
 
             // 将数据从buf拷贝到writebuf
 
-            let ret = ld.write(tty.clone(), buf, size, mode)?;
+            let ret = ld.write(tty.clone(), &buf[written..], size, mode)?;
 
             written += ret;
             count -= ret;
@@ -219,7 +220,7 @@ impl IndexNode for TtyDevice {
                 break;
             }
 
-            if pcb.sig_info().sig_pending().has_pending() {
+            if pcb.sig_info_irqsave().sig_pending().has_pending() {
                 return Err(SystemError::ERESTARTSYS);
             }
         }
@@ -273,6 +274,20 @@ impl IndexNode for TtyDevice {
                     todo!()
                 }
             }
+            EventPoll::ADD_EPOLLITEM => {
+                let _ = UserBufferReader::new(
+                    arg as *const Arc<EPollItem>,
+                    core::mem::size_of::<Arc<EPollItem>>(),
+                    false,
+                )?;
+                let epitem = unsafe { &*(arg as *const Arc<EPollItem>) };
+
+                let core = tty.core();
+
+                core.add_epitem(epitem.clone());
+
+                return Ok(0);
+            }
             _ => {}
         }
 
@@ -319,6 +334,16 @@ impl IndexNode for TtyDevice {
 
         Ok(0)
     }
+
+    fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> {
+        let (tty, _) = if let FilePrivateData::Tty(tty_priv) = private_data {
+            (tty_priv.tty.clone(), tty_priv.mode)
+        } else {
+            return Err(SystemError::EIO);
+        };
+
+        tty.ldisc().poll(tty)
+    }
 }
 
 impl DeviceINode for TtyDevice {

+ 7 - 5
kernel/src/driver/tty/tty_job_control.rs

@@ -34,7 +34,9 @@ impl TtyJobCtrlManager {
     pub fn tty_check_change(tty: Arc<TtyCore>, sig: Signal) -> Result<(), SystemError> {
         let pcb = ProcessManager::current_pcb();
 
-        if pcb.sig_info().tty().is_none() || !Arc::ptr_eq(&pcb.sig_info().tty().unwrap(), &tty) {
+        if pcb.sig_info_irqsave().tty().is_none()
+            || !Arc::ptr_eq(&pcb.sig_info_irqsave().tty().unwrap(), &tty)
+        {
             return Ok(());
         }
 
@@ -91,8 +93,8 @@ impl TtyJobCtrlManager {
 
                 let mut ctrl = tty.core().contorl_info_irqsave();
 
-                if current.sig_info().tty().is_none()
-                    || !Arc::ptr_eq(&current.sig_info().tty().clone().unwrap(), &tty)
+                if current.sig_info_irqsave().tty().is_none()
+                    || !Arc::ptr_eq(&current.sig_info_irqsave().tty().clone().unwrap(), &tty)
                     || ctrl.session.is_none()
                     || ctrl.session.unwrap() != current.pid()
                 {
@@ -106,8 +108,8 @@ impl TtyJobCtrlManager {
 
             TtyIoctlCmd::TIOCGPGRP => {
                 let current = ProcessManager::current_pcb();
-                if current.sig_info().tty().is_some()
-                    && !Arc::ptr_eq(&current.sig_info().tty().unwrap(), &tty)
+                if current.sig_info_irqsave().tty().is_some()
+                    && !Arc::ptr_eq(&current.sig_info_irqsave().tty().unwrap(), &tty)
                 {
                     return Err(SystemError::ENOTTY);
                 }

+ 1 - 1
kernel/src/driver/tty/tty_ldisc/mod.rs

@@ -48,7 +48,7 @@ pub trait TtyLineDiscipline: Sync + Send + Debug {
     /// - old: 之前的termios,如果为None则表示第一次设置
     fn set_termios(&self, tty: Arc<TtyCore>, old: Option<Termios>) -> Result<(), SystemError>;
 
-    fn poll(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>;
+    fn poll(&self, tty: Arc<TtyCore>) -> Result<usize, SystemError>;
     fn hangup(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>;
 
     /// ## 接收数据

+ 105 - 33
kernel/src/driver/tty/tty_ldisc/ntty.rs

@@ -1,3 +1,4 @@
+use core::intrinsics::likely;
 use core::ops::BitXor;
 
 use bitmap::{traits::BitMapOps, StaticBitmap};
@@ -249,11 +250,10 @@ impl NTtyData {
             || termios.local_mode.contains(LocalMode::IEXTEN);
 
         let look_ahead = self.lookahead_count.min(count);
-
         if self.real_raw {
-            todo!("tty real raw mode todo");
+            self.receive_buf_real_raw(buf, count);
         } else if self.raw || (termios.local_mode.contains(LocalMode::EXTPROC) && !preops) {
-            todo!("tty raw mode todo");
+            self.receive_buf_raw(buf, flags, count);
         } else if tty.core().is_closing() && !termios.local_mode.contains(LocalMode::EXTPROC) {
             todo!()
         } else {
@@ -282,7 +282,47 @@ impl NTtyData {
         if self.read_cnt() > 0 {
             tty.core()
                 .read_wq()
-                .wakeup((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDBAND).bits() as u64);
+                .wakeup_any((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDBAND).bits() as u64);
+        }
+    }
+
+    fn receive_buf_real_raw(&mut self, buf: &[u8], mut count: usize) {
+        let mut head = ntty_buf_mask(self.read_head);
+        let mut n = count.min(NTTY_BUFSIZE - head);
+
+        // 假如有一部分在队列头部,则这部分是拷贝尾部部分
+        self.read_buf[head..(head + n)].copy_from_slice(&buf[0..n]);
+        self.read_head += n;
+        count -= n;
+        let offset = n;
+
+        // 假如有一部分在队列头部,则这部分是拷贝头部部分
+        head = ntty_buf_mask(self.read_head);
+        n = count.min(NTTY_BUFSIZE - head);
+        self.read_buf[head..(head + n)].copy_from_slice(&buf[offset..(offset + n)]);
+        self.read_head += n;
+    }
+
+    fn receive_buf_raw(&mut self, buf: &[u8], flags: Option<&[u8]>, mut count: usize) {
+        // TTY_NORMAL 目前这部分未做,所以先占位置而不做抽象
+        let mut flag = 1;
+        let mut f_offset = 0;
+        let mut c_offset = 0;
+        while count != 0 {
+            if flags.is_some() {
+                flag = flags.as_ref().unwrap()[f_offset];
+                f_offset += 1;
+            }
+
+            if likely(flag == 1) {
+                self.read_buf[self.read_head] = buf[c_offset];
+                c_offset += 1;
+                self.read_head += 1;
+            } else {
+                todo!()
+            }
+
+            count -= 1;
         }
     }
 
@@ -364,6 +404,7 @@ impl NTtyData {
         }
     }
 
+    #[inline(never)]
     pub fn receive_special_char(&mut self, mut c: u8, tty: Arc<TtyCore>, lookahead_done: bool) {
         let is_flow_ctrl = self.is_flow_ctrl_char(tty.clone(), c, lookahead_done);
         let termios = tty.core().termios();
@@ -467,9 +508,9 @@ impl NTtyData {
                 self.read_buf[ntty_buf_mask(self.read_head)] = c;
                 self.read_head += 1;
                 self.canon_head = self.read_head;
-                tty.core()
-                    .read_wq()
-                    .wakeup((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64);
+                tty.core().read_wq().wakeup_any(
+                    (EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64,
+                );
                 return;
             }
 
@@ -480,9 +521,9 @@ impl NTtyData {
                 self.read_buf[ntty_buf_mask(self.read_head)] = c;
                 self.read_head += 1;
                 self.canon_head = self.read_head;
-                tty.core()
-                    .read_wq()
-                    .wakeup((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64);
+                tty.core().read_wq().wakeup_any(
+                    (EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64,
+                );
                 return;
             }
 
@@ -508,9 +549,9 @@ impl NTtyData {
                 self.read_buf[ntty_buf_mask(self.read_head)] = c;
                 self.read_head += 1;
                 self.canon_head = self.read_head;
-                tty.core()
-                    .read_wq()
-                    .wakeup((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64);
+                tty.core().read_wq().wakeup_any(
+                    (EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64,
+                );
                 return;
             }
         }
@@ -540,6 +581,7 @@ impl NTtyData {
     }
 
     /// ## ntty默认eraser function
+    #[inline(never)]
     fn eraser(&mut self, mut c: u8, termios: &RwLockReadGuard<Termios>) {
         if self.read_head == self.canon_head {
             return;
@@ -907,7 +949,7 @@ impl NTtyData {
             // 有一部分数据在头部,则先拷贝后面部分,再拷贝头部
             // TODO: tty审计?
             to[0..size].copy_from_slice(&self.read_buf[tail..(tail + size)]);
-            to[size..].copy_from_slice(&self.read_buf[(tail + size)..(*n + tail)]);
+            to[size..(*n)].copy_from_slice(&self.read_buf[0..(*n - size)]);
         } else {
             to[..*n].copy_from_slice(&self.read_buf[tail..(tail + *n)])
         }
@@ -975,7 +1017,7 @@ impl NTtyData {
         let size = if tail + n > NTTY_BUFSIZE {
             NTTY_BUFSIZE
         } else {
-            tail + *nr
+            tail + n
         };
 
         // 找到eol的坐标
@@ -1088,7 +1130,7 @@ impl NTtyData {
         let tail = self.read_tail & (NTTY_BUFSIZE - 1);
 
         // 计算出可读的字符数
-        let mut n = (NTTY_BUFSIZE - tail).min(self.read_tail);
+        let mut n = (NTTY_BUFSIZE - tail).min(head - self.read_tail);
         n = n.min(*nr);
 
         if n > 0 {
@@ -1209,6 +1251,7 @@ impl NTtyData {
         }
     }
 
+    #[inline(never)]
     pub fn echoes(&mut self, tty: Arc<TtyCore>) -> Result<usize, SystemError> {
         let mut space = tty.write_room(tty.core());
         let ospace = space;
@@ -1519,6 +1562,7 @@ impl TtyLineDiscipline for NTtyLinediscipline {
         Ok(())
     }
 
+    #[inline(never)]
     fn read(
         &self,
         tty: Arc<TtyCore>,
@@ -1555,7 +1599,7 @@ impl TtyLineDiscipline for NTtyLinediscipline {
                     return Ok(len - nr);
                 }
             } else {
-                if ldata.canon_copy_from_read_buf(buf, &mut nr, &mut offset)? {
+                if ldata.copy_from_read_buf(termios, buf, &mut nr, &mut offset)? {
                     return Ok(len - nr);
                 }
             }
@@ -1610,7 +1654,7 @@ impl TtyLineDiscipline for NTtyLinediscipline {
                 }
 
                 if ProcessManager::current_pcb()
-                    .sig_info()
+                    .sig_info_irqsave()
                     .sig_pending()
                     .has_pending()
                 {
@@ -1666,6 +1710,7 @@ impl TtyLineDiscipline for NTtyLinediscipline {
         ret
     }
 
+    #[inline(never)]
     fn write(
         &self,
         tty: Arc<TtyCore>,
@@ -1687,7 +1732,7 @@ impl TtyLineDiscipline for NTtyLinediscipline {
         // drop(ldata);
         let mut offset = 0;
         loop {
-            if pcb.sig_info().sig_pending().has_pending() {
+            if pcb.sig_info_irqsave().sig_pending().has_pending() {
                 return Err(SystemError::ERESTARTSYS);
             }
             if core.flags().contains(TtyFlag::HUPPED) {
@@ -1818,6 +1863,7 @@ impl TtyLineDiscipline for NTtyLinediscipline {
         }
     }
 
+    #[inline(never)]
     fn set_termios(
         &self,
         tty: Arc<TtyCore>,
@@ -1829,14 +1875,13 @@ impl TtyLineDiscipline for NTtyLinediscipline {
         let contorl_chars = termios.control_characters;
 
         // 第一次设置或者规范模式 (ICANON) 或者扩展处理 (EXTPROC) 标志发生变化
-        if old.is_none()
-            || (old.is_some()
-                && old
-                    .unwrap()
-                    .local_mode
-                    .bitxor(termios.local_mode)
-                    .contains(LocalMode::ICANON | LocalMode::EXTPROC))
-        {
+        let mut spec_mode_changed = false;
+        if old.is_some() {
+            let local_mode = old.clone().unwrap().local_mode.bitxor(termios.local_mode);
+            spec_mode_changed =
+                local_mode.contains(LocalMode::ICANON) || local_mode.contains(LocalMode::EXTPROC);
+        }
+        if old.is_none() || spec_mode_changed {
             // 重置read_flags
             ldata.read_flags.set_all(false);
 
@@ -1859,10 +1904,8 @@ impl TtyLineDiscipline for NTtyLinediscipline {
             ldata.lnext = false;
         }
 
-        // 设置规范模式
-        if termios.local_mode.contains(LocalMode::ICANON) {
-            ldata.icanon = true;
-        }
+        // 设置模式
+        ldata.icanon = termios.local_mode.contains(LocalMode::ICANON);
 
         // 设置回显
         if termios.local_mode.contains(LocalMode::ECHO) {
@@ -1984,8 +2027,37 @@ impl TtyLineDiscipline for NTtyLinediscipline {
         Ok(())
     }
 
-    fn poll(&self, _tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> {
-        todo!()
+    fn poll(&self, tty: Arc<TtyCore>) -> Result<usize, system_error::SystemError> {
+        let core = tty.core();
+        let ldata = self.disc_data();
+
+        let mut event = EPollEventType::empty();
+        if ldata.input_available(core.termios(), true) {
+            event.insert(EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM)
+        }
+
+        if core.contorl_info_irqsave().packet {
+            let link = core.link();
+            if link.is_some() && link.unwrap().core().contorl_info_irqsave().pktstatus != 0 {
+                event.insert(
+                    EPollEventType::EPOLLPRI
+                        | EPollEventType::EPOLLIN
+                        | EPollEventType::EPOLLRDNORM,
+                );
+            }
+        }
+
+        if core.flags().contains(TtyFlag::OTHER_CLOSED) {
+            event.insert(EPollEventType::EPOLLHUP);
+        }
+
+        if core.driver().driver_funcs().chars_in_buffer() < 256
+            && core.driver().driver_funcs().write_room(core) > 0
+        {
+            event.insert(EPollEventType::EPOLLOUT | EPollEventType::EPOLLWRNORM);
+        }
+
+        Ok(event.bits() as usize)
     }
 
     fn hangup(&self, _tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> {

+ 55 - 46
kernel/src/driver/tty/virtual_terminal/mod.rs

@@ -102,6 +102,54 @@ impl TtyConsoleDriverInner {
             console: Arc::new(BlittingFbConsole::new()?),
         })
     }
+
+    fn do_write(&self, tty: &TtyCoreData, buf: &[u8], mut nr: usize) -> Result<usize, SystemError> {
+        // 关闭中断
+        let mut vc_data = tty.vc_data_irqsave();
+
+        let mut offset = 0;
+
+        // 这个参数是用来扫描unicode字符的,但是这部分目前未完成,先写着
+        let mut rescan = false;
+        let mut ch: u32 = 0;
+
+        let mut draw = DrawRegion::default();
+
+        // 首先隐藏光标再写
+        vc_data.hide_cursor();
+
+        while nr != 0 {
+            if !rescan {
+                ch = buf[offset] as u32;
+                offset += 1;
+                nr -= 1;
+            }
+
+            let (tc, rescan_last) = vc_data.translate(&mut ch);
+            if tc.is_none() {
+                // 表示未转换完成
+                continue;
+            }
+
+            let tc = tc.unwrap();
+            rescan = rescan_last;
+
+            if vc_data.is_control(tc, ch) {
+                vc_data.flush(&mut draw);
+                vc_data.do_control(ch);
+                continue;
+            }
+
+            if !vc_data.console_write_normal(tc, ch, &mut draw) {
+                continue;
+            }
+        }
+
+        vc_data.flush(&mut draw);
+
+        // TODO: notify update
+        return Ok(offset);
+    }
 }
 
 impl TtyOperation for TtyConsoleDriverInner {
@@ -135,6 +183,7 @@ impl TtyOperation for TtyConsoleDriverInner {
             let mut window_size = window_size.upgrade();
             window_size.col = vc_data.cols as u16;
             window_size.row = vc_data.rows as u16;
+            kerror!("window_size {:?}", *window_size);
         }
 
         if vc_data.utf {
@@ -157,54 +206,14 @@ impl TtyOperation for TtyConsoleDriverInner {
     }
 
     /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/vt/vt.c#2894
-    fn write(&self, tty: &TtyCoreData, buf: &[u8], mut nr: usize) -> Result<usize, SystemError> {
-        // 关闭中断
-        let mut vc_data = tty.vc_data_irqsave();
-
-        let mut offset = 0;
-
-        // 这个参数是用来扫描unicode字符的,但是这部分目前未完成,先写着
-        let mut rescan = false;
-        let mut ch: u32 = 0;
-
-        let mut draw = DrawRegion::default();
-
-        // 首先隐藏光标再写
-        vc_data.hide_cursor();
-
-        while nr != 0 {
-            if !rescan {
-                ch = buf[offset] as u32;
-                offset += 1;
-                nr -= 1;
-            }
-
-            let (tc, rescan_last) = vc_data.translate(&mut ch);
-            if tc.is_none() {
-                // 表示未转换完成
-                continue;
-            }
-
-            let tc = tc.unwrap();
-            rescan = rescan_last;
-
-            if vc_data.is_control(tc, ch) {
-                vc_data.flush(&mut draw);
-                vc_data.do_control(ch);
-                continue;
-            }
-
-            if !vc_data.console_write_normal(tc, ch, &mut draw) {
-                continue;
-            }
-        }
-
-        vc_data.flush(&mut draw);
-
-        // TODO: notify update
-        return Ok(offset);
+    #[inline(never)]
+    fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
+        let ret = self.do_write(tty, buf, nr);
+        self.flush_chars(tty);
+        ret
     }
 
+    #[inline(never)]
     fn flush_chars(&self, tty: &TtyCoreData) {
         let mut vc_data = tty.vc_data_irqsave();
         vc_data.set_cursor();

+ 41 - 15
kernel/src/driver/tty/virtual_terminal/virtual_console.rs

@@ -7,7 +7,10 @@ use alloc::{
 use bitmap::{traits::BitMapOps, StaticBitmap};
 
 use crate::{
-    driver::tty::{console::ConsoleSwitch, ConsoleFont, KDMode},
+    driver::{
+        serial::serial8250::send_to_default_serial8250_port,
+        tty::{console::ConsoleSwitch, ConsoleFont, KDMode},
+    },
     libs::{font::FontDesc, rwlock::RwLock},
     process::Pid,
 };
@@ -140,6 +143,7 @@ pub struct VirtualConsoleData {
 }
 
 impl VirtualConsoleData {
+    #[inline(never)]
     pub fn new(num: usize) -> Self {
         Self {
             state: VirtualConsoleInfo::new(0, 0),
@@ -264,7 +268,8 @@ impl VirtualConsoleData {
         self.pid = None;
         self.vc_state = VirtualConsoleState::ESnormal;
         self.reset_palette();
-        self.cursor_type = VcCursor::CUR_UNDERLINE;
+        // self.cursor_type = VcCursor::CUR_UNDERLINE;
+        self.cursor_type = VcCursor::CUR_BLOCK;
 
         self.default_attr();
         self.update_attr();
@@ -567,10 +572,10 @@ impl VirtualConsoleData {
         let min_y;
         if self.origin_mode {
             min_y = self.top;
-            max_y = self.bottom;
+            max_y = self.bottom - 1;
         } else {
             min_y = 0;
-            max_y = self.rows;
+            max_y = self.rows - 1;
         }
 
         if y < min_y as i32 {
@@ -596,9 +601,10 @@ impl VirtualConsoleData {
             return;
         }
 
-        if self
-            .driver_funcs()
-            .con_scroll(self, self.top, self.bottom, dir, nr)
+        if self.is_visible()
+            && self
+                .driver_funcs()
+                .con_scroll(self, self.top, self.bottom, dir, nr)
         {
             // 如果成功
             return;
@@ -733,6 +739,7 @@ impl VirtualConsoleData {
         }
     }
 
+    #[inline(never)]
     fn do_getpars(&mut self, c: char) {
         if c == ';' && self.npar < (NPAR - 1) as u32 {
             self.npar += 1;
@@ -789,9 +796,11 @@ impl VirtualConsoleData {
             'n' => {
                 if self.private == Vt102_OP::EPecma {
                     if self.par[0] == 5 {
-                        kwarn!("tty status report todo");
+                        send_to_default_serial8250_port("tty status report todo".as_bytes());
+                        panic!();
                     } else if self.par[0] == 6 {
-                        kwarn!("tty cursor report todo");
+                        send_to_default_serial8250_port("tty cursor report todo".as_bytes());
+                        panic!();
                     }
                 }
                 return;
@@ -847,7 +856,7 @@ impl VirtualConsoleData {
                     self.par[0] += 1;
                 }
                 self.gotoxy(
-                    (self.state.x - self.par[0] as usize) as i32,
+                    self.state.x as i32 - self.par[0] as i32,
                     self.state.y as i32,
                 );
                 return;
@@ -863,7 +872,7 @@ impl VirtualConsoleData {
                 if self.par[0] == 0 {
                     self.par[0] += 1;
                 }
-                self.gotoxy(0, (self.state.y - self.par[0] as usize) as i32);
+                self.gotoxy(0, self.state.y as i32 - self.par[0] as i32);
                 return;
             }
             'd' => {
@@ -874,6 +883,7 @@ impl VirtualConsoleData {
                 return;
             }
             'H' | 'f' => {
+                // MOVETO
                 if self.par[0] != 0 {
                     self.par[0] -= 1;
                 }
@@ -900,6 +910,18 @@ impl VirtualConsoleData {
             'P' => {
                 todo!("csi_P todo");
             }
+
+            // 非ANSI标准,为ANSI拓展
+            'S' => {
+                self.scroll(ScrollDir::Up, self.par[0] as usize);
+                return;
+            }
+
+            'T' => {
+                self.scroll(ScrollDir::Down, self.par[0] as usize);
+                return;
+            }
+
             'c' => {
                 if self.par[0] == 0 {
                     kwarn!("respone ID todo");
@@ -957,6 +979,7 @@ impl VirtualConsoleData {
     }
 
     /// ##  处理Control Sequence Introducer(控制序列引导符) m字符
+    #[inline(never)]
     fn csi_m(&mut self) {
         let mut i = 0;
         loop {
@@ -1236,6 +1259,7 @@ impl VirtualConsoleData {
     }
 
     /// ## 处理终端控制字符
+    #[inline(never)]
     pub(super) fn do_control(&mut self, ch: u32) {
         // 首先检查是否处于 ANSI 控制字符串状态
         if self.vc_state.is_ansi_control_string() && ch >= 8 && ch <= 13 {
@@ -1512,6 +1536,7 @@ impl VirtualConsoleData {
         }
     }
 
+    #[inline(never)]
     pub(super) fn console_write_normal(
         &mut self,
         mut tc: u32,
@@ -1641,11 +1666,10 @@ impl VirtualConsoleData {
     fn do_update_region(&self, mut start: usize, mut count: usize) {
         let ret = self.driver_funcs().con_getxy(self, start);
         let (mut x, mut y) = if ret.is_err() {
-            let offset = start / 2;
-            (offset % self.cols, offset / self.cols)
+            (start % self.cols, start / self.cols)
         } else {
-            let (tmp_start, tmp_x, tmp_y) = ret.unwrap();
-            start = tmp_start;
+            let (_, tmp_x, tmp_y) = ret.unwrap();
+            // start = tmp_start;
             (tmp_x, tmp_y)
         };
 
@@ -1697,6 +1721,8 @@ impl VirtualConsoleData {
             let ret = self.driver_funcs().con_getxy(self, start);
             if ret.is_ok() {
                 start = ret.unwrap().0;
+            } else {
+                return;
             }
         }
     }

+ 27 - 2
kernel/src/driver/video/fbdev/base/fbcon/framebuffer_console.rs

@@ -391,6 +391,7 @@ impl ConsoleSwitch for BlittingFbConsole {
         Ok(())
     }
 
+    #[inline(never)]
     fn con_scroll(
         &self,
         vc_data: &mut VirtualConsoleData,
@@ -504,7 +505,30 @@ impl ConsoleSwitch for BlittingFbConsole {
                 }
 
                 match scroll_mode {
-                    ScrollMode::Move => todo!(),
+                    ScrollMode::Move => {
+                        let start = top * vc_data.cols;
+                        let end = bottom * vc_data.cols;
+                        vc_data.screen_buf[start..end].rotate_right(count * vc_data.cols);
+
+                        let _ = self.bmove(
+                            vc_data,
+                            top as i32,
+                            0,
+                            top as i32 + count as i32,
+                            0,
+                            (bottom - top - count) as u32,
+                            vc_data.cols as u32,
+                        );
+
+                        let _ = self.con_clear(vc_data, top, 0, count, vc_data.cols);
+
+                        let offset = vc_data.cols * count;
+                        for i in vc_data.screen_buf[start..(start + offset)].iter_mut() {
+                            *i = vc_data.erase_char;
+                        }
+
+                        return true;
+                    }
                     ScrollMode::PanMove => todo!(),
                     ScrollMode::WrapMove => todo!(),
                     ScrollMode::Redraw => {
@@ -554,7 +578,8 @@ impl FrameBufferConsole for BlittingFbConsole {
             sy * vc_data.font.height as i32,
         );
 
-        self.fb().fb_copyarea(area)
+        self.fb().fb_copyarea(area);
+        Ok(())
     }
 
     fn clear(

+ 1 - 3
kernel/src/driver/video/fbdev/base/mod.rs

@@ -408,9 +408,7 @@ pub trait FrameBufferOps {
     }
 
     /// 将数据从一处复制到另一处。
-    fn fb_copyarea(&self, _data: CopyAreaData) -> Result<(), SystemError> {
-        Err(SystemError::ENOSYS)
-    }
+    fn fb_copyarea(&self, _data: CopyAreaData);
 
     /// 将帧缓冲区的内容映射到用户空间。
     fn fb_mmap(&self, _vma: &Arc<LockedVMA>) -> Result<(), SystemError> {

+ 111 - 60
kernel/src/driver/video/fbdev/vesafb.rs

@@ -418,86 +418,138 @@ impl FrameBufferOps for VesaFb {
         Ok(())
     }
 
-    fn fb_copyarea(&self, data: super::base::CopyAreaData) -> Result<(), SystemError> {
+    #[inline(never)]
+    fn fb_copyarea(&self, data: super::base::CopyAreaData) {
         let bp = boot_params().read();
-        let base = bp.screen_info.lfb_virt_base.ok_or(SystemError::ENODEV)?;
+        let base = bp.screen_info.lfb_virt_base.unwrap();
         let var = self.current_fb_var();
 
-        if data.sx < 0
-            || data.sy < 0
-            || data.sx as u32 > var.xres
-            || data.sx as u32 + data.width > var.xres
-            || data.sy as u32 > var.yres
-            || data.sy as u32 + data.height > var.yres
+        // 原区域或者目标区域全在屏幕外,则直接返回
+        if data.sx > var.xres as i32
+            || data.sy > var.yres as i32
+            || data.dx > var.xres as i32
+            || data.dy > var.yres as i32
+            || (data.sx + data.width as i32) < 0
+            || (data.sy + data.height as i32) < 0
+            || (data.dx + data.width as i32) < 0
+            || (data.dy + data.height as i32) < 0
         {
-            return Err(SystemError::EINVAL);
+            return;
         }
 
-        let bytes_per_pixel = var.bits_per_pixel >> 3;
-        let bytes_per_line = var.xres * bytes_per_pixel;
+        // 求两个矩形可视范围交集
+        let (s_visiable_x, s_w) = if data.sx < 0 {
+            (0, (data.width - ((-data.sx) as u32)).min(var.xres))
+        } else {
+            let w = if data.sx as u32 + data.width > var.xres {
+                var.xres - data.sx as u32
+            } else {
+                data.width
+            };
 
-        let sy = data.sy as u32;
-        let sx = data.sx as u32;
+            (data.sx, w)
+        };
+        let (s_visiable_y, s_h) = if data.sy < 0 {
+            (0, (data.height - ((-data.sy) as u32).min(var.yres)))
+        } else {
+            let h = if data.sy as u32 + data.height > var.yres {
+                var.yres - data.sy as u32
+            } else {
+                data.height
+            };
 
-        let dst = {
-            let mut dst = base;
-            if data.dy < 0 {
-                dst -= VirtAddr::new((((-data.dy) as u32) * bytes_per_line) as usize);
+            (data.sy, h)
+        };
+
+        let (d_visiable_x, d_w) = if data.dx < 0 {
+            (0, (data.width - ((-data.dx) as u32)).min(var.xres))
+        } else {
+            let w = if data.dx as u32 + data.width > var.xres {
+                var.xres - data.dx as u32
             } else {
-                dst += VirtAddr::new(((data.dy as u32) * bytes_per_line) as usize);
-            }
+                data.width
+            };
 
-            if data.dx > 0 && (data.dx as u32) < var.xres {
-                dst += VirtAddr::new(((data.dx as u32) * bytes_per_pixel) as usize);
-            }
+            (data.dx, w)
+        };
+        let (d_visiable_y, d_h) = if data.dy < 0 {
+            (0, (data.height - ((-data.dy) as u32).min(var.yres)))
+        } else {
+            let h = if data.dy as u32 + data.height > var.yres {
+                var.yres - data.dy as u32
+            } else {
+                data.height
+            };
 
-            dst
+            (data.dy, h)
         };
-        let src = base + VirtAddr::new((sy * bytes_per_line + sx * bytes_per_pixel) as usize);
+
+        // 可视范围无交集
+        if !(d_h + s_h > data.height && s_w + d_w > data.width) {
+            return;
+        }
+
+        // 可视区域左上角相对于矩形的坐标
+        let s_relative_x = s_visiable_x - data.sx;
+        let s_relative_y = s_visiable_y - data.sy;
+        let d_relative_x = d_visiable_x - data.dx;
+        let d_relative_y = d_visiable_y - data.dy;
+
+        let visiable_x = s_relative_x.max(d_relative_x);
+        let visiable_y = s_relative_y.max(d_relative_y);
+        let visiable_h = d_h + s_h - data.height;
+        let visiable_w = d_w + s_w - data.width;
+
+        let s_real_x = (visiable_x + data.sx) as u32;
+        let s_real_y = (visiable_y + data.sy) as u32;
+        let d_real_x = (visiable_x + data.dx) as u32;
+        let d_real_y = (visiable_y + data.dy) as u32;
+
+        let bytes_per_pixel = var.bits_per_pixel >> 3;
+        let bytes_per_line = var.xres * bytes_per_pixel;
+
+        let src =
+            base + VirtAddr::new((s_real_y * bytes_per_line + s_real_x * bytes_per_pixel) as usize);
+
+        let dst =
+            base + VirtAddr::new((d_real_y * bytes_per_line + d_real_x * bytes_per_pixel) as usize);
+
+        let size = (visiable_h * visiable_w) as usize;
 
         match bytes_per_pixel {
             4 => {
                 // 32bpp
                 let mut dst = dst.as_ptr::<u32>();
                 let mut src = src.as_ptr::<u32>();
-
-                for y in 0..data.height as usize {
-                    if (data.dy + y as i32) < 0 || (data.dy + y as i32) > var.yres as i32 {
-                        unsafe {
-                            // core::ptr::copy(src, dst, data.width as usize);
-                            src = src.add(var.xres as usize);
-                            dst = dst.add(var.xres as usize);
+                let line_offset = var.xres as usize;
+
+                if s_real_x > d_real_x {
+                    // 如果src在dst下方,则可以直接拷贝不会出现指针覆盖
+                    unsafe {
+                        for _ in 0..visiable_h {
+                            core::ptr::copy(src, dst, visiable_w as usize);
+                            src = src.add(line_offset);
+                            dst = dst.add(visiable_w as usize);
                         }
-                        continue;
                     }
-                    if data.dx < 0 {
-                        if ((-data.dx) as u32) < data.width {
-                            unsafe {
-                                core::ptr::copy(
-                                    src.add((-data.dx) as usize),
-                                    dst,
-                                    (data.width as usize) - (-data.dx) as usize,
-                                );
-                                src = src.add(var.xres as usize);
-                                dst = dst.add(var.xres as usize);
-                            }
-                        }
-                    } else if data.dx as u32 + data.width > var.xres {
-                        if (data.dx as u32) < var.xres {
-                            unsafe {
-                                core::ptr::copy(src, dst, (var.xres - data.dx as u32) as usize);
-                                src = src.add(var.xres as usize);
-                                dst = dst.add(var.xres as usize);
-                            }
+                } else {
+                    let mut tmp: Vec<u32> = Vec::with_capacity(size);
+                    tmp.resize(size, 0);
+                    let mut tmp_ptr = tmp.as_mut_ptr();
+
+                    // 这里是一个可以优化的点,现在为了避免指针拷贝时覆盖,统一先拷贝进入buf再拷贝到dst
+                    unsafe {
+                        for _ in 0..visiable_h {
+                            core::ptr::copy(src, tmp_ptr, visiable_w as usize);
+                            src = src.add(line_offset);
+                            tmp_ptr = tmp_ptr.add(visiable_w as usize);
                         }
-                    } else {
-                        for i in 0..data.width as usize {
-                            unsafe { *(dst.add(i)) = *(src.add(i)) }
-                        }
-                        unsafe {
-                            // core::ptr::copy(src, dst, data.width as usize);
-                            src = src.add(var.xres as usize);
-                            dst = dst.add(var.xres as usize);
+
+                        tmp_ptr = tmp_ptr.sub(size);
+                        for _ in 0..visiable_h {
+                            core::ptr::copy(tmp_ptr, dst, visiable_w as usize);
+                            dst = dst.add(line_offset);
+                            tmp_ptr = tmp_ptr.add(visiable_w as usize);
                         }
                     }
                 }
@@ -506,7 +558,6 @@ impl FrameBufferOps for VesaFb {
                 todo!()
             }
         }
-        Ok(())
     }
 }
 

+ 12 - 1
kernel/src/filesystem/vfs/file.rs

@@ -484,7 +484,18 @@ impl File {
                 let inode = self.inode.downcast_ref::<LockedPipeInode>().unwrap();
                 return inode.inner().lock().add_epoll(epitem);
             }
-            _ => return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP),
+            _ => {
+                let r = self.inode.ioctl(
+                    EventPoll::ADD_EPOLLITEM,
+                    &epitem as *const Arc<EPollItem> as usize,
+                    &self.private_data,
+                );
+                if r.is_err() {
+                    return Err(SystemError::ENOSYS);
+                }
+
+                Ok(())
+            }
         }
     }
 

+ 5 - 0
kernel/src/filesystem/vfs/mount.rs

@@ -369,6 +369,11 @@ impl IndexNode for MountFSInode {
     fn special_node(&self) -> Option<super::SpecialNodeData> {
         self.inner_inode.special_node()
     }
+
+    #[inline]
+    fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> {
+        self.inner_inode.poll(private_data)
+    }
 }
 
 impl FileSystem for MountFS {

+ 13 - 5
kernel/src/ipc/signal.rs

@@ -86,7 +86,7 @@ impl Signal {
             return Err(SystemError::EINVAL);
         }
         // kdebug!("force send={}", force_send);
-        let pcb_info = pcb.sig_info();
+        let pcb_info = pcb.sig_info_irqsave();
         let pending = if matches!(pt, PidType::PID) {
             pcb_info.sig_shared_pending()
         } else {
@@ -189,7 +189,11 @@ impl Signal {
     #[inline]
     fn wants_signal(&self, pcb: Arc<ProcessControlBlock>) -> bool {
         // 如果改进程屏蔽了这个signal,则不能接收
-        if pcb.sig_info().sig_block().contains(self.clone().into()) {
+        if pcb
+            .sig_info_irqsave()
+            .sig_block()
+            .contains(self.clone().into())
+        {
             return false;
         }
 
@@ -209,7 +213,7 @@ impl Signal {
         // todo: 检查目标进程是否正在一个cpu上执行,如果是,则返回true,否则继续检查下一项
 
         // 检查目标进程是否有信号正在等待处理,如果是,则返回false,否则返回true
-        if pcb.sig_info().sig_pending().signal().bits() == 0 {
+        if pcb.sig_info_irqsave().sig_pending().signal().bits() == 0 {
             return true;
         } else {
             return false;
@@ -263,7 +267,11 @@ impl Signal {
         }
 
         // 一个被阻塞了的信号肯定是要被处理的
-        if pcb.sig_info().sig_block().contains(self.into_sigset()) {
+        if pcb
+            .sig_info_irqsave()
+            .sig_block()
+            .contains(self.into_sigset())
+        {
             return true;
         }
         return !pcb.sig_struct().handlers[self.clone() as usize - 1].is_ignore();
@@ -430,7 +438,7 @@ pub fn set_current_sig_blocked(new_set: &mut SigSet) {
         如果当前pcb的sig_blocked和新的相等,那么就不用改变它。
         请注意,一个进程的sig_blocked字段不能被其他进程修改!
     */
-    if pcb.sig_info().sig_block().eq(new_set) {
+    if pcb.sig_info_irqsave().sig_block().eq(new_set) {
         return;
     }
 

+ 1 - 1
kernel/src/libs/printk.c

@@ -599,7 +599,7 @@ int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, ..
     io_mfence();
     va_list args;
     va_start(args, fmt);
-    char buf[4096]; // vsprintf()的缓冲区
+    static char buf[4096]; // vsprintf()的缓冲区
     int len = vsprintf(buf, fmt, args);
 
     va_end(args);

+ 17 - 0
kernel/src/libs/rwlock.rs

@@ -218,6 +218,23 @@ impl<T> RwLock<T> {
         return r;
     } //当架构为arm时,有些代码需要作出调整compare_exchange=>compare_exchange_weak
 
+    #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
+    #[allow(dead_code)]
+    #[inline]
+    pub fn try_write_irqsave(&self) -> Option<RwLockWriteGuard<T>> {
+        ProcessManager::preempt_disable();
+        let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
+        let r = self.inner_try_write().map(|mut g| {
+            g.irq_guard = Some(irq_guard);
+            g
+        });
+        if r.is_none() {
+            ProcessManager::preempt_enable();
+        }
+
+        return r;
+    }
+
     #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
     #[allow(dead_code)]
     fn inner_try_write(&self) -> Option<RwLockWriteGuard<T>> {

+ 3 - 1
kernel/src/net/event_poll/mod.rs

@@ -52,6 +52,8 @@ pub struct EventPoll {
 
 impl EventPoll {
     pub const EP_MAX_EVENTS: u32 = INT32_MAX / (core::mem::size_of::<EPollEvent>() as u32);
+    /// 用于获取inode中的epitem队列
+    pub const ADD_EPOLLITEM: u32 = 0x7965;
     pub fn new() -> Self {
         Self {
             epoll_wq: WaitQueue::INIT,
@@ -462,7 +464,7 @@ impl EventPoll {
                 }
 
                 // 如果有未处理的信号则返回错误
-                if current_pcb.sig_info().sig_pending().signal().bits() != 0 {
+                if current_pcb.sig_info_irqsave().sig_pending().signal().bits() != 0 {
                     return Err(SystemError::EINTR);
                 }
 

+ 9 - 7
kernel/src/process/fork.rs

@@ -363,12 +363,12 @@ impl ProcessManager {
 
         // 设置clear_child_tid,在线程结束时将其置0以通知父进程
         if clone_flags.contains(CloneFlags::CLONE_CHILD_CLEARTID) {
-            pcb.thread.write().clear_child_tid = Some(clone_args.child_tid);
+            pcb.thread.write_irqsave().clear_child_tid = Some(clone_args.child_tid);
         }
 
         // 设置child_tid,意味着子线程能够知道自己的id
         if clone_flags.contains(CloneFlags::CLONE_CHILD_SETTID) {
-            pcb.thread.write().set_child_tid = Some(clone_args.child_tid);
+            pcb.thread.write_irqsave().set_child_tid = Some(clone_args.child_tid);
         }
 
         // 将子进程/线程的id存储在用户态传进的地址中
@@ -424,13 +424,14 @@ impl ProcessManager {
 
         // 设置线程组id、组长
         if clone_flags.contains(CloneFlags::CLONE_THREAD) {
-            pcb.thread.write().group_leader = current_pcb.thread.read().group_leader.clone();
+            pcb.thread.write_irqsave().group_leader =
+                current_pcb.thread.read_irqsave().group_leader.clone();
             unsafe {
                 let ptr = pcb.as_ref() as *const ProcessControlBlock as *mut ProcessControlBlock;
                 (*ptr).tgid = current_pcb.tgid;
             }
         } else {
-            pcb.thread.write().group_leader = Arc::downgrade(&pcb);
+            pcb.thread.write_irqsave().group_leader = Arc::downgrade(&pcb);
             unsafe {
                 let ptr = pcb.as_ref() as *const ProcessControlBlock as *mut ProcessControlBlock;
                 (*ptr).tgid = pcb.tgid;
@@ -439,12 +440,13 @@ impl ProcessManager {
 
         // CLONE_PARENT re-uses the old parent
         if clone_flags.contains(CloneFlags::CLONE_PARENT | CloneFlags::CLONE_THREAD) {
-            *pcb.real_parent_pcb.write() = current_pcb.real_parent_pcb.read().clone();
+            *pcb.real_parent_pcb.write_irqsave() =
+                current_pcb.real_parent_pcb.read_irqsave().clone();
 
             if clone_flags.contains(CloneFlags::CLONE_THREAD) {
                 pcb.exit_signal.store(Signal::INVALID, Ordering::SeqCst);
             } else {
-                let leader = current_pcb.thread.read().group_leader();
+                let leader = current_pcb.thread.read_irqsave().group_leader();
                 if unlikely(leader.is_none()) {
                     panic!(
                         "fork: Failed to get leader of current process, current pid: [{:?}]",
@@ -459,7 +461,7 @@ impl ProcessManager {
             }
         } else {
             // 新创建的进程,设置其父进程为当前进程
-            *pcb.real_parent_pcb.write() = Arc::downgrade(&current_pcb);
+            *pcb.real_parent_pcb.write_irqsave() = Arc::downgrade(&current_pcb);
             pcb.exit_signal
                 .store(clone_args.exit_signal, Ordering::SeqCst);
         }

+ 17 - 15
kernel/src/process/mod.rs

@@ -311,7 +311,7 @@ impl ProcessManager {
                     .adopt_childen()
                     .unwrap_or_else(|e| panic!("adopte_childen failed: error: {e:?}"))
             };
-            let r = current.parent_pcb.read().upgrade();
+            let r = current.parent_pcb.read_irqsave().upgrade();
             if r.is_none() {
                 return;
             }
@@ -344,7 +344,7 @@ impl ProcessManager {
         pcb.wait_queue.wakeup(Some(ProcessState::Blocked(true)));
 
         // 进行进程退出后的工作
-        let thread = pcb.thread.write();
+        let thread = pcb.thread.write_irqsave();
         if let Some(addr) = thread.set_child_tid {
             unsafe { clear_user(addr, core::mem::size_of::<i32>()).expect("clear tid failed") };
         }
@@ -668,7 +668,7 @@ impl ProcessControlBlock {
 
         // 将当前pcb加入父进程的子进程哈希表中
         if pcb.pid() > Pid(1) {
-            if let Some(ppcb_arc) = pcb.parent_pcb.read().upgrade() {
+            if let Some(ppcb_arc) = pcb.parent_pcb.read_irqsave().upgrade() {
                 let mut children = ppcb_arc.children.write_irqsave();
                 children.push(pcb.pid());
             } else {
@@ -718,7 +718,7 @@ impl ProcessControlBlock {
     /// 否则会导致死锁
     #[inline(always)]
     pub fn basic(&self) -> RwLockReadGuard<ProcessBasicInfo> {
-        return self.basic.read();
+        return self.basic.read_irqsave();
     }
 
     #[inline(always)]
@@ -841,17 +841,13 @@ impl ProcessControlBlock {
         return name;
     }
 
-    pub fn sig_info(&self) -> RwLockReadGuard<ProcessSignalInfo> {
-        self.sig_info.read()
-    }
-
     pub fn sig_info_irqsave(&self) -> RwLockReadGuard<ProcessSignalInfo> {
         self.sig_info.read_irqsave()
     }
 
-    pub fn try_siginfo(&self, times: u8) -> Option<RwLockReadGuard<ProcessSignalInfo>> {
+    pub fn try_siginfo_irqsave(&self, times: u8) -> Option<RwLockReadGuard<ProcessSignalInfo>> {
         for _ in 0..times {
-            if let Some(r) = self.sig_info.try_read() {
+            if let Some(r) = self.sig_info.try_read_irqsave() {
                 return Some(r);
             }
         }
@@ -865,7 +861,7 @@ impl ProcessControlBlock {
 
     pub fn try_siginfo_mut(&self, times: u8) -> Option<RwLockWriteGuard<ProcessSignalInfo>> {
         for _ in 0..times {
-            if let Some(r) = self.sig_info.try_write() {
+            if let Some(r) = self.sig_info.try_write_irqsave() {
                 return Some(r);
             }
         }
@@ -874,10 +870,10 @@ impl ProcessControlBlock {
     }
 
     pub fn sig_struct(&self) -> SpinLockGuard<SignalStruct> {
-        self.sig_struct.lock()
+        self.sig_struct.lock_irqsave()
     }
 
-    pub fn try_sig_struct_irq(&self, times: u8) -> Option<SpinLockGuard<SignalStruct>> {
+    pub fn try_sig_struct_irqsave(&self, times: u8) -> Option<SpinLockGuard<SignalStruct>> {
         for _ in 0..times {
             if let Ok(r) = self.sig_struct.try_lock_irqsave() {
                 return Some(r);
@@ -894,13 +890,19 @@ impl ProcessControlBlock {
 
 impl Drop for ProcessControlBlock {
     fn drop(&mut self) {
+        let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
+        // kdebug!("drop: {:?}", self.pid);
         // 在ProcFS中,解除进程的注册
         procfs_unregister_pid(self.pid())
             .unwrap_or_else(|e| panic!("procfs_unregister_pid failed: error: {e:?}"));
 
-        if let Some(ppcb) = self.parent_pcb.read().upgrade() {
-            ppcb.children.write().retain(|pid| *pid != self.pid());
+        if let Some(ppcb) = self.parent_pcb.read_irqsave().upgrade() {
+            ppcb.children
+                .write_irqsave()
+                .retain(|pid| *pid != self.pid());
         }
+
+        drop(irq_guard);
     }
 }
 

+ 4 - 4
kernel/src/process/syscall.rs

@@ -202,11 +202,11 @@ impl Syscall {
         });
 
         if flags.contains(CloneFlags::CLONE_VFORK) {
-            pcb.thread.write().vfork_done = Some(vfork.clone());
+            pcb.thread.write_irqsave().vfork_done = Some(vfork.clone());
         }
 
-        if pcb.thread.read().set_child_tid.is_some() {
-            let addr = pcb.thread.read().set_child_tid.unwrap();
+        if pcb.thread.read_irqsave().set_child_tid.is_some() {
+            let addr = pcb.thread.read_irqsave().set_child_tid.unwrap();
             let mut writer =
                 UserBufferWriter::new(addr.as_ptr::<i32>(), core::mem::size_of::<i32>(), true)?;
             writer.copy_one_to_user(&(pcb.pid().data() as i32), 0)?;
@@ -234,7 +234,7 @@ impl Syscall {
             .map_err(|_| SystemError::EFAULT)?;
 
         let pcb = ProcessManager::current_pcb();
-        pcb.thread.write().clear_child_tid = Some(VirtAddr::new(ptr));
+        pcb.thread.write_irqsave().clear_child_tid = Some(VirtAddr::new(ptr));
         Ok(pcb.pid.0)
     }