Browse Source

[x86] update config and page

jasonhu 3 years ago
parent
commit
6945b3e196
6 changed files with 306 additions and 329 deletions
  1. 65 15
      bsp/x86/.config
  2. 1 0
      bsp/x86/Kconfig
  3. 23 5
      bsp/x86/rtconfig.h
  4. 2 5
      libcpu/x86/i386/mmu.c
  5. 195 288
      libcpu/x86/i386/page.c
  6. 20 16
      libcpu/x86/i386/page.h

+ 65 - 15
bsp/x86/.config

@@ -71,6 +71,7 @@ CONFIG_RT_VER_NUM=0x50000
 CONFIG_RT_USING_CACHE=y
 # CONFIG_RT_USING_CPU_FFS is not set
 # CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
+CONFIG_ARCH_MM_MMU=y
 CONFIG_RT_USING_USERSPACE=y
 CONFIG_KERNEL_VADDR_START=0x00000000
 CONFIG_PV_OFFSET=0
@@ -93,6 +94,7 @@ CONFIG_RT_MAIN_THREAD_PRIORITY=10
 #
 CONFIG_RT_USING_FINSH=y
 CONFIG_RT_USING_MSH=y
+CONFIG_FINSH_USING_MSH=y
 CONFIG_FINSH_THREAD_NAME="tshell"
 CONFIG_FINSH_USING_HISTORY=y
 CONFIG_FINSH_HISTORY_LINES=5
@@ -143,6 +145,7 @@ CONFIG_RT_USING_DFS_ROMFS=y
 # Device Drivers
 #
 CONFIG_RT_USING_DEVICE_IPC=y
+CONFIG_RT_UNAMED_PIPE_NUMBER=64
 CONFIG_RT_PIPE_BUFSZ=512
 CONFIG_RT_USING_SYSTEM_WORKQUEUE=y
 CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=4096
@@ -150,6 +153,8 @@ CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23
 CONFIG_RT_USING_SERIAL=y
 # CONFIG_RT_SERIAL_USING_DMA is not set
 CONFIG_RT_SERIAL_RB_BUFSZ=64
+CONFIG_RT_USING_TTY=y
+# CONFIG_RT_TTY_DEBUG is not set
 # CONFIG_RT_USING_CAN is not set
 # CONFIG_RT_USING_HWTIMER is not set
 # CONFIG_RT_USING_CPUTIME is not set
@@ -189,10 +194,10 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64
 CONFIG_RT_USING_LIBC=y
 # CONFIG_RT_USING_NEWLIB is not set
 CONFIG_RT_USING_MUSL=y
+# CONFIG_RT_USING_MLIB is not set
 # CONFIG_RT_USING_PTHREADS is not set
 CONFIG_RT_USING_POSIX=y
 # CONFIG_RT_USING_POSIX_MMAP is not set
-# CONFIG_RT_USING_POSIX_TERMIOS is not set
 # CONFIG_RT_USING_POSIX_GETLINE is not set
 # CONFIG_RT_USING_POSIX_AIO is not set
 CONFIG_RT_USING_POSIX_CLOCKTIME=y
@@ -259,15 +264,15 @@ CONFIG_RT_LWIP_RAW_PCB_NUM=4
 CONFIG_RT_LWIP_UDP_PCB_NUM=4
 CONFIG_RT_LWIP_TCP_PCB_NUM=4
 CONFIG_RT_LWIP_TCP_SEG_NUM=40
-CONFIG_RT_LWIP_TCP_SND_BUF=8196
-CONFIG_RT_LWIP_TCP_WND=8196
+CONFIG_RT_LWIP_TCP_SND_BUF=8192
+CONFIG_RT_LWIP_TCP_WND=8192
 CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10
 CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=8
-CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=2048
+CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=8192
 # CONFIG_LWIP_NO_RX_THREAD is not set
 # CONFIG_LWIP_NO_TX_THREAD is not set
 CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=12
-CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=2048
+CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=8192
 CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=8
 # CONFIG_RT_LWIP_REASSEMBLY_FRAG is not set
 CONFIG_LWIP_NETIF_STATUS_CALLBACK=1
@@ -306,9 +311,9 @@ CONFIG_RT_USING_LWP=y
 CONFIG_RT_LWP_MAX_NR=30
 CONFIG_LWP_TASK_STACK_SIZE=16384
 CONFIG_RT_CH_MSG_MAX_NR=1024
-CONFIG_RT_LWP_SHM_MAX_NR=64
 CONFIG_LWP_CONSOLE_INPUT_BUFFER_SIZE=1024
 CONFIG_LWP_TID_MAX_NR=64
+CONFIG_RT_LWP_SHM_MAX_NR=64
 # CONFIG_LWP_UNIX98_PTY is not set
 
 #
@@ -400,12 +405,17 @@ CONFIG_LWP_TID_MAX_NR=64
 # CONFIG_PKG_USING_AGILE_FTP is not set
 # CONFIG_PKG_USING_EMBEDDEDPROTO is not set
 # CONFIG_PKG_USING_RT_LINK_HW is not set
+# CONFIG_PKG_USING_LORA_PKT_FWD is not set
+# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set
+# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set
+# CONFIG_PKG_USING_HM is not set
+# CONFIG_PKG_USING_SMALL_MODBUS is not set
 
 #
 # security packages
 #
 # CONFIG_PKG_USING_MBEDTLS is not set
-# CONFIG_PKG_USING_libsodium is not set
+# CONFIG_PKG_USING_LIBSODIUM is not set
 # CONFIG_PKG_USING_TINYCRYPT is not set
 # CONFIG_PKG_USING_TFM is not set
 # CONFIG_PKG_USING_YD_CRYPTO is not set
@@ -421,6 +431,19 @@ CONFIG_LWP_TID_MAX_NR=64
 #
 # multimedia packages
 #
+
+#
+# LVGL: powerful and easy-to-use embedded GUI library
+#
+# CONFIG_PKG_USING_LVGL is not set
+# CONFIG_PKG_USING_LITTLEVGL2RTT is not set
+# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set
+
+#
+# u8g2: a monochrome graphic library
+#
+# CONFIG_PKG_USING_U8G2_OFFICIAL is not set
+# CONFIG_PKG_USING_U8G2 is not set
 # CONFIG_PKG_USING_OPENMV is not set
 # CONFIG_PKG_USING_MUPDF is not set
 # CONFIG_PKG_USING_STEMWIN is not set
@@ -433,6 +456,16 @@ CONFIG_LWP_TID_MAX_NR=64
 # CONFIG_PKG_USING_NUEMWIN is not set
 # CONFIG_PKG_USING_MP3PLAYER is not set
 # CONFIG_PKG_USING_TINYJPEG is not set
+# CONFIG_PKG_USING_UGUI is not set
+
+#
+# PainterEngine: A cross-platform graphics application framework written in C language
+#
+# CONFIG_PKG_USING_PAINTERENGINE is not set
+# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set
+# CONFIG_PKG_USING_MCURSES is not set
+# CONFIG_PKG_USING_TERMBOX is not set
+# CONFIG_PKG_USING_VT100 is not set
 
 #
 # tools packages
@@ -475,19 +508,32 @@ CONFIG_LWP_TID_MAX_NR=64
 # CONFIG_PKG_USING_MEM_SANDBOX is not set
 # CONFIG_PKG_USING_SOLAR_TERMS is not set
 # CONFIG_PKG_USING_GAN_ZHI is not set
+# CONFIG_PKG_USING_FDT is not set
 
 #
 # system packages
 #
 
 #
-# acceleration: Assembly language or algorithmic acceleration packages
+# enhanced kernel services
 #
 # CONFIG_PKG_USING_RT_MEMCPY_CM is not set
+# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set
+# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set
+
+#
+# acceleration: Assembly language or algorithmic acceleration packages
+#
 # CONFIG_PKG_USING_QFPLIB_M0_FULL is not set
 # CONFIG_PKG_USING_QFPLIB_M0_TINY is not set
 # CONFIG_PKG_USING_QFPLIB_M3 is not set
 
+#
+# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard
+#
+# CONFIG_PKG_USING_CMSIS_5 is not set
+# CONFIG_PKG_USING_CMSIS_RTOS2 is not set
+
 #
 # Micrium: Micrium software products porting for RT-Thread
 #
@@ -497,6 +543,7 @@ CONFIG_LWP_TID_MAX_NR=64
 # CONFIG_PKG_USING_UC_CLK is not set
 # CONFIG_PKG_USING_UC_COMMON is not set
 # CONFIG_PKG_USING_UC_MODBUS is not set
+# CONFIG_RT_USING_ARDUINO is not set
 # CONFIG_PKG_USING_GUIENGINE is not set
 # CONFIG_PKG_USING_CAIRO is not set
 # CONFIG_PKG_USING_PIXMAN is not set
@@ -505,8 +552,6 @@ CONFIG_LWP_TID_MAX_NR=64
 # CONFIG_PKG_USING_FLASHDB is not set
 # CONFIG_PKG_USING_SQLITE is not set
 # CONFIG_PKG_USING_RTI is not set
-# CONFIG_PKG_USING_LITTLEVGL2RTT is not set
-# CONFIG_PKG_USING_CMSIS is not set
 # CONFIG_PKG_USING_DFS_YAFFS is not set
 # CONFIG_PKG_USING_LITTLEFS is not set
 # CONFIG_PKG_USING_DFS_JFFS2 is not set
@@ -523,11 +568,14 @@ CONFIG_LWP_TID_MAX_NR=64
 # CONFIG_PKG_USING_QBOOT is not set
 # CONFIG_PKG_USING_PPOOL is not set
 # CONFIG_PKG_USING_OPENAMP is not set
-# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set
 # CONFIG_PKG_USING_LPM is not set
 # CONFIG_PKG_USING_TLSF is not set
 # CONFIG_PKG_USING_EVENT_RECORDER is not set
 # CONFIG_PKG_USING_ARM_2D is not set
+# CONFIG_PKG_USING_WCWIDTH is not set
+# CONFIG_PKG_USING_MCUBOOT is not set
+# CONFIG_PKG_USING_TINYUSB is not set
+# CONFIG_PKG_USING_USB_STACK is not set
 
 #
 # peripheral libraries and drivers
@@ -539,7 +587,6 @@ CONFIG_LWP_TID_MAX_NR=64
 # CONFIG_PKG_USING_AS7341 is not set
 # CONFIG_PKG_USING_STM32_SDIO is not set
 # CONFIG_PKG_USING_ICM20608 is not set
-# CONFIG_PKG_USING_U8G2 is not set
 # CONFIG_PKG_USING_BUTTON is not set
 # CONFIG_PKG_USING_PCF8574 is not set
 # CONFIG_PKG_USING_SX12XX is not set
@@ -600,6 +647,11 @@ CONFIG_LWP_TID_MAX_NR=64
 # CONFIG_PKG_USING_MICRO_ROS is not set
 # CONFIG_PKG_USING_MCP23008 is not set
 # CONFIG_PKG_USING_BLUETRUM_SDK is not set
+# CONFIG_PKG_USING_MISAKA_AT24CXX is not set
+# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set
+# CONFIG_PKG_USING_BL_MCU_SDK is not set
+# CONFIG_PKG_USING_SOFT_SERIAL is not set
+# CONFIG_PKG_USING_MB85RS16 is not set
 
 #
 # AI packages
@@ -638,6 +690,7 @@ CONFIG_LWP_TID_MAX_NR=64
 # CONFIG_PKG_USING_SNAKE is not set
 # CONFIG_PKG_USING_TETRIS is not set
 # CONFIG_PKG_USING_DONUT is not set
+# CONFIG_PKG_USING_COWSAY is not set
 # CONFIG_PKG_USING_LIBCSV is not set
 # CONFIG_PKG_USING_OPTPARSE is not set
 # CONFIG_PKG_USING_FASTLZ is not set
@@ -659,13 +712,10 @@ CONFIG_LWP_TID_MAX_NR=64
 # CONFIG_PKG_USING_VI is not set
 # CONFIG_PKG_USING_KI is not set
 # CONFIG_PKG_USING_ARMv7M_DWT is not set
-# CONFIG_PKG_USING_VT100 is not set
 # CONFIG_PKG_USING_UKAL is not set
 # CONFIG_PKG_USING_CRCLIB is not set
 # CONFIG_PKG_USING_LWGPS is not set
 # CONFIG_PKG_USING_STATE_MACHINE is not set
-# CONFIG_PKG_USING_MCURSES is not set
-# CONFIG_PKG_USING_COWSAY is not set
 CONFIG_BOARD_x86=y
 CONFIG_BSP_USING_DIRECT_UART=y
 CONFIG_BSP_DRV_UART=y

+ 1 - 0
bsp/x86/Kconfig

@@ -25,6 +25,7 @@ config BOARD_x86
     select RT_USING_USER_MAIN
     select RT_USING_CACHE
     select BSP_USING_UART
+    select ARCH_MM_MMU
     default y
 
 config RT_USING_USERSPACE

+ 23 - 5
bsp/x86/rtconfig.h

@@ -45,6 +45,7 @@
 #define RT_CONSOLE_DEVICE_NAME "uart0"
 #define RT_VER_NUM 0x50000
 #define RT_USING_CACHE
+#define ARCH_MM_MMU
 #define RT_USING_USERSPACE
 #define KERNEL_VADDR_START 0x00000000
 #define PV_OFFSET 0
@@ -63,6 +64,7 @@
 
 #define RT_USING_FINSH
 #define RT_USING_MSH
+#define FINSH_USING_MSH
 #define FINSH_THREAD_NAME "tshell"
 #define FINSH_USING_HISTORY
 #define FINSH_HISTORY_LINES 5
@@ -98,12 +100,14 @@
 /* Device Drivers */
 
 #define RT_USING_DEVICE_IPC
+#define RT_UNAMED_PIPE_NUMBER 64
 #define RT_PIPE_BUFSZ 512
 #define RT_USING_SYSTEM_WORKQUEUE
 #define RT_SYSTEM_WORKQUEUE_STACKSIZE 4096
 #define RT_SYSTEM_WORKQUEUE_PRIORITY 23
 #define RT_USING_SERIAL
 #define RT_SERIAL_RB_BUFSZ 64
+#define RT_USING_TTY
 
 /* Using USB */
 
@@ -165,13 +169,13 @@
 #define RT_LWIP_UDP_PCB_NUM 4
 #define RT_LWIP_TCP_PCB_NUM 4
 #define RT_LWIP_TCP_SEG_NUM 40
-#define RT_LWIP_TCP_SND_BUF 8196
-#define RT_LWIP_TCP_WND 8196
+#define RT_LWIP_TCP_SND_BUF 8192
+#define RT_LWIP_TCP_WND 8192
 #define RT_LWIP_TCPTHREAD_PRIORITY 10
 #define RT_LWIP_TCPTHREAD_MBOX_SIZE 8
-#define RT_LWIP_TCPTHREAD_STACKSIZE 2048
+#define RT_LWIP_TCPTHREAD_STACKSIZE 8192
 #define RT_LWIP_ETHTHREAD_PRIORITY 12
-#define RT_LWIP_ETHTHREAD_STACKSIZE 2048
+#define RT_LWIP_ETHTHREAD_STACKSIZE 8192
 #define RT_LWIP_ETHTHREAD_MBOX_SIZE 8
 #define LWIP_NETIF_STATUS_CALLBACK 1
 #define LWIP_NETIF_LINK_CALLBACK 1
@@ -195,9 +199,9 @@
 #define RT_LWP_MAX_NR 30
 #define LWP_TASK_STACK_SIZE 16384
 #define RT_CH_MSG_MAX_NR 1024
-#define RT_LWP_SHM_MAX_NR 64
 #define LWP_CONSOLE_INPUT_BUFFER_SIZE 1024
 #define LWP_TID_MAX_NR 64
+#define RT_LWP_SHM_MAX_NR 64
 
 /* RT-Thread online packages */
 
@@ -223,15 +227,29 @@
 
 /* multimedia packages */
 
+/* LVGL: powerful and easy-to-use embedded GUI library */
+
+
+/* u8g2: a monochrome graphic library */
+
+
+/* PainterEngine: A cross-platform graphics application framework written in C language */
+
 
 /* tools packages */
 
 
 /* system packages */
 
+/* enhanced kernel services */
+
+
 /* acceleration: Assembly language or algorithmic acceleration packages */
 
 
+/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
+
+
 /* Micrium: Micrium software products porting for RT-Thread */
 
 

+ 2 - 5
libcpu/x86/i386/mmu.c

@@ -509,16 +509,13 @@ static void __rt_hw_mmu_unmap(rt_mmu_info *mmu_info,void *v_addr,rt_size_t npage
         *mmu_l2 = 0;    /* clear page table entry */
         rt_hw_cpu_dcache_clean(mmu_l2, sizeof(*mmu_l2));
         mmu_l2 -= l2_off;   /* get base addr on page aligned */
-        rt_page_ref_dec(mmu_l2, 0); /* page ref dec when unmap */
 
-        if(!rt_page_ref_get(mmu_l2, 0)) /* page table no phy page, empty */
+        if(rt_pages_free(mmu_l2, 0)) /* page table no phy page, empty */
         {
-            rt_page_ref_inc(mmu_l2, 0); /* page ref inc before free, make sure ref > 0 */
-            //release level 2 page
-            rt_pages_free(mmu_l2, 0); //entry page and ref_cnt page
             *mmu_l1 = 0;    /* clear page dir table entry */
             rt_hw_cpu_dcache_clean(mmu_l1, sizeof(*mmu_l1));
         }
+        
         loop_va += PAGE_SIZE;
     }
 }

+ 195 - 288
libcpu/x86/i386/page.c

@@ -1,173 +1,165 @@
 /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
+ * Copyright (c) 2006-2019, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date           Author       Notes
- * 2021-01-29     lizhirui     first version
- * 2021-07-17     JasonHu      used in i386
+ * 2019-11-01     Jesven      The first version
  */
-
 #include <stdint.h>
-#include <rtthread.h>
+
 #include <rthw.h>
-#include <board.h>
+#include <rtthread.h>
 
 #ifdef RT_USING_USERSPACE
 
-#include "page.h"
-#include "mmu.h"
-
-#define PAGE_LIST_SIZE (ADDRESS_WIDTH_BITS - PAGE_OFFSET_BIT)
+#include <page.h>
+#include <mmu.h>
 
-// #define RT_PAGE_DEBUG
+#define ARCH_PAGE_LIST_SIZE     (ARCH_ADDRESS_WIDTH_BITS - ARCH_PAGE_SHIFT)
 
-#ifdef RT_PAGE_DEBUG
-    #define dprintf rt_kprintf
-#else
-    #define dprintf(...)
-#endif
-
-#define RT_PASSERT RT_ASSERT
+#define DBG_TAG "PAGE"
+#define DBG_LVL DBG_WARNING
+#include <rtdbg.h>
 
 struct page
 {
-    struct page *next;
-    struct page *pre;
-    rt_size_t size_bits;
-    int ref_cnt;
+    struct page *next;  /* same level next */
+    struct page *pre;   /* same level pre  */
+    uint32_t size_bits; /* if is ARCH_ADDRESS_WIDTH_BITS, means not free */
+    int ref_cnt;        /* page group ref count */
 };
 
-static struct page *page_start;
-static void *page_addr;
-static rt_size_t page_nr;
+static struct page* page_start;
+static void*  page_addr;
+static size_t page_nr;
 
-#define PAGE_VALID(pageobj) RT_PASSERT(!((((rt_size_t)pageobj) - ((rt_size_t)page_start)) % sizeof(struct page)))
+static struct page *page_list[ARCH_PAGE_LIST_SIZE];
 
-static struct page *page_list[ADDRESS_WIDTH_BITS] = {0};
-
-//get the correct page_list index according the actual size
-rt_size_t rt_page_bits(rt_size_t size)
+RT_WEAK int rt_clz(size_t n)
 {
-    rt_base_t bit;
+    int bits = sizeof(size_t) * 8;
+
+    n |= (n >> 1);
+    n |= (n >> 2);
+    n |= (n >> 4);
+    n |= (n >> 8);
+    n |= (n >> 16);
+
+#ifdef ARCH_CPU_64BIT
+    n |= (n >> 32);
+
+    n = (n & 0x5555555555555555UL) + ((n >> 1) & 0x5555555555555555UL);
+    n = (n & 0x3333333333333333UL) + ((n >> 2) & 0x3333333333333333UL);
+    n = (n & 0x0707070707070707UL) + ((n >> 4) & 0x0707070707070707UL);
+    n = (n & 0x000f000f000f000fUL) + ((n >> 8) & 0x000f000f000f000fUL);
+    n = (n & 0x0000001f0000001fUL) + ((n >> 16) & 0x0000001f0000001fUL);
+    n = (n & 0x000000000000003fUL) + ((n >> 32) & 0x000000000000003fUL);
+#else
+    n = (n & 0x55555555UL) + ((n >> 1) & 0x55555555UL);
+    n = (n & 0x33333333UL) + ((n >> 2) & 0x33333333UL);
+    n = (n & 0x07070707UL) + ((n >> 4) & 0x07070707UL);
+    n = (n & 0x000f000fUL) + ((n >> 8) & 0x000f000fUL);
+    n = (n & 0x0000001fUL) + ((n >> 16) & 0x0000001fUL);
+#endif
+    return bits - n;
+}
 
-    //get highest 1 bit index
-    bit = __builtin_clzl(size);
-    bit = sizeof(rt_size_t) * 8 - bit - 1;
+RT_WEAK int rt_ctz(size_t n)
+{
+    int ret = sizeof(size_t) * 8;
 
-    //if bits remained has 1,the large page is needed
-    if((size ^ (1UL << bit)) != 0)
+    if (n)
     {
-        bit++;
+        ret -= (rt_clz(n ^ (n - 1)) + 1);
     }
+    return ret;
+}
 
-    bit -= PAGE_OFFSET_BIT;
+size_t rt_page_bits(size_t size)
+{
+    int bit = sizeof(size_t) * 8 - rt_clz(size) - 1;
 
-    if(bit < 0)
+    if ((size ^ (1UL << bit)) != 0)
+    {
+        bit++;
+    }
+    bit -= ARCH_PAGE_SHIFT;
+    if (bit < 0)
     {
         bit = 0;
     }
-
-    return (rt_size_t)bit;
+    return bit;
 }
 
-//convert physical address to page object
-static struct page *addr_to_page(void *addr)
+static struct page * addr_to_page(void *addr)
 {
-    rt_size_t off;
+    size_t off;
 
-    if(addr < page_addr)
+    if (addr < page_addr)
     {
         return 0;
     }
-    RT_PASSERT(__CHECKALIGN(addr,PAGE_OFFSET_BIT));
-    off = ((rt_size_t)addr) - ((rt_size_t)page_addr);
-    off >>= PAGE_OFFSET_BIT;
-
-    if(off >= page_nr)
+    off = (size_t)((char*)addr - (char*)page_addr);
+    off >>= ARCH_PAGE_SHIFT;
+    if (off >= page_nr)
     {
         return 0;
     }
-
     return &page_start[off];
 }
 
-//convert page object to physical address
-static void *page_to_addr(struct page *p)
+static void* page_to_addr(struct page* p)
 {
-    if(!p)
+    if (!p)
     {
         return 0;
     }
-
-    PAGE_VALID(p);
-    return (void *)(((rt_size_t)page_addr) + ((p - page_start) << PAGE_OFFSET_BIT));
+    return (void*)((char*)page_addr + ((p - page_start) << ARCH_PAGE_SHIFT));
 }
 
-//get the buddy of page specified by p(split a page to two page according to size_bits)
-static inline struct page *buddy_get(struct page *p,rt_size_t size_bits)
+static inline struct page *buddy_get(struct page *p, uint32_t size_bits)
 {
-    rt_size_t addr;
+    size_t addr;
 
-    PAGE_VALID(p);
-    addr = (rt_size_t)page_to_addr(p);
-    RT_PASSERT(__CHECKALIGN(addr,size_bits + PAGE_OFFSET_BIT));
-    addr ^= (1UL << (size_bits + PAGE_OFFSET_BIT));
-    return addr_to_page((void *)addr);
+    addr = (size_t)page_to_addr(p);
+    addr ^= (1UL << (size_bits + ARCH_PAGE_SHIFT));
+    return addr_to_page((void*)addr);
 }
 
-//remove the page from the linked list
-static void page_remove(struct page *p,rt_size_t size_bits)
+static void page_remove(struct page *p, uint32_t size_bits)
 {
-    PAGE_VALID(p);
-
-    if(p -> pre)
+    if (p->pre)
     {
-        p -> pre -> next = p -> next;
+        p->pre->next = p->next;
     }
     else
     {
-        page_list[size_bits] = p -> next;
+        page_list[size_bits] = p->next;
     }
 
-    if(p -> next)
+    if (p->next)
     {
-        p -> next -> pre = p -> pre;
+        p->next->pre = p->pre;
     }
 
-    p -> size_bits = ADDRESS_WIDTH_BITS;
+    p->size_bits = ARCH_ADDRESS_WIDTH_BITS;
 }
 
-static void _pages_ref_inc(struct page *p, uint32_t size_bits)
+static void page_insert(struct page *p, uint32_t size_bits)
 {
-    struct page *page_head;
-    int idx;
-
-    /* find page group head */
-    idx = p - page_start;
-    if (idx < 0 || idx >= page_nr)
+    p->next = page_list[size_bits];
+    if (p->next)
     {
-        return;
+        p->next->pre = p;
     }
-    idx = idx & ~((1UL << size_bits) - 1);
-
-    page_head = page_start + idx;
-    page_head->ref_cnt++;
-}
-
-void rt_page_ref_inc(void *addr, uint32_t size_bits)
-{
-    struct page *p;
-    rt_base_t level;
-
-    p = addr_to_page(addr);
-    level = rt_hw_interrupt_disable();
-    _pages_ref_inc(p, size_bits);
-    rt_hw_interrupt_enable(level);
+    p->pre = 0;
+    page_list[size_bits] = p;
+    p->size_bits = size_bits;
 }
 
-static void _pages_ref_dec(struct page *p, uint32_t size_bits)
+static void _pages_ref_inc(struct page *p, uint32_t size_bits)
 {
     struct page *page_head;
     int idx;
@@ -181,157 +173,94 @@ static void _pages_ref_dec(struct page *p, uint32_t size_bits)
     idx = idx & ~((1UL << size_bits) - 1);
 
     page_head = page_start + idx;
-    page_head->ref_cnt--;
+    page_head->ref_cnt++;
 }
 
-void rt_page_ref_dec(void *addr, uint32_t size_bits)
+static int _pages_free(struct page *p, uint32_t size_bits)
 {
-    struct page *p;
-    rt_base_t level;
-
-    p = addr_to_page(addr);
-    level = rt_hw_interrupt_disable();
-    _pages_ref_dec(p, size_bits);
-    rt_hw_interrupt_enable(level);
-}
+    uint32_t level = size_bits;
+    uint32_t high = ARCH_PAGE_LIST_SIZE - size_bits - 1;
+    struct page *buddy;
 
-static int _pages_ref_get(struct page *p, uint32_t size_bits)
-{
-    struct page *page_head;
-    int idx;
+    RT_ASSERT(p->ref_cnt > 0);
+    RT_ASSERT(p->size_bits == ARCH_ADDRESS_WIDTH_BITS);
 
-    /* find page group head */
-    idx = p - page_start;
-    if (idx < 0 || idx >= page_nr)
+    p->ref_cnt--;
+    if (p->ref_cnt != 0)
     {
-        return - 1;
+        return 0;
     }
-    idx = idx & ~((1UL << size_bits) - 1);
-
-    page_head = page_start + idx;
-    return page_head->ref_cnt;
-}
-
-int rt_page_ref_get(void *addr, uint32_t size_bits)
-{
-    struct page *p;
-    rt_base_t level;
-    int ref_cnt;
-    p = addr_to_page(addr);
-    level = rt_hw_interrupt_disable();
-    ref_cnt = _pages_ref_get(p, size_bits);
-    rt_hw_interrupt_enable(level);
-    return ref_cnt;
-}
-
-//add new page to the first item of the linked list
-static void page_insert(struct page *p,rt_size_t size_bits)
-{
-    PAGE_VALID(p);
 
-    p -> next = page_list[size_bits];
-
-    if(p -> next)
+    while (level < high)
     {
-        p -> next -> pre = p;
+        buddy = buddy_get(p, level);
+        if (buddy && buddy->size_bits == level)
+        {
+            page_remove(buddy, level);
+            p = (p < buddy) ? p : buddy;
+            level++;
+        }
+        else
+        {
+            break;
+        }
     }
-
-    p -> pre = 0;
-    page_list[size_bits] = p;
-    p -> size_bits = size_bits;
+    page_insert(p, level);
+    return 1;
 }
 
-static struct page *_pages_alloc(rt_size_t size_bits)
+static struct page *_pages_alloc(uint32_t size_bits)
 {
     struct page *p;
 
-    if(page_list[size_bits])
+    if (page_list[size_bits])
     {
-        //if appropriate page exists,just get new page from the linked list specified by size_bits
         p = page_list[size_bits];
-        page_remove(p,size_bits);
+        page_remove(p, size_bits);
     }
     else
     {
-        //otherwise get new page from large linked list
-        rt_size_t level;
-        rt_size_t high = PAGE_LIST_SIZE;
+        uint32_t level;
+        uint32_t high = ARCH_PAGE_LIST_SIZE - size_bits - 1;
 
-        for(level = size_bits + 1;level <= high;level++)
+        for (level = size_bits + 1; level <= high; level++)
         {
-            if(page_list[level])
+            if (page_list[level])
             {
                 break;
             }
         }
-
-        RT_ASSERT(level <= (high + 2));
-
-        if(level == high + 2)
+        if (level == high + 1)
         {
-            return 0;//couldn't find a appropriate page
+            return 0;
         }
 
         p = page_list[level];
-        page_remove(p,level);
-
-        //push down this page,and split it to the size specified by size_bits
-        while(level > size_bits)
+        page_remove(p, level);
+        while (level > size_bits)
         {
-            page_insert(p,level - 1);
-            p = buddy_get(p,level - 1);
+            page_insert(p, level - 1);
+            p = buddy_get(p, level - 1);
             level--;
         }
     }
-    p->size_bits = ADDRESS_WIDTH_BITS;
+    p->size_bits = ARCH_ADDRESS_WIDTH_BITS;
     p->ref_cnt = 1;
-    dprintf("page_alloc:paddr = 0x%p,size_bits = 0x%p\n",page_to_addr(p),size_bits);
     return p;
 }
 
-static int _pages_free(struct page *p,rt_size_t size_bits)
+void rt_page_ref_inc(void *addr, uint32_t size_bits)
 {
-    rt_size_t level = size_bits;
-    rt_size_t high = ARCH_PAGE_LIST_SIZE - size_bits - 1;
-    struct page *buddy;
-
-    if (p->ref_cnt <= 0)
-    {
-        rt_kprintf("page ref %d\n", p->ref_cnt);
-    }
-    RT_ASSERT(p->ref_cnt > 0);
-    RT_ASSERT(p->size_bits == ADDRESS_WIDTH_BITS);
-
-    p->ref_cnt--;
-    if (p->ref_cnt != 0)
-    {
-        return 0;
-    }
-
-    dprintf("page_free:paddr = 0x%p,size_bits = 0x%p\n",page_to_addr(p),size_bits);
-    PAGE_VALID(p);
-
-    while(level < high)
-    {
-        buddy = buddy_get(p,level);
-
-        if(buddy && (buddy -> size_bits == level))
-        {
-            page_remove(buddy,level);
-            p = (p < buddy) ? p : buddy;
-            level++;
-        }
-        else
-        {
-            break;
-        }
-    }
+    struct page *p;
+    rt_base_t level;
 
-    page_insert(p,level);
-    return 1;
+    p = addr_to_page(addr);
+    level = rt_hw_interrupt_disable();
+    _pages_ref_inc(p, size_bits);
+    rt_hw_interrupt_enable(level);
 }
 
-void *rt_pages_alloc(rt_size_t size_bits)
+void *rt_pages_alloc(uint32_t size_bits)
 {
     struct page *p;
     rt_base_t level;
@@ -342,72 +271,67 @@ void *rt_pages_alloc(rt_size_t size_bits)
     return page_to_addr(p);
 }
 
-int rt_pages_free(void *addr,rt_size_t size_bits)
+int rt_pages_free(void *addr, uint32_t size_bits)
 {
     struct page *p;
-    RT_PASSERT(__CHECKALIGN(addr,size_bits));
-    p = addr_to_page(addr);
     int real_free = 0;
 
-    if(p)
+    p = addr_to_page(addr);
+    if (p)
     {
         rt_base_t level;
         level = rt_hw_interrupt_disable();
-        real_free = _pages_free(p,size_bits);
+        real_free = _pages_free(p, size_bits);
         rt_hw_interrupt_enable(level);
     }
     return real_free;
 }
 
-void rt_pageinfo_dump()
+void list_page(void)
 {
-    rt_size_t i;
-    rt_size_t total = 0;
+    int i;
+    size_t total = 0;
 
     rt_base_t level;
     level = rt_hw_interrupt_disable();
 
-    for(i = 0;i < PAGE_LIST_SIZE;i++)
+    for (i = 0; i < ARCH_PAGE_LIST_SIZE; i++)
     {
         struct page *p = page_list[i];
 
-        rt_kprintf("level %d ",i);
+        rt_kprintf("level %d ", i);
 
-        while(p)
+        while (p)
         {
             total += (1UL << i);
-            rt_kprintf("[0x%08x]",page_to_addr(p));
-            p = p -> next;
+            rt_kprintf("[0x%08x]", page_to_addr(p));
+            p = p->next;
         }
-
         rt_kprintf("\n");
     }
-
     rt_hw_interrupt_enable(level);
-    rt_kprintf("free pages is %08x\n",total);
+    rt_kprintf("free pages is %08x\n", total);
     rt_kprintf("-------------------------------\n");
 }
-MSH_CMD_EXPORT(rt_pageinfo_dump, show page info);
+MSH_CMD_EXPORT(list_page, show page info);
 
 void rt_page_get_info(size_t *total_nr, size_t *free_nr)
 {
-    rt_size_t i;
-    rt_size_t total_free = 0;
+    int i;
+    size_t total_free = 0;
     rt_base_t level;
 
     level = rt_hw_interrupt_disable();
-
-    for (i = 0;i < PAGE_LIST_SIZE;i++)
+    for (i = 0; i < ARCH_PAGE_LIST_SIZE; i++)
     {
         struct page *p = page_list[i];
 
         while (p)
         {
             total_free += (1UL << i);
-            p = p -> next;
+            p = p->next;
         }
     }
-
     rt_hw_interrupt_enable(level);
     *total_nr = page_nr;
     *free_nr = total_free;
@@ -415,75 +339,58 @@ void rt_page_get_info(size_t *total_nr, size_t *free_nr)
 
 void rt_page_init(rt_region_t reg)
 {
-    rt_size_t align_bits;
-    rt_size_t size_bits;
-    rt_size_t i;
-
-    dprintf("split 0x%08x 0x%08x\n",reg.start,reg.end);
-
-    reg.start = __ALIGNUP(reg.start,PAGE_OFFSET_BIT);
-    reg.end = __ALIGNDOWN(reg.end,PAGE_OFFSET_BIT);
-
-    rt_size_t nr = PAGE_SIZE / sizeof(struct page);
-    rt_size_t total = (reg.end - reg.start) >> PAGE_OFFSET_BIT;
-
-    /*
-        equation:cell((total - mnr) / nr) = mnr
-        let total - mnr = knr + p(k is integer,0 <= p < nr)
-        then,k + cell(p / nr) = mnr
-        when p = 0,k = (total - mnr) / nr,mnr = total / (nr + 1)
-        when p > 0,k = (total - mnr - p) / nr,cell(p / nr) = 1,mnr = (total - p + nr) / (nr + 1)
-        to be simple,let all free memory remained can be indicated in page struct memory,so let use the upbound of mnr
-        let p = 0,mnr = max(total / (nr + 1),(total - p + nr) / (nr + 1)) = (total + nr) / (nr + 1)
-    */
-    rt_size_t mnr = (total + nr) / (nr + 1);
-
-    dprintf("nr = 0x%08x\n",nr);
-    dprintf("total = 0x%08x\n",total);
-    dprintf("mnr = 0x%08x\n",mnr);
-
-    page_start = (struct page *)reg.start;
-    reg.start += (mnr << PAGE_OFFSET_BIT);//now reg.start is the start point of free memory remained
-    page_addr = (void *)reg.start;
-    page_nr = (reg.end - reg.start) >> PAGE_OFFSET_BIT;
-
-    dprintf("align 0x%08x 0x%08x\n",reg.start,reg.end);
-
-    //init page struct
-    for(i = 0;i < page_nr;i++)
+    int i;
+
+    LOG_D("split 0x%08x 0x%08x\n", reg.start, reg.end);
+
+    reg.start += ARCH_PAGE_MASK;
+    reg.start &= ~ARCH_PAGE_MASK;
+
+    reg.end &= ~ARCH_PAGE_MASK;
+
     {
-        page_start[i].size_bits = ADDRESS_WIDTH_BITS;
+        int nr = ARCH_PAGE_SIZE / sizeof(struct page);
+        int total = (reg.end - reg.start) >> ARCH_PAGE_SHIFT;
+        int mnr = (total + nr) / (nr + 1);
+
+        LOG_D("nr = 0x%08x\n", nr);
+        LOG_D("total = 0x%08x\n", total);
+        LOG_D("mnr = 0x%08x\n", mnr);
+
+        RT_ASSERT(mnr < total);
+
+        page_start = (struct page*)reg.start;
+        reg.start += (mnr << ARCH_PAGE_SHIFT);
+        page_addr = (void*)reg.start;
+        page_nr = (reg.end - reg.start) >> ARCH_PAGE_SHIFT;
     }
 
-    //init free list
-    for(i = 0;i < PAGE_LIST_SIZE;i++)
+    LOG_D("align 0x%08x 0x%08x\n", reg.start, reg.end);
+
+    /* init free list */
+    for (i = 0; i < ARCH_PAGE_LIST_SIZE; i++)
     {
-        page_list[i] = RT_NULL;
+        page_list[i] = 0;
     }
 
-    //init buddy list
-    while(reg.start != reg.end)
+    /* add pages to free list */
+    while (reg.start != reg.end)
     {
         struct page *p;
-        size_bits = ADDRESS_WIDTH_BITS - 1 - __builtin_clzl(reg.end - reg.start);
-        align_bits = __builtin_ctzl(reg.start);
-
-        /*
-            align_bits < size_bits:a small page exists
-            align_bits = size_bits:this is a page
-            align_bits > size_bits:the size of memory is less than the align size of current addr
-        */
-        if(align_bits < size_bits)
+        int align_bits;
+        int size_bits;
+
+        size_bits = ARCH_ADDRESS_WIDTH_BITS - 1 - rt_clz(reg.end - reg.start);
+        align_bits = rt_ctz(reg.start);
+        if (align_bits < size_bits)
         {
             size_bits = align_bits;
         }
         p = addr_to_page((void*)reg.start);
+        p->size_bits = ARCH_ADDRESS_WIDTH_BITS;
         p->ref_cnt = 1;
-        _pages_free(addr_to_page((void *)reg.start),size_bits - PAGE_OFFSET_BIT);
-        reg.start += (1U << size_bits);
+        _pages_free(p, size_bits - ARCH_PAGE_SHIFT);
+        reg.start += (1UL << size_bits);
     }
-
-    rt_pages_alloc(0);
 }
-
-#endif /* RT_USING_USERSPACE */
+#endif

+ 20 - 16
libcpu/x86/i386/page.h

@@ -1,34 +1,38 @@
 /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
+ * Copyright (c) 2006-2019, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date           Author       Notes
- * 2021-01-29     lizhirui     first version
- * 2021-07-17     JasonHu      used in i386
+ * 2019-11-01     Jesven      The first version
  */
 
-#ifndef __PAGE_H__
-#define __PAGE_H__
+#ifndef  __PAGE_H__
+#define  __PAGE_H__
 
-#include <rtdef.h>
+#ifdef RT_USING_USERSPACE
 
-struct tag_region
+typedef struct tag_region
 {
     size_t start;
     size_t end;
-};
-typedef struct tag_region rt_region_t;
+} rt_region_t;
+
+void rt_page_init(rt_region_t reg);
+
+void *rt_pages_alloc(uint32_t size_bits);
 
-rt_size_t rt_page_bits(rt_size_t size);
-void *rt_pages_alloc(rt_size_t size_bits);
 void rt_page_ref_inc(void *addr, uint32_t size_bits);
-int rt_page_ref_get(void *addr, uint32_t size_bits);
-void rt_page_ref_dec(void *addr, uint32_t size_bits);
-int rt_pages_free(void *addr,rt_size_t size_bits);
-void rt_pageinfo_dump();
+
+int rt_pages_free(void *addr, uint32_t size_bits);
+
+void rt_pageinfo_dump(void);
+
+size_t rt_page_bits(size_t size);
+
 void rt_page_get_info(size_t *total_nr, size_t *free_nr);
-void rt_page_init(rt_region_t reg);
 
 #endif
+
+#endif  /*__PAGE_H__*/