Skip to content

Commit 52aeb9c

Browse files
authored
add demand paging for systems with serial memory (#224)
add csrc/paging folder add fetch and store macros add QA macros from PortAudio Add unit tests for demand paging Add PF_ASSERT() macro. Add pagedmem.h for the serial memory API. reduce use of int data type add U.HEX and use it in MAP Support different sized ptr and cell! For example, a pointer can be 32-bit and CELL can be 64-bit. For demand paging on a system with 16-bit pointers, we need to support 16-bit pointers in the kernel, and 32-bit CELL and VM addresses on the stack. build using --std=c99 Fix lots of warnings. link with ldatomic for address sanitization Used (uintptr_t) casting to address warnings related to converting form a 32-bit cell_t to a pointer. Add new paging files to CMake build CI for cell size 4 and 8 on 32-bit builds
1 parent 63d4a41 commit 52aeb9c

37 files changed

Lines changed: 1806 additions & 395 deletions

.github/workflows/make.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,18 @@ env:
1313

1414
jobs:
1515
build:
16+
name: Build (PAGING=${{ matrix.demand_paging }}, FLOAT=${{ matrix.support_fp }})
1617
# This uses a Unix Makefile and should run on Linux and Mac
1718
runs-on: ubuntu-latest
1819

20+
strategy:
21+
matrix:
22+
demand_paging: [0, 1]
23+
support_fp: [0, 1]
24+
1925
steps:
2026
- uses: actions/checkout@v2
2127

2228
- name: Build and Test
2329
working-directory: ${{github.workspace}}/platforms/unix
24-
run: make test ASAN=1
30+
run: make test ASAN=1 XCPPFLAGS="-DPF_SUPPORT_FP=${{ matrix.support_fp }} -DPF_DEMAND_PAGING=${{ matrix.demand_paging }} -D_DEFAULT_SOURCE -D_GNU_SOURCE"

.github/workflows/make32.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,16 @@ env:
1313

1414
jobs:
1515
build:
16+
name: Build 32-bit (PAGING=${{ matrix.demand_paging }}, FLOAT=${{ matrix.support_fp }}, CELL=${{ matrix.cell_size }})
1617
# This uses a Unix Makefile and should run on Linux and Mac
1718
runs-on: ubuntu-latest
1819

20+
strategy:
21+
matrix:
22+
demand_paging: [0, 1]
23+
support_fp: [0, 1]
24+
cell_size: [4, 8]
25+
1926
steps:
2027
- uses: actions/checkout@v2
2128

@@ -24,5 +31,5 @@ jobs:
2431

2532
- name: Build and Test
2633
working-directory: ${{github.workspace}}/platforms/unix
27-
run: make test WIDTHOPT=-m32 ASAN=1
34+
run: make test WIDTHOPT=-m32 ASAN=1 XCPPFLAGS="-DPF_SUPPORT_FP=${{ matrix.support_fp }} -DPF_DEMAND_PAGING=${{ matrix.demand_paging }} -DPF_CELL_SIZE=${{ matrix.cell_size }} -D_DEFAULT_SOURCE -D_GNU_SOURCE"
2835

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ fth/fatest1.txt
1111
fth/pforth.dic
1212
**/.DS_Store
1313
build/
14+
Testing/
1415

1516
CMakeCache.txt
1617
CMakeFiles/

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ add_custom_command(OUTPUT ${PFORTH_DIC}
7070
COMMAND ./${PFORTH_EXE} -i ${PFORTH_FTH_DIR}/system.fth
7171
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
7272
DEPENDS pforth
73-
COMMENT Building pforth.dic
73+
COMMENT "Building pforth.dic"
7474
VERBATIM
7575
)
7676
add_custom_target(pforth_dic DEPENDS ${PFORTH_DIC})
@@ -83,7 +83,7 @@ add_custom_command(OUTPUT ${PFORTH_DIC_HEADER}
8383
COMMAND ${CMAKE_COMMAND} -E rename pfdicdat.h ../csrc/pfdicdat.h
8484
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
8585
DEPENDS pforth_dic
86-
COMMENT Building pfdicdat.h
86+
COMMENT "Building pfdicdat.h"
8787
VERBATIM
8888
)
8989
add_custom_target(pforth_dic_header DEPENDS ${PFORTH_DIC_HEADER})

csrc/paging/dmpaging.h

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#ifndef _pf_dmpaging_h
2+
#define _pf_dmpaging_h
3+
4+
/***************************************************************
5+
** Include file for PForth Demand Paging
6+
**
7+
** Author: Phil Burk
8+
** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom
9+
**
10+
** Permission to use, copy, modify, and/or distribute this
11+
** software for any purpose with or without fee is hereby granted.
12+
**
13+
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
14+
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
15+
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
16+
** THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
17+
** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
18+
** FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19+
** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20+
** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21+
**
22+
***************************************************************/
23+
24+
#ifdef __cplusplus
25+
extern "C" {
26+
#endif
27+
28+
/**
29+
* To use demand paged memory, enable the code by passing -DPF_DEMAND_PAGING=1
30+
* to the C compiler.
31+
*/
32+
typedef ucell_t paging_address_t; /** an address in paged memory */
33+
34+
/* Basic memory access macros. */
35+
#if (PF_DEMAND_PAGING == 0)
36+
/* Straight memory access. */
37+
#define DP_FETCH_U8(address) (*((const uint8_t *)(uintptr_t)(address)))
38+
#define DP_FETCH_U16(address) (*((const uint16_t *)(uintptr_t)(address)))
39+
#define DP_FETCH_CELL(address) (*((const cell_t *)(uintptr_t)(address)))
40+
#define DP_FETCH_FLOAT(address) (*((const PF_FLOAT *)(uintptr_t)(address)))
41+
42+
#define DP_STORE_U8(address, value) *((uint8_t *)(uintptr_t)(address)) = (uint8_t)(value)
43+
#define DP_STORE_U16(address, value) *((uint16_t *)(uintptr_t)(address)) = (uint16_t)(value)
44+
#define DP_STORE_CELL(address, value) *((cell_t *)(uintptr_t)(address)) = (cell_t)(value)
45+
#define DP_STORE_FLOAT(address, value) *((PF_FLOAT *)(uintptr_t)(address)) = (PF_FLOAT)(value)
46+
47+
#else /* PF_DEMAND_PAGING */
48+
49+
/* Use either physical or paged memory. */
50+
#define DP_FETCH_U8(address) pfFetchVirtualU8(PTR_TO_VMA(address))
51+
#define DP_FETCH_U16(address) pfFetchVirtualU16(PTR_TO_VMA(address))
52+
#define DP_FETCH_CELL(address) pfFetchVirtualCell(PTR_TO_VMA(address))
53+
#define DP_FETCH_FLOAT(address) pfFetchVirtualFloat(PTR_TO_VMA(address))
54+
55+
#define DP_STORE_U8(address, value) pfStoreVirtualU8(PTR_TO_VMA(address), (uint8_t)(value))
56+
#define DP_STORE_U16(address, value) pfStoreVirtualU16(PTR_TO_VMA(address), (uint16_t)(value))
57+
#define DP_STORE_CELL(address, value) pfStoreVirtualCell(PTR_TO_VMA(address), (cell_t)(value))
58+
#define DP_STORE_FLOAT(address, value) pfStoreVirtualFloat(PTR_TO_VMA(address), (PF_FLOAT)(value))
59+
#endif /* PF_DEMAND_PAGING */
60+
61+
uint8_t pfFetchVirtualU8(vm_address_t address);
62+
uint16_t pfFetchVirtualU16(vm_address_t address);
63+
cell_t pfFetchVirtualCell(vm_address_t address);
64+
65+
void pfStoreVirtualU8(vm_address_t address, uint8_t value);
66+
void pfStoreVirtualU16(vm_address_t address, uint16_t value);
67+
void pfStoreVirtualCell(vm_address_t address, cell_t value);
68+
69+
#ifdef PF_SUPPORT_FP
70+
PF_FLOAT pfFetchVirtualFloat(vm_address_t address);
71+
void pfStoreVirtualFloat(vm_address_t address, PF_FLOAT value);
72+
#endif /* PF_SUPPORT_FP */
73+
74+
/* Memory region locking and unlocking
75+
* A maximum of DP_MAX_REGIONS can be locked at one time.
76+
* The regions cannot overlap.
77+
* Adjacent virtual regions will not be adjacent in physical memory!
78+
*/
79+
80+
/* maximum number of locked regions */
81+
#define DP_MAX_REGIONS (4)
82+
/* maximum number of bytes per region */
83+
#define DP_MAX_REGION_SIZE (256)
84+
85+
void pfResetLockedMemory(void);
86+
87+
/**
88+
* Lock a read-only region of demand paging in physical memory.
89+
* Load the data from demand paging if not already loaded.
90+
* A region should only be locked temporarily, for example within
91+
* a single primitive.
92+
* If the virtual memory address is not in paged memory then it will be passed through.
93+
* You cannot lock more than DP_MAX_REGION_SIZE bytes.
94+
*
95+
* @param vp virtual address in physical or paged memory
96+
* @param numBytes number of byte in region
97+
* @return physical address that can be used by normal C code as “const” memory.
98+
*/
99+
const uint8_t *pfLockMemoryReadOnly(vm_address_t vp, uint32_t numBytes);
100+
101+
/**
102+
* Lock a read-write region of demand paging in physical memory.
103+
* Load the data from demand paging if not already loaded.
104+
* If the virtual memory address is not in paged memory then it will be passed through.
105+
* You cannot lock more than DP_MAX_REGION_SIZE bytes.
106+
*
107+
* @param vp virtual address in physical or paged memory
108+
* @param numBytes number of byte in region
109+
* @return physical address that can be read or written by normal C code.
110+
*/
111+
uint8_t *pfLockMemoryReadWrite(vm_address_t vp, uint32_t numBytes);
112+
113+
/**
114+
* Release a previously locked region of memory.
115+
* Writable regions will be written back to serial memory.
116+
* Regions may be kept in physical memory on an LRU basis
117+
* to improve performance.
118+
* @param vp virtual address in physical or paged memory
119+
* @param pp physical memory address
120+
* @return negative code if an error occured else zero
121+
*/
122+
int pfUnlockMemory(vm_address_t vp, const uint8_t *pp);
123+
124+
/** Copy from virtual to physical memory.
125+
* @param destination target address in physical memory
126+
* @param source data address in physical or paged memory
127+
* @return destination
128+
*/
129+
void *pfCopyFromVirtualMemory(void *destination,
130+
vm_address_t source,
131+
uint32_t numBytes);
132+
133+
/** Copy from physical to virtual memory.
134+
* @param destination target address in physical or paged memory
135+
* @param source in physical memory
136+
* @return destination
137+
*/
138+
vm_address_t pfCopyToVirtualMemory(vm_address_t destination,
139+
const void *source,
140+
uint32_t numBytes);
141+
142+
/** Free virtual memory.
143+
* @param address may be in physical or paged memory
144+
*/
145+
void pfFreeVirtualMemory(vm_address_t address);
146+
147+
/** Set a region of virtual memory to a byte value.
148+
* @param destination in physical or paged memory
149+
* @param value fill memory with this value
150+
* @param numBytes how many bytes to set
151+
* @return destination
152+
*/
153+
vm_address_t pfSetVirtualMemory(vm_address_t destination,
154+
uint8_t value,
155+
uint32_t numBytes);
156+
157+
#ifdef __cplusplus
158+
}
159+
#endif
160+
161+
#endif /* _pf_dmpaging_h */

0 commit comments

Comments
 (0)