diff --git a/all.tar.gz b/all.tar.gz new file mode 100644 index 0000000..a358a4d Binary files /dev/null and b/all.tar.gz differ diff --git a/build.sh b/build.sh index 6ffe1d1..145bd29 100755 --- a/build.sh +++ b/build.sh @@ -1 +1 @@ -g++ ccc.cpp -o ccc -ltree-sitter -ltree-sitter-c +g++ ccc.cpp -o ccc -ltree-sitter -ltree-sitter-c -llzma diff --git a/ccc.cpp b/ccc.cpp index 1cdba9c..0c95c2d 100644 --- a/ccc.cpp +++ b/ccc.cpp @@ -9,6 +9,7 @@ #include #include #include +#include using namespace std; namespace fs=filesystem; const vector CCC_C_KEYYORD_HEAD {0,0,0}; @@ -157,7 +158,9 @@ const vector c_keywords={ "unsigned", "void", "volatile", - "while" + "while", + "__asm__", + "__attribute__" }; struct symbol { string name; @@ -177,10 +180,19 @@ void insert(node* root,string str,int id) { } curr->token_id=id; } -vector all_tokens; -void get_all_nodes(TSNode node,const string &source_code,map &rec_map) { +struct processed_file { + string path; + uint32_t payload_size; + vector payload; + bool is_payload_compressed; +}; +map> all_tokens; +map rec_map; +vector rec_list; +bool debug=false; +void get_all_nodes(TSNode node,const string &source_code,map &rec_map,const string& file) { if (ts_node_child_count(node)==0) { - all_tokens.push_back(node); + all_tokens[file].push_back(node); string text=source_code.substr(ts_node_start_byte(node),ts_node_end_byte(node)-ts_node_start_byte(node)); if (string(ts_node_type(node))=="string_content" || string(ts_node_type(node))=="system_lib_string" || string(ts_node_type(node))=="identifier" || string(ts_node_type(node))=="number_literal" || string(ts_node_type(node))=="type_identifier" || string(ts_node_type(node))=="field_identifier" || string(ts_node_type(node))=="escape_sequence" || string(ts_node_type(node))=="statement_identifier") { rec_map[text]++; @@ -188,11 +200,14 @@ void get_all_nodes(TSNode node,const string &source_code,map &rec_ma if (string(ts_node_type(node))=="primitive_type" && find(c_keywords.begin(),c_keywords.end(),text)==c_keywords.end()) { rec_map[text]++; } + if (string(ts_node_type(node))=="comment") { + rec_map[text]=2; + } } else { uint32_t child_count=ts_node_child_count(node); for (uint32_t i=0;i generate_string_content(string str) { } return out; } -vector process_all_nodes(vector *nodes,string code,vector &rec_list) { +void print_debug(string text) { + if (debug==true) { + cout< process_file_nodes(vector *nodes,string code,vector &rec_list) { vector out; for (int i=0;isize();i++) { string type=string(ts_node_type(nodes->at(i))); if (type=="#if") { CCC_ADD_COMPOMENT(out,CCC_PREPROCESSOR_CONDITIONAL_IF); - cout<<"if"<at(i)),ts_node_end_byte(nodes->at(i))-ts_node_start_byte(nodes->at(i))); auto it=find(rec_list.begin(),rec_list.end(),text); @@ -342,17 +362,17 @@ vector process_all_nodes(vector *nodes,string code,vector if (!text.empty()) { string text=code.substr(ts_node_start_byte(nodes->at(i)),ts_node_end_byte(nodes->at(i))-ts_node_start_byte(nodes->at(i))); CCC_ADD_COMPOMENT(out,generate_string_content(text)); - cout<<"string ("<at(i)),ts_node_end_byte(nodes->at(i))-ts_node_start_byte(nodes->at(i))); @@ -360,21 +380,21 @@ vector process_all_nodes(vector *nodes,string code,vector if (it!=c_keywords.end()) { size_t index=distance(c_keywords.begin(),it); CCC_ADD_COMPOMENT(out,generate_c_keyword(index)); - cout<<"primitive_type: "< process_all_nodes(vector *nodes,string code,vector if (it!=delimiter.end()) { size_t index=distance(delimiter.begin(),it); CCC_ADD_COMPOMENT(out,generate_delimiter(index)); - cout<<"delimiter: "< process_all_nodes(vector *nodes,string code,vector if (it!=other_grammer.end()) { size_t index=distance(other_grammer.begin(),it); CCC_ADD_COMPOMENT(out,generate_other_grammar(index)); - cout<<"other grammar: "< process_all_nodes(vector *nodes,string code,vector if (it!=c_keywords.end()) { size_t index=distance(c_keywords.begin(),it); CCC_ADD_COMPOMENT(out,generate_c_keyword(index)); - cout<<"c keyword: "< process_all_nodes(vector *nodes,string code,vector if (it!=miscellaneous.end()) { size_t index=distance(miscellaneous.begin(),it); CCC_ADD_COMPOMENT(out,generate_miscellaneous(index)); - cout<<"miscellaneous: "<at(i)),ts_node_end_byte(nodes->at(i))-ts_node_start_byte(nodes->at(i))); + auto it=find(rec_list.begin(),rec_list.end(),text); + if (it==rec_list.end()) { + cout<<"Error: comment in reccurences map not found: "<size()) { if (string(ts_node_type(nodes->at(i+1)))=="\"") { auto it=find(delimiter.begin(),delimiter.end(),""); size_t index=distance(delimiter.begin(),it); CCC_ADD_COMPOMENT(out,generate_delimiter(index)); - cout<<"double quotes mark, inserting delimiter for empty string"<at(i)),ts_node_end_byte(nodes->at(i))-ts_node_start_byte(nodes->at(i))); - cout<<"unknow node type: "<"<(file)),istreambuf_iterator()); - TSParser *parser=ts_parser_new(); - ts_parser_set_language(parser,tree_sitter_c()); - TSTree *tree=ts_parser_parse_string(parser,nullptr,code.c_str(),code.size()); - TSNode root=ts_tree_root_node(tree); - map rec_map; - vector rec_list; - get_all_nodes(root,code,rec_map); - for (auto s:rec_map) { - if (s.second>=2 and s.first.size()>=3 && s.first.size()<=256) { - rec_list.push_back(s.first); - } - } - auto payload=process_all_nodes(&all_tokens,code,rec_list); - vector out={0,1,0,0,0,0,1,1,0,1,0,0,0,0,1,1,0,1,0,0,0,0,1,1}; - for (int i=63;i>=0;i--) { - bool enabled=(rec_list.size()>>i)&0x01; - out.push_back(enabled); - } - for (int i=0;i=0;i--) { - bool enabled=(size>>i)&0x01; - out.push_back(enabled); - } - for (auto c:rec_list[i]) { - for (int i=7;i>=0;i--) { - bool enabled=(c>>i)&0x01; - out.push_back(enabled); - } - } - } - CCC_ADD_COMPOMENT(out,payload); - vector outbytes; + vector payload_bytes; unsigned char current=0; - int bit_index=0; + size_t bit_index=0; for (bool b:out) { current|=(b<<(7-bit_index)); bit_index++; if (bit_index==8) { - outbytes.push_back(current); + payload_bytes.push_back(current); current=0; bit_index=0; } } if (bit_index!=0) { - outbytes.push_back(current); + payload_bytes.push_back(current); } - ofstream fileout(filepath+".ccc",ios::binary); - if (!fileout) { - cout<<"Error: couldn't open output file."< &files_content,vector files_names) { + for (int i=0;i=2 and s.first.size()>=3) { + rec_list.push_back(s.first); + } + } +} +int main(int argc,char **argv) { + if (argc<2) { + cout<<"Usage: ccc [FILES]"<(outbytes.data()),outbytes.size()); - fileout.close(); - cout<<"Reccurences map entry count: "< files; + for (int i=1;i files_content; + for (auto f:files) { + ifstream file(f,ios::binary); + if (!file) { + cout<<"Error: couldn't open provided file."<(file)),istreambuf_iterator()); + files_content.push_back(code); + } + construct_rec_table(files_content,files); + vector files_archive; + for (int i=0;i payload_compressed; + payload_compressed.resize(payload_bytes.size()+payload_bytes.size()/3+128); + lzma_stream strm=LZMA_STREAM_INIT; + if (lzma_easy_encoder(&strm,9,LZMA_CHECK_CRC64)!=LZMA_OK) { + cout<<"Error: couldn't initialize LZMA compressor for file: "<=original_size) { + pfile.is_payload_compressed=false; + pfile.payload=payload_bytes; + pfile.payload_size=original_size; + } else { + pfile.is_payload_compressed=true; + pfile.payload=payload_compressed; + pfile.payload_size=compressed_size; + } + cout< rec_table; + // for (int i=0;i rec_table_compressed; + // rec_table_compressed.resize(rec_table.size()+rec_table.size()/3+128); + // lzma_stream strm=LZMA_STREAM_INIT; + // if (lzma_easy_encoder(&strm,9,LZMA_CHECK_CRC64)!=LZMA_OK) { + // cout<<"Error: couldn't initialize LZMA compressor."< out; + // out.push_back('C'); + // out.push_back(compressed_size>=original_size?'C':'c'); + // vector payload_bytes; + // unsigned char current=0; + // size_t bit_index=0; + // for (bool b:payload) { + // current|=(b<<(7-bit_index)); + // bit_index++; + // if (bit_index==8) { + // payload_bytes.push_back(current); + // current=0; + // bit_index=0; + // } + // } + // if (bit_index!=0) { + // payload_bytes.push_back(current); + // } + // vector payload_compressed; + // payload_compressed.resize(payload_bytes.size()+payload_bytes.size()/3+128); + // strm=LZMA_STREAM_INIT; + // if (lzma_easy_encoder(&strm,9,LZMA_CHECK_CRC64)!=LZMA_OK) { + // cout<<"Error: couldn't initialize LZMA compressor."<=original_size1?'C':'c'); + // if (compressed_size>=original_size) { + // CCC_ADD_COMPOMENT(out,rec_table); + // } else { + // CCC_ADD_COMPOMENT(out,rec_table_compressed); + // } + // if (compressed_size1>=original_size1) { + // CCC_ADD_COMPOMENT(out,payload_bytes); + // } else { + // CCC_ADD_COMPOMENT(out,payload_compressed); + // } + // ofstream fileout("test.ccc",ios::binary); + // if (!fileout) { + // cout<<"Error: couldn't open output file."<(out.data()),out.size()); + // fileout.close(); + // return 0; } diff --git a/ccc.cpp.ccc b/ccc.cpp.ccc deleted file mode 100644 index 2a83843..0000000 Binary files a/ccc.cpp.ccc and /dev/null differ diff --git a/hello.c b/hello.c index 458e355..fcf50b7 100644 --- a/hello.c +++ b/hello.c @@ -1,6 +1,12 @@ #include #include typedef static unsigned char HEY; +// hello +// hello +// hello +// hello +// hello +// hello int main() { hello[]="hello"; HEY res=8; diff --git a/hello.c.ccc b/hello.c.ccc deleted file mode 100644 index 1dcd819..0000000 Binary files a/hello.c.ccc and /dev/null differ diff --git a/log.c b/log.c new file mode 100644 index 0000000..54df5d6 --- /dev/null +++ b/log.c @@ -0,0 +1,409 @@ +#include "../include/log.h" +#include "../include/page.h" +sh_uint8 kernel_log_level=0; +static inline sh_uint8 inb(sh_uint16 port) { + sh_uint8 val; + __asm__ volatile ("inb %1, %0":"=a"(val):"Nd"(port)); + return val; +} +static inline void outb(sh_uint16 port,sh_uint8 val) { + __asm__ volatile ("outb %0, %1"::"a"(val),"Nd"(port)); +} +SH_STATUS sh_log_send_byte(sh_uint8 b) { + while (!(inb(SH_LOG_SERIAL_PORT_COM1+5) & 0x20)); + outb(SH_LOG_SERIAL_PORT_COM1,b); + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_send_string(const char* str) { + while (*str) { + sh_log_send_byte(*str++); + } + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_send_uintn(sh_uint64 n) { + char buf[20]; + sh_uint32 i=0; + if (n==0) { + sh_log_send_byte('0'); + return SH_STATUS_SUCCESS; + } + while (n>0) { + buf[i++]='0'+(n%10); + n/=10; + } + while (i--) { + sh_log_send_byte(buf[i]); + } + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_send_uintn_hex(sh_uint64 n) { + char buf[16]; + sh_uint32 i=0; + const char hex_digits[]="0123456789ABCDEF"; + if (n==0) { + sh_log_send_byte('0'); + return SH_STATUS_SUCCESS; + } + while (n>0) { + buf[i++]=hex_digits[n & 0xF]; + n>>=4; + } + while (i--) { + sh_log_send_byte(buf[i]); + } + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_send_double(double value) { + if (value<0) { + sh_log_send_byte('-'); + value=-value; + } + sh_uint64 integer_part=(sh_uint64)value; + double fractional_part=value-(double)integer_part; + SH_STATUS status=sh_log_send_uintn(integer_part); + if (status!=SH_STATUS_SUCCESS) return status; + status=sh_log_send_byte('.'); + if (status!=SH_STATUS_SUCCESS) return status; + for (int i=0;i<6;i++) { + fractional_part*=10.0; + sh_uint64 digit=(sh_uint64)fractional_part; + status=sh_log_send_byte('0'+(sh_uint8)digit); + if (status!=SH_STATUS_SUCCESS) return status; + fractional_part-=(double)digit; + } + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_send_payload(sh_log_OUTPUT_PAYLOAD *payload) { + if (payload==SH_NULLPTR) { + return SH_STATUS_INVALID_PARAMETER; + } + if (!(sh_log_output_type_valid(payload->output_type))) { + return SH_STATUS_INVALID_PARAMETER; + } + if (!(sh_log_output_source_valid(payload->output_source))) { + return SH_STATUS_INVALID_PARAMETER; + } + if (payload->output_source!=SH_LOG_SOURCE_TEST && payload->output_typeoutput_source==SH_LOG_SOURCE_MAIN) { + sh_log_send_string("Main@"); + } else if (payload->output_source==SH_LOG_SOURCE_CONF) { + sh_log_send_string("Conf@"); + } else if (payload->output_source==SH_LOG_SOURCE_PAGE) { + sh_log_send_string("Page@"); + } else if (payload->output_source==SH_LOG_SOURCE_SLAB) { + sh_log_send_string("Slab@"); + } else if (payload->output_source==SH_LOG_SOURCE_TEST) { + sh_log_send_string("Test@"); + } + if (payload->output_type==SH_LOG_DEBUG) { + sh_log_send_string("Debug] "); + } else if (payload->output_type==SH_LOG_LOG) { + sh_log_send_string("Log] "); + } else if (payload->output_type==SH_LOG_WARNING) { + sh_log_send_string("Warning] "); + } else if (payload->output_type==SH_LOG_ERROR) { + sh_log_send_string("Error] "); + } else if (payload->output_type==SH_LOG_CRITICAL) { + sh_log_send_string("Critical] "); + } else if (payload->output_type==SH_LOG_FATAL) { + sh_log_send_string("Fatal] "); + } else if (payload->output_type==SH_LOG_TEST) { + sh_log_send_string("Test] "); + } + sh_log_send_uintn(payload->tsc_value); + sh_log_send_string(" : "); + sh_log_send_string(payload->message_pointer); + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_load_log_level(sh_uint8 log_level) { + kernel_log_level=log_level; + return SH_STATUS_SUCCESS; +} +sh_uint8 sh_log_get_log_level() { + return kernel_log_level; +} +SH_STATUS sh_log_test(const char* str) { + if (str==SH_NULLPTR) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_log_OUTPUT_PAYLOAD payload={ + .output_type=SH_LOG_TEST, + .output_source=SH_LOG_SOURCE_TEST, + .tsc_value=sh_tsc_get_kernel_current_tsc(), + .message_pointer=str + }; + SH_STATUS status=sh_log_send_payload(&payload); + if (sh_status_error(status)) { + return status; + } + sh_log_send_string("\n"); + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_debug(const char* str,sh_log_OUTPUT_SOURCE source) { + if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_log_OUTPUT_PAYLOAD payload={ + .output_type=SH_LOG_DEBUG, + .output_source=source, + .tsc_value=sh_tsc_get_kernel_current_tsc(), + .message_pointer=str + }; + SH_STATUS status=sh_log_send_payload(&payload); + if (sh_status_error(status)) { + return status; + } + sh_log_send_string("\n"); + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_log(const char* str,sh_log_OUTPUT_SOURCE source) { + if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_log_OUTPUT_PAYLOAD payload={ + .output_type=SH_LOG_LOG, + .output_source=source, + .tsc_value=sh_tsc_get_kernel_current_tsc(), + .message_pointer=str + }; + SH_STATUS status=sh_log_send_payload(&payload); + if (sh_status_error(status)) { + return status; + } + sh_log_send_string("\n"); + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_warning(const char* str,sh_log_OUTPUT_SOURCE source) { + if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_log_OUTPUT_PAYLOAD payload={ + .output_type=SH_LOG_WARNING, + .output_source=source, + .tsc_value=sh_tsc_get_kernel_current_tsc(), + .message_pointer=str + }; + SH_STATUS status=sh_log_send_payload(&payload); + if (sh_status_error(status)) { + return status; + } + sh_log_send_string("\n"); + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_error(const char* str,sh_log_OUTPUT_SOURCE source) { + if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_log_OUTPUT_PAYLOAD payload={ + .output_type=SH_LOG_ERROR, + .output_source=source, + .tsc_value=sh_tsc_get_kernel_current_tsc(), + .message_pointer=str + }; + SH_STATUS status=sh_log_send_payload(&payload); + if (sh_status_error(status)) { + return status; + } + sh_log_send_string("\n"); + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_critical(const char* str,sh_log_OUTPUT_SOURCE source) { + if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_log_OUTPUT_PAYLOAD payload={ + .output_type=SH_LOG_CRITICAL, + .output_source=source, + .tsc_value=sh_tsc_get_kernel_current_tsc(), + .message_pointer=str + }; + SH_STATUS status=sh_log_send_payload(&payload); + if (sh_status_error(status)) { + return status; + } + sh_log_send_string("\n"); + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_fatal(const char* str,sh_log_OUTPUT_SOURCE source) { + if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_log_OUTPUT_PAYLOAD payload={ + .output_type=SH_LOG_FATAL, + .output_source=source, + .tsc_value=sh_tsc_get_kernel_current_tsc(), + .message_pointer=str + }; + SH_STATUS status=sh_log_send_payload(&payload); + if (sh_status_error(status)) { + return status; + } + sh_log_send_string("\n"); + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_ltest(const char* str) { + if (str==SH_NULLPTR) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_log_OUTPUT_PAYLOAD payload={ + .output_type=SH_LOG_TEST, + .output_source=SH_LOG_SOURCE_TEST, + .tsc_value=sh_tsc_get_kernel_current_tsc(), + .message_pointer=str + }; + SH_STATUS status=sh_log_send_payload(&payload); + if (sh_status_error(status)) { + return status; + } + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_ldebug(const char* str,sh_log_OUTPUT_SOURCE source) { + if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_log_OUTPUT_PAYLOAD payload={ + .output_type=SH_LOG_DEBUG, + .output_source=source, + .tsc_value=sh_tsc_get_kernel_current_tsc(), + .message_pointer=str + }; + SH_STATUS status=sh_log_send_payload(&payload); + if (sh_status_error(status)) { + return status; + } + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_llog(const char* str,sh_log_OUTPUT_SOURCE source) { + if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_log_OUTPUT_PAYLOAD payload={ + .output_type=SH_LOG_LOG, + .output_source=source, + .tsc_value=sh_tsc_get_kernel_current_tsc(), + .message_pointer=str + }; + SH_STATUS status=sh_log_send_payload(&payload); + if (sh_status_error(status)) { + return status; + } + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_lwarning(const char* str,sh_log_OUTPUT_SOURCE source) { + if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_log_OUTPUT_PAYLOAD payload={ + .output_type=SH_LOG_WARNING, + .output_source=source, + .tsc_value=sh_tsc_get_kernel_current_tsc(), + .message_pointer=str + }; + SH_STATUS status=sh_log_send_payload(&payload); + if (sh_status_error(status)) { + return status; + } + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_lerror(const char* str,sh_log_OUTPUT_SOURCE source) { + if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_log_OUTPUT_PAYLOAD payload={ + .output_type=SH_LOG_ERROR, + .output_source=source, + .tsc_value=sh_tsc_get_kernel_current_tsc(), + .message_pointer=str + }; + SH_STATUS status=sh_log_send_payload(&payload); + if (sh_status_error(status)) { + return status; + } + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_lcritical(const char* str,sh_log_OUTPUT_SOURCE source) { + if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_log_OUTPUT_PAYLOAD payload={ + .output_type=SH_LOG_CRITICAL, + .output_source=source, + .tsc_value=sh_tsc_get_kernel_current_tsc(), + .message_pointer=str + }; + SH_STATUS status=sh_log_send_payload(&payload); + if (sh_status_error(status)) { + return status; + } + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_lfatal(const char* str,sh_log_OUTPUT_SOURCE source) { + if (str==SH_NULLPTR || !(sh_log_output_source_valid(source))) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_log_OUTPUT_PAYLOAD payload={ + .output_type=SH_LOG_FATAL, + .output_source=source, + .tsc_value=sh_tsc_get_kernel_current_tsc(), + .message_pointer=str + }; + SH_STATUS status=sh_log_send_payload(&payload); + if (sh_status_error(status)) { + return status; + } + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_log_mem_stats(sh_log_OUTPUT_SOURCE source) { + sh_page_MEM_STATS mem_stats; + sh_page_get_memory_stats(&mem_stats); + if (sh_log_get_log_level()<=1) { + sh_log_llog("Total memory installed (bytes) : ",source); + sh_log_send_uintn(mem_stats.memory_total_bytes); + sh_log_send_string(" / 0x"); + sh_log_send_uintn_hex(mem_stats.memory_total_bytes); + sh_log_send_string("\n"); + sh_log_llog("Total memory installed (pages) : ",source); + sh_log_send_uintn(mem_stats.memory_total_pages); + sh_log_send_string(" / 0x"); + sh_log_send_uintn_hex(mem_stats.memory_total_pages); + sh_log_send_string("\n"); + sh_log_llog("Free memory : ",source); + sh_log_send_double(mem_stats.free_ratio*100); + sh_log_send_string("%\n"); + sh_log_llog("Used memory : ",source); + sh_log_send_double(mem_stats.used_ratio*100); + sh_log_send_string("%\n"); + sh_log_llog("Free pages : ",source); + sh_log_send_uintn(mem_stats.free_pages); + sh_log_send_string("\n"); + sh_log_llog("Used pages : ",source); + sh_log_send_uintn(mem_stats.used_pages); + sh_log_send_string("\n"); + sh_log_llog("Largest free block (pages) : ",source); + sh_log_send_uintn(mem_stats.largest_free_block); + sh_log_send_string("\n"); + sh_log_llog("Largest used block (pages) : ",source); + sh_log_send_uintn(mem_stats.largest_used_block); + sh_log_send_string("\n"); + sh_log_llog("Free block count : ",source); + sh_log_send_uintn(mem_stats.free_blocks_count); + sh_log_send_string("\n"); + sh_log_llog("Used block count : ",source); + sh_log_send_uintn(mem_stats.used_blocks_count); + sh_log_send_string("\n"); + sh_log_llog("Total memory taken by physical bitmap (bytes) : ",source); + sh_log_send_uintn(mem_stats.physical_bitmap_size_bytes); + sh_log_send_string(" / 0x"); + sh_log_send_uintn_hex(mem_stats.physical_bitmap_size_bytes); + sh_log_send_string("\n"); + sh_log_llog("Total memory taken by physical bitmap (pages) : ",source); + sh_log_send_uintn(mem_stats.physical_bitmap_size_pages); + sh_log_send_string(" / 0x"); + sh_log_send_uintn_hex(mem_stats.physical_bitmap_size_pages); + sh_log_send_string("\n"); + } + return SH_STATUS_SUCCESS; +} diff --git a/page.c b/page.c new file mode 100644 index 0000000..48fe7ea --- /dev/null +++ b/page.c @@ -0,0 +1,721 @@ +#include "../include/page.h" +#include +__attribute__((section(".bss"))) +static sh_uint8 memory_map_buffer[64*1024]; +static sh_uint8 *physical_bitmap; +__attribute__((section(".bss"))) +static sh_uint64 physical_memory_pages_count=0; +__attribute__((section(".bss"))) +static sh_uint64 physical_memory_bytes_count=0; +__attribute__((section(".bss"))) +static sh_uint64 physical_bitmap_size_bytes=0; +__attribute__((section(".bss"))) +static sh_uint64 physical_bitmap_size_pages=0; +static sh_page_VIRTUAL_ADRESS page_table_pool_va_ptr=SH_PAGE_NULL_VA; +SH_STATUS sh_page_load_boot_ptp_va(sh_page_VIRTUAL_ADRESS pt_pool_va) { + page_table_pool_va_ptr=pt_pool_va; + sh_log_ldebug("Page table pool VA: 0x",SH_LOG_SOURCE_PAGE); + sh_log_send_uintn_hex((sh_uint64)page_table_pool_va_ptr); + sh_log_send_string("\n"); + sh_uint8 first_byte=*(sh_uint8*)(page_table_pool_va_ptr); + sh_log_debug("If you can see this message, no fault happened.",SH_LOG_SOURCE_PAGE); + return SH_STATUS_SUCCESS; +} +sh_page_VIRTUAL_ADRESS sh_page_get_boot_ptp_va() { + return page_table_pool_va_ptr; +} +SH_STATUS sh_page_copy_memory_map() { + return sh_mem_copy(memory_map_buffer,(void*)SH_PAGE_MEMORY_MAP_VA,sizeof(memory_map_buffer)); +} +SH_STATUS sh_page_check_memory_map() { + static const sh_uint8 memory_map_sig[8]={'S','h','e','M','m','a','p','B'}; + if (sh_mem_compare(memory_map_sig,memory_map_buffer,sizeof(memory_map_sig))==SH_STATUS_MEM_NOT_EQUAL) { + sh_log_critical("Memory map doesn't have signature on.",SH_LOG_SOURCE_PAGE); + return SH_STATUS_INVALID_SIGNATURE; + } + sh_page_MEMORY_MAP_HEADER *memory_map_header=(sh_page_MEMORY_MAP_HEADER *)memory_map_buffer; + sh_log_ldebug("Memory map entry count: ",SH_LOG_SOURCE_PAGE); + sh_log_send_uintn((sh_uint64)memory_map_header->entry_count); + sh_log_send_string("\n"); + sh_log_ldebug("Memory map entry size: ",SH_LOG_SOURCE_PAGE); + sh_log_send_uintn((sh_uint64)memory_map_header->entry_size); + sh_log_send_string("\n"); + sh_log_ldebug("Memory map syntax version: ",SH_LOG_SOURCE_PAGE); + sh_log_send_uintn((sh_uint64)memory_map_header->mmap_syntax_version); + sh_log_send_string("\n"); + if (memory_map_header->entry_count*memory_map_header->entry_size+sizeof(sh_page_MEMORY_MAP_HEADER)>sizeof(memory_map_buffer)) { + sh_log_error("Memory map overflow allocated buffer.",SH_LOG_SOURCE_PAGE); + return SH_STATUS_MMAP_BUFFER_OVERFLOW; + } + return SH_STATUS_SUCCESS; +} +void sh_page_dump_memory_map() { + sh_page_MEMORY_MAP_HEADER *memory_map_header=(sh_page_MEMORY_MAP_HEADER *)memory_map_buffer; + sh_log_send_string("Memory map dump:\n"); + sh_log_send_string("Header:\n"); + for (sh_uint64 i=0;ientry_count;++i) { + sh_log_send_string("Entry number "); + sh_log_send_uintn(i); + sh_log_send_string(" : "); + for (sh_uint64 y=0;y=page_count) { + return 0; + } + if ((value & (1ULL<page_count_in_bitmap) { + return SH_STATUS_INVALID_PARAMETER; + } + for (sh_uint64 i=0;ipage_table_pa=ptp_pa; + page_table_pool->page_table_va=ptp_va; + page_table_pool->ptp_pages_count=SH_PAGE_PTP_ALLOCATOR_PAGES_COUNT; + page_table_pool->ptp_alloc_bitmap_uint64_count=SH_PAGE_PTP_ALLOCATOR_BITMAP_UINT64; + SH_STATUS status=sh_mem_set_8((sh_uint8*)page_table_pool->ptp_alloc_bitmap,SH_FALSE,sizeof(page_table_pool->ptp_alloc_bitmap)); + if (sh_status_error(status)) { + sh_log_error("Error: couldn't initialize page table pool bitmap.",SH_LOG_SOURCE_PAGE); + return SH_STATUS_PT_POOL_NO_BITMAP_INIT; + } + if (initial_fill_level!=0) { + status=sh_page_set_pages_range_bitmap((sh_uint8*)page_table_pool->ptp_alloc_bitmap,page_table_pool->ptp_pages_count,0,initial_fill_level,SH_TRUE); + if (sh_status_error(status)) { + sh_log_error("Error: couldn't initialize pages tables already alocated.",SH_LOG_SOURCE_PAGE); + return SH_STATUS_PT_POOL_NO_PAGE_SET; + } + } + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_page_dump_ptp_bitmap(sh_page_PAGE_TABLE_POOL *ptp) { + for (sh_uint64 i=0;iptp_alloc_bitmap_uint64_count;++i) { + sh_log_send_string(" 0x"); + sh_log_send_uintn_hex(ptp->ptp_alloc_bitmap[i]); + } + sh_log_send_string("\n"); + return SH_STATUS_SUCCESS; +} +sh_page_PHYSICAL_ADRESS sh_page_ptp_alloc_one_page(sh_page_PAGE_TABLE_POOL *pt_pool) { + if (pt_pool==SH_NULLPTR) { + return SH_STATUS_INVALID_PARAMETER; + } + sh_uint64 page_count=pt_pool->ptp_pages_count; + sh_uint64 bitmap_word_count=(page_count+63)/64; + for (sh_uint64 word=0;wordptp_alloc_bitmap[word]; + if (value==0xFFFFFFFFFFFFFFFFULL) { + continue; + } + for (sh_uint64 bit=0;bit<64;bit++) { + sh_uint64 page_index=(word*64)+bit; + if (page_index>=page_count) { + return 0; + } + if ((value & (1ULL<ptp_alloc_bitmap[word]|=(1ULL<page_table_pa+page_index*SH_PAGE_SIZE; + return pa; + } + } + } + return 0; +} +SH_STATUS sh_page_map_one_page_ptp(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADRESS va,sh_page_PHYSICAL_ADRESS pa,sh_uint64 flags) { + if (ptp==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER; + if (va%SH_PAGE_SIZE!=0 || pa%SH_PAGE_SIZE!=0) return SH_STATUS_INVALID_PARAMETER; + sh_uint64 pml4_i=(va>>39) & 0x1FF; + sh_uint64 pdpt_i=(va>>30) & 0x1FF; + sh_uint64 pd_i=(va>>21) & 0x1FF; + sh_uint64 pt_i=(va>>12) & 0x1FF; + sh_uint64 *pdpt; + sh_uint64 *pd; + sh_uint64 *pt; + sh_uint64 *pml4=(sh_uint64*)ptp->page_table_va; + if (!(pml4[pml4_i] & SH_PAGE_PRESENT)) { + sh_page_PHYSICAL_ADRESS pdpt_pa=sh_page_ptp_alloc_one_page(ptp); + if (!pdpt_pa) return SH_STATUS_OUT_OF_MEMORY; + pdpt=sh_page_ptp_pa_to_va(ptp,pdpt_pa); + if (!pdpt) return SH_STATUS_INVALID_INTERNAL_PA; + sh_mem_set_8((sh_uint8*)pdpt,0,SH_PAGE_SIZE); + pml4[pml4_i]=pdpt_pa | SH_PAGE_TABLE_FLAGS | SH_PAGE_PRESENT; + } else { + pdpt=sh_page_ptp_pa_to_va(ptp,(pml4[pml4_i] & ~0xFFFULL)); + if (!pdpt) return SH_STATUS_INVALID_INTERNAL_PA; + } + if (!(pdpt[pdpt_i] & SH_PAGE_PRESENT)) { + sh_page_PHYSICAL_ADRESS pd_pa=sh_page_ptp_alloc_one_page(ptp); + if (!pd_pa) return SH_STATUS_OUT_OF_MEMORY; + pd=sh_page_ptp_pa_to_va(ptp,pd_pa); + if (!pd) return SH_STATUS_INVALID_INTERNAL_PA; + sh_mem_set_8((sh_uint8*)pd,0,SH_PAGE_SIZE); + pdpt[pdpt_i]=pd_pa | SH_PAGE_TABLE_FLAGS | SH_PAGE_PRESENT; + } else { + pd=sh_page_ptp_pa_to_va(ptp,(pdpt[pdpt_i] & ~0xFFFULL)); + if (!pd) return SH_STATUS_INVALID_INTERNAL_PA; + } + if (!(pd[pd_i] & SH_PAGE_PRESENT)) { + sh_page_PHYSICAL_ADRESS pt_pa=sh_page_ptp_alloc_one_page(ptp); + if (!pt_pa) return SH_STATUS_OUT_OF_MEMORY; + pt=sh_page_ptp_pa_to_va(ptp,pt_pa); + if (!pt) return SH_STATUS_INVALID_INTERNAL_PA; + sh_mem_set_8((sh_uint8*)pt,0,SH_PAGE_SIZE); + pd[pd_i]=pt_pa | SH_PAGE_TABLE_FLAGS | SH_PAGE_PRESENT; + } else { + pt=sh_page_ptp_pa_to_va(ptp,pd[pd_i] & ~0xFFFULL); + if (!pt) return SH_STATUS_INVALID_INTERNAL_PA; + } + pt[pt_i]=(pa & ~0xFFFULL) | flags | SH_PAGE_PRESENT; + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_page_is_va_mapped_ptp(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADRESS va) { + if (ptp==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER; + sh_uint64 pml4_i=(va>>39) & 0x1FF; + sh_uint64 pdpt_i=(va>>30) & 0x1FF; + sh_uint64 pd_i=(va>>21) & 0x1FF; + sh_uint64 pt_i=(va>>12) & 0x1FF; + sh_uint64 *pdpt; + sh_uint64 *pd; + sh_uint64 *pt; + sh_uint64 *pml4=(sh_uint64*)ptp->page_table_va; + if (!(pml4[pml4_i] & SH_PAGE_PRESENT)) { + return SH_STATUS_VA_NOT_MAPPED; + } else { + pdpt=sh_page_ptp_pa_to_va(ptp,(pml4[pml4_i] & ~0xFFFULL)); + if (pdpt==0) return SH_STATUS_INVALID_INTERNAL_PA; + } + if (!(pdpt[pdpt_i] & SH_PAGE_PRESENT)) { + return SH_STATUS_VA_NOT_MAPPED; + } else { + pd=sh_page_ptp_pa_to_va(ptp,(pdpt[pdpt_i] & ~0xFFFULL)); + if (pd==0) return SH_STATUS_INVALID_INTERNAL_PA; + } + if (!(pd[pd_i] & SH_PAGE_PRESENT)) { + return SH_STATUS_VA_NOT_MAPPED; + } else { + pt=sh_page_ptp_pa_to_va(ptp,(pd[pd_i] & ~0xFFFULL)); + if (pt==0) return SH_STATUS_INVALID_INTERNAL_PA; + } + if (!(pt[pt_i] & SH_PAGE_PRESENT)) { + return SH_STATUS_VA_NOT_MAPPED; + } else { + return SH_STATUS_VA_MAPPED; + } +} +SH_STATUS sh_page_is_va_range_mapped_ptp(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADRESS va,sh_uint64 size_bytes) { + if (ptp==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER; + if (va%SH_PAGE_SIZE!=0 || size_bytes%SH_PAGE_SIZE!=0 || size_bytes==0) return SH_STATUS_INVALID_PARAMETER; + sh_uint64 counter=0; + for (sh_uint64 i=0;i>39) & 0x1FF; + sh_uint64 pdpt_i=(va>>30) & 0x1FF; + sh_uint64 pd_i=(va>>21) & 0x1FF; + sh_uint64 pt_i=(va>>12) & 0x1FF; + sh_uint64 *pdpt; + sh_uint64 *pd; + sh_uint64 *pt; + sh_uint64 *pml4=(sh_uint64*)ptp->page_table_va; + if (!(pml4[pml4_i] & SH_PAGE_PRESENT)) { + return SH_STATUS_ERROR_VA_NOT_MAPPED; + } else { + pdpt=sh_page_ptp_pa_to_va(ptp,(pml4[pml4_i] & ~0xFFFULL)); + if (!pdpt) return SH_STATUS_INVALID_INTERNAL_PA; + } + if (!(pdpt[pdpt_i] & SH_PAGE_PRESENT)) { + return SH_STATUS_ERROR_VA_NOT_MAPPED; + } else { + pd=sh_page_ptp_pa_to_va(ptp,(pdpt[pdpt_i] & ~0xFFFULL)); + if (!pd) return SH_STATUS_INVALID_INTERNAL_PA; + } + if (!(pd[pd_i] & SH_PAGE_PRESENT)) { + return SH_STATUS_ERROR_VA_NOT_MAPPED; + } else { + pt=sh_page_ptp_pa_to_va(ptp,pd[pd_i] & ~0xFFFULL); + if (!pt) return SH_STATUS_INVALID_INTERNAL_PA; + } + pt[pt_i]=0x0ULL; + __asm__ volatile("invlpg (%0)" :: "r"(va) : "memory"); + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_page_unmap_contiguous_pages_range_ptp(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADRESS va,sh_uint64 size_bytes) { + if (ptp==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER; + if (va%SH_PAGE_SIZE!=0 || size_bytes==0 || size_bytes%SH_PAGE_SIZE!=0) return SH_STATUS_INVALID_PARAMETER; + sh_uint64 pages=size_bytes/SH_PAGE_SIZE; + SH_STATUS status=sh_page_is_va_range_mapped_ptp(ptp,va,size_bytes); + if (status==SH_STATUS_VA_PARTIALLY_MAPPED) return SH_STATUS_ERROR_VA_PARTIALLY_MAPPED; + if (status==SH_STATUS_VA_NOT_MAPPED) return SH_STATUS_ERROR_VA_NOT_MAPPED; + for (sh_uint64 i=0;i>39) & 0x1FF; + sh_uint64 pdpt_i=(va>>30) & 0x1FF; + sh_uint64 pd_i=(va>>21) & 0x1FF; + sh_uint64 pt_i=(va>>12) & 0x1FF; + sh_uint64 *pdpt; + sh_uint64 *pd; + sh_uint64 *pt; + sh_uint64 *pml4=(sh_uint64*)ptp->page_table_va; + if (!(pml4[pml4_i] & SH_PAGE_PRESENT)) { + return SH_STATUS_ERROR_VA_NOT_MAPPED; + } else { + pdpt=sh_page_ptp_pa_to_va(ptp,(pml4[pml4_i] & ~0xFFFULL)); + if (!pdpt) return SH_STATUS_INVALID_INTERNAL_PA; + } + if (!(pdpt[pdpt_i] & SH_PAGE_PRESENT)) { + return SH_STATUS_ERROR_VA_NOT_MAPPED; + } else { + pd=sh_page_ptp_pa_to_va(ptp,(pdpt[pdpt_i] & ~0xFFFULL)); + if (!pd) return SH_STATUS_INVALID_INTERNAL_PA; + } + if (!(pd[pd_i] & SH_PAGE_PRESENT)) { + return SH_STATUS_ERROR_VA_NOT_MAPPED; + } else { + pt=sh_page_ptp_pa_to_va(ptp,pd[pd_i] & ~0xFFFULL); + if (!pt) return SH_STATUS_INVALID_INTERNAL_PA; + } + if (!(pt[pt_i] & SH_PAGE_PRESENT)) return SH_STATUS_ERROR_VA_NOT_MAPPED; + *pa=pt[pt_i] & 0x000FFFFFFFFFF000; + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_page_unalloc_one_page(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADRESS va) { + if (ptp==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER; + if (va%SH_PAGE_SIZE!=0) return SH_STATUS_INVALID_PARAMETER; + sh_page_PHYSICAL_ADRESS equivalent_pa; + SH_STATUS status=sh_page_ptp_va_to_pa(ptp,va,&equivalent_pa); + if (status!=SH_STATUS_SUCCESS) return status; + status=sh_page_unmap_one_page_ptp(ptp,va); // If this call return SH_STATUS_ERROR_VA_NOT_MAPPED, there is a severe bug that should cause kernel panic because sh_page_ptp_va_to_pa should already have returned exact same error code. + if (status!=SH_STATUS_SUCCESS) return status; + status=sh_page_set_pages_range_bitmap(physical_bitmap,physical_memory_pages_count,(sh_uint64)(equivalent_pa/SH_PAGE_SIZE),1,SH_FALSE); + if (status!=SH_STATUS_SUCCESS) return status; + return SH_STATUS_SUCCESS; +} +SH_STATUS sh_page_unalloc_contiguous(sh_page_PAGE_TABLE_POOL *ptp,sh_page_VIRTUAL_ADRESS va,sh_uint64 size_bytes) { + if (ptp==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER; + if (va%SH_PAGE_SIZE!=0 || size_bytes==0 || size_bytes%SH_PAGE_SIZE!=0) return SH_STATUS_INVALID_PARAMETER; + SH_STATUS status=sh_page_is_va_range_mapped_ptp(ptp,va,size_bytes); + if (status==SH_STATUS_VA_NOT_MAPPED) return SH_STATUS_ERROR_VA_NOT_MAPPED; + if (status==SH_STATUS_VA_PARTIALLY_MAPPED) return SH_STATUS_ERROR_VA_PARTIALLY_MAPPED; + sh_uint64 pages=size_bytes/SH_PAGE_SIZE; + for (sh_uint64 i=0;ientry_count;i++) { + sh_uint64 start_page=memory_map_cursor[i].physical_start/4096; + sh_uint64 end_page=start_page+memory_map_cursor[i].pages_count; + if (memory_map_cursor[i].type==SH_PAGE_CONVENTIONAL_MEMORY && memory_map_cursor[i].pages_count>biggest_segment_pages) { + biggest_segment_pages=memory_map_cursor[i].pages_count; + biggest_segment_index=i; + } + if (verbose) { + sh_log_ldebug("Found memory map segment #",SH_LOG_SOURCE_PAGE); + sh_log_send_uintn(i); + sh_log_send_string(": [0x"); + sh_log_send_uintn_hex(start_page*4096); + sh_log_send_string(" - 0x"); + sh_log_send_uintn_hex(end_page*4096); + sh_log_send_string("] Memory type: "); + sh_log_send_uintn(memory_map_cursor[i].type); + if (memory_map_cursor[i].type==SH_PAGE_CONVENTIONAL_MEMORY) { + sh_log_send_string(" --> usable\n"); + } else { + sh_log_send_string(" --> not usable\n"); + } + if (!(end_page<=SH_PAGE_MAX_PAGES_COUNT)) { + sh_log_lwarning("Memory map segment #",SH_LOG_SOURCE_PAGE); + sh_log_send_uintn(i); + sh_log_send_string(" isn't usable because it overflow over max page count. Enable debug log channel to see more.\n"); + } + } + if (memory_map_cursor[i].type==SH_PAGE_CONVENTIONAL_MEMORY && end_page<=SH_PAGE_MAX_PAGES_COUNT) { + if (end_page>highest_usable_page) { + highest_usable_segment=i; + highest_usable_page=end_page; + } + } + } + physical_memory_pages_count=highest_usable_page; + physical_memory_bytes_count=physical_memory_pages_count*SH_PAGE_SIZE; + if (verbose) { + sh_log_ldebug("Total memory was given by memory map segment #",SH_LOG_SOURCE_PAGE); + sh_log_send_uintn(highest_usable_segment); + sh_log_send_string("\n"); + sh_log_ldebug("Total memory (pages): 0x",SH_LOG_SOURCE_PAGE); + sh_log_send_uintn_hex(physical_memory_pages_count); + sh_log_send_string(". Total memory (bytes) : 0x"); + sh_log_send_uintn_hex(physical_memory_bytes_count); + sh_log_send_string("\n"); + } + if (biggest_segment_pages==0) { + sh_log_error("No suitable conventional memory segment found.",SH_LOG_SOURCE_PAGE); + return SH_STATUS_OUT_OF_MEMORY; + } + if (memory_map_cursor[biggest_segment_index].pages_count<(physical_memory_pages_count/8)) { + sh_log_error("Memory is too low or too fragmented to allocate physical bitmap.",SH_LOG_SOURCE_PAGE); + return SH_STATUS_OUT_OF_MEMORY; + } + sh_page_PHYSICAL_ADRESS pa=memory_map_cursor[biggest_segment_index].physical_start; + sh_page_VIRTUAL_ADRESS va; + physical_bitmap_size_bytes=physical_memory_pages_count/8; + if (physical_memory_pages_count%8!=0) physical_bitmap_size_bytes++; + physical_bitmap_size_pages=physical_bitmap_size_bytes/SH_PAGE_SIZE; + if (physical_bitmap_size_bytes%SH_PAGE_SIZE!=0) physical_bitmap_size_pages++; + SH_STATUS status=sh_page_search_available_va_range(ptp,SH_PAGE_KERNEL_PERM_VA_BASE,(SH_PAGE_KERNEL_PERM_VA_END-SH_PAGE_KERNEL_PERM_VA_BASE+1-0x1000),physical_bitmap_size_pages*SH_PAGE_SIZE,&va); + if (status!=SH_STATUS_SUCCESS) { + sh_log_error("Memory is too low or too fragmented to allocate physical bitmap.",SH_LOG_SOURCE_PAGE); + return status; + } + status=sh_page_map_contiguous_pages_range_ptp(ptp,va,pa,SH_PAGE_PRESENT | SH_PAGE_NX | SH_PAGE_RW,physical_bitmap_size_pages*SH_PAGE_SIZE); + if (status==SH_STATUS_OUT_OF_MEMORY) { + sh_log_error("Memory is too low or too fragmented to allocate physical bitmap.",SH_LOG_SOURCE_PAGE); + return status; + } else if (status!=SH_STATUS_SUCCESS) { + sh_log_error("An unknow error happened during physical bitmap pages mapping. See error below",SH_LOG_SOURCE_PAGE); + return status; + } + physical_bitmap=(sh_uint8*)va; + status=sh_mem_set_8(physical_bitmap,0xFF,physical_bitmap_size_bytes); + if (sh_status_error(status)) { + sh_log_error("An unknow error happened during physical bitmap filling with 0xFF. See error below.",SH_LOG_SOURCE_PAGE); + return status; + } + // second loop : actually set all free regions into physical bitmap + for (sh_uint64 i=0;ientry_count;i++) { + sh_uint64 start_page=memory_map_cursor[i].physical_start/4096; + sh_uint64 end_page=start_page+memory_map_cursor[i].pages_count; + if (end_page<=SH_PAGE_MAX_PAGES_COUNT) { + if (memory_map_cursor[i].type==SH_PAGE_CONVENTIONAL_MEMORY) { + SH_STATUS status=sh_page_set_pages_range_bitmap(physical_bitmap,physical_memory_pages_count,memory_map_cursor[i].physical_start/SH_PAGE_SIZE,memory_map_cursor[i].pages_count,SH_FALSE); + if (sh_status_error(status)) { + sh_log_error("Couldn't set this memory map segment to usable.",SH_LOG_SOURCE_PAGE); + return SH_STATUS_PMAP_NO_PAGES_SET; + } + } + } + } + sh_page_set_pages_range_bitmap(physical_bitmap,physical_memory_pages_count,pa/SH_PAGE_SIZE,physical_bitmap_size_pages,SH_TRUE); + return SH_STATUS_SUCCESS; +} +sh_page_VIRTUAL_ADRESS sh_page_get_physical_bitmap_ptr() { + return (sh_page_VIRTUAL_ADRESS)physical_bitmap; +} +static sh_uint64 popcount64(sh_uint64 x) { + x=x-((x>>1) & 0x5555555555555555ULL); + x=(x & 0x3333333333333333ULL)+((x>>2) & 0x3333333333333333ULL); + x=(x+(x>>4)) & 0x0F0F0F0F0F0F0F0FULL; + x=x+(x>>8); + x=x+(x>>16); + x=x+(x>>32); + return x & 0x7F; +} +SH_STATUS sh_page_get_memory_stats(sh_page_MEM_STATS *mem_stats) { + if (mem_stats==SH_NULLPTR) return SH_STATUS_INVALID_PARAMETER; + mem_stats->memory_total_pages=physical_memory_pages_count; + mem_stats->memory_total_bytes=physical_memory_bytes_count; + sh_uint64 free_pages=0; + sh_uint64 used_pages=0; + sh_uint64 largest_free_block=0; + sh_uint64 largest_used_block=0; + sh_uint64 free_blocks_count=0; + sh_uint64 used_blocks_count=0; + sh_uint64 current_free_block=0; + sh_uint64 current_used_block=0; + sh_uint64 full_uint64_count=physical_memory_pages_count/64; + sh_uint64 remaining_bits=physical_memory_pages_count%64; + sh_uint64 *bitmap64=(sh_uint64*)physical_bitmap; + for (sh_uint64 i=0;i>b) & 1; + if (bit_set) { + current_used_block++; + if (current_free_block) { + free_blocks_count++; + if (current_free_block>largest_free_block) { + largest_free_block=current_free_block; + } + current_free_block=0; + } + } else { + current_free_block++; + if (current_used_block) { + used_blocks_count++; + if (current_used_block>largest_used_block) { + largest_used_block=current_used_block; + } + current_used_block=0; + } + } + } + } + if (remaining_bits) { + sh_uint64 val=bitmap64[full_uint64_count] & ((1ULL<>b) & 1; + if (bit_set) { + current_used_block++; + if (current_free_block) { + free_blocks_count++; + if (current_free_block>largest_free_block) { + largest_free_block=current_free_block; + } + current_free_block=0; + } + } else { + current_free_block++; + if (current_used_block) { + used_blocks_count++; + if (current_used_block>largest_used_block) { + largest_used_block=current_used_block; + } + current_used_block=0; + } + } + } + } + if (current_free_block) { + free_blocks_count++; + if (current_free_block>largest_free_block) { + largest_free_block=current_free_block; + } + } + if (current_used_block) { + used_blocks_count++; + if (current_used_block>largest_used_block) { + largest_used_block=current_used_block; + } + } + mem_stats->free_pages=free_pages; + mem_stats->used_pages=used_pages; + mem_stats->free_ratio=(double)free_pages/(double)physical_memory_pages_count; + mem_stats->used_ratio=(double)used_pages/(double)physical_memory_pages_count; + mem_stats->largest_free_block=largest_free_block; + mem_stats->largest_used_block=largest_used_block; + mem_stats->free_blocks_count=free_blocks_count; + mem_stats->used_blocks_count=used_blocks_count; + mem_stats->physical_bitmap_size_bytes=(physical_memory_pages_count+7)/8; + mem_stats->physical_bitmap_size_pages=(mem_stats->physical_bitmap_size_bytes+4095)/4096; + return SH_STATUS_SUCCESS; +} diff --git a/test.c.ccc b/test.c.ccc deleted file mode 100644 index 0523c48..0000000 Binary files a/test.c.ccc and /dev/null differ