Skip to content

Instantly share code, notes, and snippets.

@caisan
Created July 30, 2020 07:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save caisan/47e9c49f530a88fb2741134978cf9c99 to your computer and use it in GitHub Desktop.
Save caisan/47e9c49f530a88fb2741134978cf9c99 to your computer and use it in GitHub Desktop.
// =====================================================================================
//
// 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