Created
July 30, 2020 07:17
-
-
Save caisan/47e9c49f530a88fb2741134978cf9c99 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ===================================================================================== | |
// | |
// Filename: qemu phyaddr section.c | |
// | |
// Description: | |
// | |
// Version: 1.0 | |
// Created: 2020/07/29 20时18分30秒 | |
// Revision: none | |
// Compiler: g++ | |
// ===================================================================================== | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
#include <string.h> | |
#define CAI ((uint32_t)~0) | |
void printBits(size_t const size, void const * const ptr) | |
{ | |
unsigned char *b = (unsigned char*) ptr; | |
unsigned char byte; | |
int i, j; | |
for (i=size-1;i>=0;i--) | |
{ | |
for (j=7;j>=0;j--) | |
{ | |
byte = (b[i] >> j) & 1; | |
printf("%u", byte); | |
} | |
} | |
puts(""); | |
} | |
#define P_L2_BITS 9 | |
#define P_L2_SIZE (1 << P_L2_BITS) //512 | |
#define PHYS_SECTION_UNASSIGNED 0 | |
#define PHYS_MAP_NODE_NIL (((uint32_t)~0) >> 6) | |
#define ADDR_SPACE_BITS 64 | |
#define TARGET_PAGE_BITS 12 | |
#define P_L2_LEVELS (((ADDR_SPACE_BITS - TARGET_PAGE_BITS - 1) / P_L2_BITS) + 1) | |
/* | |
#define g_renew(struct_type, mem, n_structs) _G_RENEW (struct_type, mem, n_structs, realloc) | |
#define _G_RENEW(struct_type, mem, n_structs, func) \ | |
((struct_type *) g_##func##_n (mem, (n_structs), sizeof (struct_type))) | |
*/ | |
typedef uint64_t hwaddr; | |
typedef struct PhysPageEntry PhysPageEntry; | |
struct PhysPageEntry { | |
uint32_t skip : 6; | |
uint32_t ptr : 26; | |
}; | |
typedef PhysPageEntry Node[P_L2_SIZE]; | |
typedef struct PhysPageMap { | |
// struct rcu_head rcu; | |
unsigned sections_nb; | |
unsigned sections_nb_alloc; | |
unsigned nodes_nb; | |
unsigned nodes_nb_alloc; | |
Node *nodes; | |
// MemoryRegionSection *sections; | |
} PhysPageMap; | |
static void phys_map_node_reserve(PhysPageMap *map, unsigned nodes) | |
{ | |
static unsigned alloc_hint = 16; | |
if(map->nodes_nb+nodes > map->nodes_nb_alloc) { | |
// map->nodes = g_renew(Node, map->nodes, map->nodes_nb_alloc); | |
map->nodes = realloc(map->nodes, map->nodes_nb_alloc*sizeof(Node)); | |
} | |
} | |
static uint32_t phys_map_node_alloc(PhysPageMap *map, bool leaf) | |
{ | |
unsigned i; | |
uint32_t ret; | |
PhysPageEntry e, *p; | |
ret = map->nodes_nb++; | |
p = map->nodes[ret]; | |
e.skip = leaf ? 0 : 1; | |
e.ptr = leaf ? PHYS_SECTION_UNASSIGNED : PHYS_MAP_NODE_NIL; | |
for (i = 0; i < P_L2_SIZE; ++i) | |
{ | |
memcpy(&p[i], &e, sizeof(e)); | |
} | |
return ret; | |
} | |
static void phys_page_set_level(PhysPageMap *map, PhysPageEntry *lp, | |
hwaddr *index, hwaddr *nb, uint16_t leaf, int level) | |
{ | |
PhysPageEntry *p; | |
hwaddr step = (hwaddr)1 << (level * P_L2_BITS); | |
if (lp->skip && lp->ptr == PHYS_MAP_NODE_NIL) | |
{ | |
lp->ptr = phys_map_node_alloc(map, level == 0); | |
} | |
p = map->nodes[lp->ptr]; | |
lp = &p[(*index >> (level * P_L2_BITS)) & (P_L2_SIZE - 1)]; | |
while (*nb && lp < &p[P_L2_SIZE]) | |
{ | |
if ((*index & (step - 1)) == 0 && *nb >= step) { | |
lp->skip = 0; | |
lp->ptr = leaf; | |
*index += step; | |
*nb -= step; | |
}else { | |
phys_page_set_level(map, lp, index, nb, leaf, level - 1); | |
} | |
++lp; | |
} | |
} | |
int main() | |
{ | |
PhysPageEntry phys_map = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .skip = 1 }; | |
PhysPageMap *map = NULL; | |
map = (struct PhysPageMap*)malloc(sizeof(struct PhysPageMap)); | |
phys_map_node_reserve(map, 3 * P_L2_LEVELS); | |
hwaddr start_addr = 65535; | |
hwaddr index = start_addr >> TARGET_PAGE_BITS; | |
printf("%llu", index); | |
uint64_t num_pages = 512; | |
uint16_t section_index = 0; | |
uint16_t leaf = section_index; | |
phys_page_set_level(map, &phys_map,&index, &num_pages, leaf, P_L2_LEVELS - 1 ); | |
return 0; | |
} | |
int main_test(int argv, char* argc[]) | |
{ | |
int i = PHYS_MAP_NODE_NIL; | |
// printBits(sizeof(i), &i); | |
printf("%d\n", P_L2_SIZE); | |
int level = 5; | |
int r = level * P_L2_BITS & (P_L2_SIZE - 1); | |
printf("%d\n",r ); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment