2283 lines
41 KiB
C
2283 lines
41 KiB
C
|
|
/**
|
||
|
|
* @file cli.c
|
||
|
|
*
|
||
|
|
* @brief cli code file for memory management library
|
||
|
|
*
|
||
|
|
* @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved.
|
||
|
|
*
|
||
|
|
* @date Jul 2024
|
||
|
|
* @author Barrett Edwards <code@jrlabs.io>
|
||
|
|
*
|
||
|
|
*/
|
||
|
|
|
||
|
|
/* INCLUDES ==================================================================*/
|
||
|
|
|
||
|
|
/* printf()
|
||
|
|
* fprintf()
|
||
|
|
* stderr
|
||
|
|
*/
|
||
|
|
#include <stdio.h>
|
||
|
|
|
||
|
|
/* atoi()
|
||
|
|
* calloc()
|
||
|
|
* free()
|
||
|
|
*/
|
||
|
|
#include <stdlib.h>
|
||
|
|
|
||
|
|
/* strcmp()
|
||
|
|
*/
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
/* errno MACROS
|
||
|
|
*/
|
||
|
|
#include <errno.h>
|
||
|
|
|
||
|
|
/* CLI_LOG_LEVEL
|
||
|
|
*/
|
||
|
|
#include <sys/syslog.h>
|
||
|
|
|
||
|
|
/* cxl_new()
|
||
|
|
* cxl_region
|
||
|
|
* cxl_memdev
|
||
|
|
* cxl_decoder
|
||
|
|
*/
|
||
|
|
#include <cxl/libcxl.h>
|
||
|
|
|
||
|
|
#include "options.h"
|
||
|
|
|
||
|
|
#include "libmem.h"
|
||
|
|
|
||
|
|
/* MACROS ====================================================================*/
|
||
|
|
|
||
|
|
#define CLI_LOG_LEVEL LOG_DEBUG
|
||
|
|
#define CLI_LOG_DST LMLD_SYSLOG
|
||
|
|
#define CLI_IG 4096
|
||
|
|
|
||
|
|
/* ENUMERATIONS ==============================================================*/
|
||
|
|
|
||
|
|
/* STRUCTS ===================================================================*/
|
||
|
|
|
||
|
|
struct cli_arg
|
||
|
|
{
|
||
|
|
char *name;
|
||
|
|
char *args;
|
||
|
|
char *help;
|
||
|
|
int (*fn)(int argc, char **argv);
|
||
|
|
};
|
||
|
|
|
||
|
|
/* PROTOTYPES ================================================================*/
|
||
|
|
|
||
|
|
int cmd_blk_offline(int num, int start);
|
||
|
|
int cmd_blk_online(int num, int start);
|
||
|
|
|
||
|
|
int cmd_info();
|
||
|
|
int cmd_list(int online, int offline, char *region_name);
|
||
|
|
|
||
|
|
int cmd_region_create(int granularity, int num, char **names);
|
||
|
|
int cmd_region_delete(char *name);
|
||
|
|
int cmd_region_disable(char *name);
|
||
|
|
int cmd_region_enable(char *name);
|
||
|
|
int cmd_region_daxmode(char *name);
|
||
|
|
int cmd_region_rammode(char *name);
|
||
|
|
int cmd_region_set_blk_state(char *name, int offset, int state);
|
||
|
|
|
||
|
|
int cmd_set_blk_state(int index, int state);
|
||
|
|
int cmd_set_system_policy(int policy);
|
||
|
|
|
||
|
|
int cmd_show_blk_device(int id);
|
||
|
|
int cmd_show_blk_isonline(int id);
|
||
|
|
int cmd_show_blk_isremovable(int id);
|
||
|
|
int cmd_show_blk_node(int id);
|
||
|
|
int cmd_show_blk_state(int id);
|
||
|
|
int cmd_show_blk_zones(int id);
|
||
|
|
|
||
|
|
int cmd_show_blocks(int online, int offline, char *region_name);
|
||
|
|
|
||
|
|
int cmd_show_capacity(int online, int offline, char *region_name, int human);
|
||
|
|
|
||
|
|
int cmd_show_memdev_interleave_granulariy(char *name); //todo
|
||
|
|
int cmd_show_memdev_isavailable(char *name);
|
||
|
|
int cmd_show_memdevs(char *memdev_name, char *region_name, int human);
|
||
|
|
|
||
|
|
int cmd_show_num_blocks(int online, int offline, char *region_name);
|
||
|
|
int cmd_show_num_devices();
|
||
|
|
int cmd_show_num_regions();
|
||
|
|
|
||
|
|
int cmd_show_region_blk_state(char *name, int offset);
|
||
|
|
|
||
|
|
int cmd_show_region_isenabled(char *name);
|
||
|
|
|
||
|
|
int cmd_show_regions(char *name, int human);
|
||
|
|
|
||
|
|
int cmd_show_system_blocksize(int human);
|
||
|
|
int cmd_show_system_policy();
|
||
|
|
|
||
|
|
/* GLOBAL VARIABLES ==========================================================*/
|
||
|
|
|
||
|
|
/* FUNCTIONS =================================================================*/
|
||
|
|
|
||
|
|
int cmd_blk_offline(int num, int start)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Privileges
|
||
|
|
if ( getuid() != 0 )
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Command must be run as root\n");
|
||
|
|
rv = -EACCES;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
for ( int i = start ; i < (start + num) ; i++)
|
||
|
|
{
|
||
|
|
if (mem_blkid_is_online(ctx, i) == 1)
|
||
|
|
{
|
||
|
|
// Online a memory block
|
||
|
|
rv = mem_blkid_offline(ctx, i);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not offline memory block %d. %d\n", i, rv);
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_blk_online(int num, int start)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct mem_blk *blk;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Privileges
|
||
|
|
if ( getuid() != 0 )
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Command must be run as root\n");
|
||
|
|
rv = -EACCES;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
// Online all blocks
|
||
|
|
if (num < 0)
|
||
|
|
{
|
||
|
|
mem_blk_foreach(ctx, blk)
|
||
|
|
if (!mem_blk_is_online(blk))
|
||
|
|
mem_blk_online(blk);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
for ( int i = start ; i < (start + num) ; i++)
|
||
|
|
{
|
||
|
|
if (!mem_blkid_is_online(ctx, i))
|
||
|
|
{
|
||
|
|
// Online a memory block
|
||
|
|
rv = mem_blkid_online(ctx, i);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not online memory block %d. %d\n", i, rv);
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_info()
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
|
||
|
|
// Create mem context
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
printf("Memory Blocksize: %llu\n", mem_system_get_blocksize(ctx));
|
||
|
|
printf("Auto Online Memory Policy: %s\n", mem_lmpl(mem_system_get_policy(ctx)));
|
||
|
|
printf("Number of Blocks: %d\n", mem_system_num_blocks(ctx));
|
||
|
|
printf(" Number of Blocks online: %d\n", mem_system_num_blocks_online(ctx));
|
||
|
|
printf(" Number of Blocks offline: %d\n", mem_system_num_blocks_offline(ctx));
|
||
|
|
printf("Memory Capacity: %llu\n", mem_system_get_capacity(ctx));
|
||
|
|
printf(" Memory Capacity online: %llu\n", mem_system_get_capacity_online(ctx));
|
||
|
|
printf(" Memory Capacity offline: %llu\n", mem_system_get_capacity_offline(ctx));
|
||
|
|
printf("Number of CXL regions: %d\n", mem_num_regions(ctx));
|
||
|
|
printf("Number of CXL memdevs: %d\n", mem_num_memdevs(ctx));
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_list(int online, int offline, char *region_name)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_blk *blk;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_region *region;
|
||
|
|
unsigned long u;
|
||
|
|
|
||
|
|
// Initialize variables
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Get mem context
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
printf("Index node online cxl_region zones\n");
|
||
|
|
printf("----- ---- ------ ---------- -------------------\n");
|
||
|
|
|
||
|
|
mem_blk_foreach(ctx, blk)
|
||
|
|
{
|
||
|
|
if (online && !mem_blk_is_online(blk))
|
||
|
|
continue;
|
||
|
|
|
||
|
|
if (offline && mem_blk_is_online(blk))
|
||
|
|
continue;
|
||
|
|
|
||
|
|
region = mem_blk_get_region(blk);
|
||
|
|
|
||
|
|
if (region == NULL && region_name != NULL)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
if (region != NULL && region_name != NULL && strcmp(region_name, cxl_region_get_devname(region)) )
|
||
|
|
continue;
|
||
|
|
|
||
|
|
printf("%-5d %-4d %-6d ",
|
||
|
|
mem_blk_get_id(blk),
|
||
|
|
mem_blk_get_node(blk),
|
||
|
|
mem_blk_is_online(blk));
|
||
|
|
|
||
|
|
if (region != NULL)
|
||
|
|
printf("%-10s ", cxl_region_get_devname(region));
|
||
|
|
else
|
||
|
|
printf("%-10s ", "-");
|
||
|
|
|
||
|
|
// Print zones
|
||
|
|
u = mem_blk_get_zones(blk);
|
||
|
|
for ( int k = 0 ; k < LMZN_MAX ; k++)
|
||
|
|
{
|
||
|
|
if (u & (0x01 << k))
|
||
|
|
printf("%s ", mem_lmzn(k));
|
||
|
|
}
|
||
|
|
printf("\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
end:
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_region_create(int granularity, int num, char **names)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct cxl_memdev **memdevs;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
|
||
|
|
// Initialize variables
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Privileges
|
||
|
|
if ( getuid() != 0 )
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Command must be run as root\n");
|
||
|
|
rv = -EACCES;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (granularity == 0)
|
||
|
|
granularity = CLI_IG;
|
||
|
|
|
||
|
|
if (!(granularity == 256
|
||
|
|
|| granularity == 512
|
||
|
|
|| granularity == 1024
|
||
|
|
|| granularity == 2048
|
||
|
|
|| granularity == 4096
|
||
|
|
|| granularity == 8192))
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Invalid Interleave Granularity: %d\n", granularity);
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (num < 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing memdev[s]\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem context
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
// Use all memdevs
|
||
|
|
if (num == 0)
|
||
|
|
{
|
||
|
|
num = mem_num_memdevs(ctx);
|
||
|
|
memdevs = mem_get_memdevs(ctx);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// Allocate memory for the array of memdevs
|
||
|
|
memdevs = calloc(num, sizeof(*memdevs));
|
||
|
|
if (memdevs == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not allocate memory. %d - %s\n", errno, strerror(errno));
|
||
|
|
rv = -ENOMEM;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Loop through requested memory devices
|
||
|
|
for ( int i = 0 ; i < num ; i++ )
|
||
|
|
{
|
||
|
|
memdevs[i] = mem_get_memdev(ctx, names[i]);
|
||
|
|
if (memdevs[i] == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain memdev: %s\n", names[i]);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create the region
|
||
|
|
rv = mem_region_create(ctx, granularity, num, memdevs);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not create region: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
free(memdevs);
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_region_daxmode(char *name)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_region *region;
|
||
|
|
|
||
|
|
// Initialize variables
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Privileges
|
||
|
|
if ( getuid() != 0 )
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Command must be run as root\n");
|
||
|
|
rv = -EACCES;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (name == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing region\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem context
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
// Get region
|
||
|
|
region = mem_get_region(ctx, name);
|
||
|
|
if (region == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain region: %s\n", name);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Enable devdax mode
|
||
|
|
rv = mem_region_daxmode(ctx, region);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Enable of devdax mode failed: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_region_delete(char *name)
|
||
|
|
{
|
||
|
|
int rv, num;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_region *region, **regions;
|
||
|
|
|
||
|
|
// Initialize variables
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Privileges
|
||
|
|
if ( getuid() != 0 )
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Command must be run as root\n");
|
||
|
|
rv = -EACCES;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem context
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
// Delete all regions
|
||
|
|
if (name == NULL)
|
||
|
|
{
|
||
|
|
num = mem_num_regions(ctx);
|
||
|
|
regions = mem_get_regions(ctx);
|
||
|
|
char name[256];
|
||
|
|
|
||
|
|
for ( int i = 0 ; i < num ; i++)
|
||
|
|
{
|
||
|
|
// Delete region
|
||
|
|
strcpy(name, cxl_region_get_devname(regions[i]));
|
||
|
|
rv = mem_region_delete(ctx, regions[i]);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not delete region: %s\n", name);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// Get region
|
||
|
|
region = mem_get_region(ctx, name);
|
||
|
|
if (region == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain region: %s\n", name);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete region
|
||
|
|
rv = mem_region_delete(ctx, region);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not delete region: %s\n", name);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_region_disable(char *name)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_region *region;
|
||
|
|
|
||
|
|
// Initialize variables
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Privileges
|
||
|
|
if ( getuid() != 0 )
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Command must be run as root\n");
|
||
|
|
rv = -EACCES;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (name == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing region\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem context
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
// Get region
|
||
|
|
region = mem_get_region(ctx, name);
|
||
|
|
if (region == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain region: %s\n", name);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check if Region was enabled
|
||
|
|
rv = cxl_region_is_enabled(region);
|
||
|
|
if (rv == 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Region was already disabled\n");
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Disable Region
|
||
|
|
rv = cxl_region_disable(region);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not disable region: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_region_enable(char *name)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_region *region;
|
||
|
|
|
||
|
|
// Initialize variables
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Privileges
|
||
|
|
if ( getuid() != 0 )
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Command must be run as root\n");
|
||
|
|
rv = -EACCES;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (name == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing region\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem context
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
// Get the region
|
||
|
|
region = mem_get_region(ctx, name);
|
||
|
|
if (region == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain region: %s\n", name);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check if region is already enabled
|
||
|
|
rv = cxl_region_is_enabled(region);
|
||
|
|
if (rv == 1)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Region was already enabled\n");
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Enable the region
|
||
|
|
rv = cxl_region_enable(region);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not enable region: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_region_rammode(char *name)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_region *region;
|
||
|
|
|
||
|
|
// Initialize variables
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Privileges
|
||
|
|
if ( getuid() != 0 )
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Command must be run as root\n");
|
||
|
|
rv = -EACCES;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (name == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing region\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem context
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
// Get Region
|
||
|
|
region = mem_get_region(ctx, name);
|
||
|
|
if (region == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain region: %s\n", name);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Enable Ram mode
|
||
|
|
rv = mem_region_rammode(ctx, region);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Enable of systemram mode failed: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_region_set_blk_state(char *name, int offset, int state)
|
||
|
|
{
|
||
|
|
int rv, num;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_region *region;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Privileges
|
||
|
|
if ( getuid() != 0 )
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Command must be run as root\n");
|
||
|
|
rv = -EACCES;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (name == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing region\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (offset < -1)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Invalid index\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (state <0 || state >= LMPL_MAX)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Invalid state\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
region = mem_get_region(ctx, name);
|
||
|
|
if (region == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain region\n");
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (offset == -1)
|
||
|
|
{
|
||
|
|
num = mem_region_num_blocks(ctx, region);
|
||
|
|
for ( int i = 0 ; i < num ; i++)
|
||
|
|
{
|
||
|
|
// Set the state
|
||
|
|
rv = mem_region_set_blk_state(ctx, region, i, state);
|
||
|
|
if (rv < 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not set state of memory block %d in region %s: %d\n", i, cxl_region_get_devname(region), rv);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// Set the state
|
||
|
|
rv = mem_region_set_blk_state(ctx, region, offset, state);
|
||
|
|
if (rv < 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not set state of memory block %d in region %s: %d\n", offset, cxl_region_get_devname(region), rv);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_set_blk_state(int index, int state)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Privileges
|
||
|
|
if ( getuid() != 0 )
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Command must be run as root\n");
|
||
|
|
rv = -EACCES;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (index < 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Invalid index\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (state < 0 || state >= LMPL_MAX)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Invalid state\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
// Set the state
|
||
|
|
rv = mem_blkid_set_state(ctx, index, state);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not set state of memory block. %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_set_system_policy(int policy)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Privileges
|
||
|
|
if ( getuid() != 0 )
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Command must be run as root\n");
|
||
|
|
rv = -EACCES;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (policy < 0 || policy >= LMPL_MAX)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Inavlid policy\n");
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
// Set the policy
|
||
|
|
rv = mem_system_set_policy(ctx, policy);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not set policy. %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_blk_device(int id)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (id < 1)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing block index\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
// Get phys device
|
||
|
|
rv = mem_blkid_get_device(ctx, id);
|
||
|
|
if (rv < 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain phys_device. %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
printf("%d\n", rv);
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_blk_isonline(int id)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct mem_blk *blk;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (id < 1)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing block index\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
// Check if memory block is online
|
||
|
|
rv = -1;
|
||
|
|
mem_blk_foreach(ctx, blk)
|
||
|
|
if (id == mem_blk_get_id(blk))
|
||
|
|
{
|
||
|
|
rv = mem_blk_is_online(blk);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
printf("%d\n", rv);
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_blk_isremovable(int id)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (id < 1)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing block index\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
rv = mem_blkid_is_removable(ctx, id);
|
||
|
|
printf("%d\n", rv);
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_blk_node(int id)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (id < 1)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing block index\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
rv = mem_blkid_get_node(ctx, id);
|
||
|
|
printf("%d\n", rv);
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_blk_state(int id)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (id < 1)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing block index\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
rv = mem_blkid_get_state(ctx, id);
|
||
|
|
if (rv < 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain block state: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
printf("%s\n", mem_lmpl(rv));
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_blk_zones(int id)
|
||
|
|
{
|
||
|
|
int i, rv;
|
||
|
|
unsigned long u;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (id < 1)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing block index\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
u = mem_blkid_get_zones(ctx, id);
|
||
|
|
|
||
|
|
for ( i = 0 ; i < LMZN_MAX ; i++ )
|
||
|
|
{
|
||
|
|
if ((0x01 << i) & u)
|
||
|
|
printf("%s ", mem_lmzn(i));
|
||
|
|
}
|
||
|
|
printf("\n");
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_blocks(int online, int offline, char *region_name)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct mem_blk *blk;
|
||
|
|
struct cxl_region *region;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
mem_blk_foreach(ctx, blk)
|
||
|
|
{
|
||
|
|
if (online && !mem_blk_is_online(blk))
|
||
|
|
continue;
|
||
|
|
|
||
|
|
if (offline && mem_blk_is_online(blk))
|
||
|
|
continue;
|
||
|
|
|
||
|
|
region = mem_blk_get_region(blk);
|
||
|
|
|
||
|
|
if (region_name != NULL && region == NULL)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
if (region_name != NULL && region != NULL && strcmp(region_name, cxl_region_get_devname(region)))
|
||
|
|
continue;
|
||
|
|
|
||
|
|
printf("%d\n", mem_blk_get_id(blk));
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_capacity(int online, int offline, char *region_name, int human)
|
||
|
|
{
|
||
|
|
unsigned long long size;
|
||
|
|
double d;
|
||
|
|
int i, rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_region *region;
|
||
|
|
|
||
|
|
i = 0;
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
if (region_name == NULL)
|
||
|
|
{
|
||
|
|
if (online)
|
||
|
|
size = mem_system_get_capacity_online(ctx);
|
||
|
|
else if (offline)
|
||
|
|
size = mem_system_get_capacity_offline(ctx);
|
||
|
|
else
|
||
|
|
size = mem_system_get_capacity(ctx);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
region = mem_get_region(ctx, region_name);
|
||
|
|
if (region == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain region: %s\n", region_name);
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (online)
|
||
|
|
size = mem_region_get_capacity_online(ctx, region);
|
||
|
|
else if (offline)
|
||
|
|
size = mem_region_get_capacity_offline(ctx, region);
|
||
|
|
else
|
||
|
|
size = mem_region_get_capacity(ctx, region);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (human)
|
||
|
|
{
|
||
|
|
char units[] = {' ', 'K', 'M', 'G', 'T'};
|
||
|
|
d = (double) size;
|
||
|
|
while ((d > 1024) && i++ < 5)
|
||
|
|
d /= 1024;
|
||
|
|
printf("%0.2f %c\n", d, units[i]);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
printf("%llu\n", size);
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_memdev_interleave_granulariy(char *name)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_memdev *memdev;
|
||
|
|
|
||
|
|
// Initialize variables
|
||
|
|
rv = 1;
|
||
|
|
ctx = NULL;
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (name == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing memdev\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem context
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
// Get memdev
|
||
|
|
memdev = mem_get_memdev(ctx, name);
|
||
|
|
if (memdev == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain memdev: %s\n", name);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = mem_memdev_get_interleave_granularity(ctx, memdev);
|
||
|
|
printf("%d\n", rv);
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_memdev_isavailable(char *name)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_memdev *memdev;
|
||
|
|
|
||
|
|
// Initialize variables
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (name == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing memdev\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem context
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
// Get memdev
|
||
|
|
memdev = mem_get_memdev(ctx, name);
|
||
|
|
if (memdev == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain memdev: %s\n", name);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = mem_memdev_is_available(ctx, memdev);
|
||
|
|
printf("%d\n", rv);
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_memdevs(char *memdev_name, char *region_name, int human)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_memdev *memdev;
|
||
|
|
struct cxl_endpoint *endpoint;
|
||
|
|
struct cxl_port *port;
|
||
|
|
struct cxl_decoder *decoder;
|
||
|
|
struct cxl_region *region;
|
||
|
|
int i, num;
|
||
|
|
struct cxl_memdev **array;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
i = 0;
|
||
|
|
array = NULL;
|
||
|
|
|
||
|
|
// Get mem context
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
// Get the number of memdevs
|
||
|
|
num = mem_num_memdevs(ctx);
|
||
|
|
|
||
|
|
if (opts[CLOP_NUM].set)
|
||
|
|
{
|
||
|
|
printf("%d\n", num);
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (num <= 0)
|
||
|
|
{
|
||
|
|
rv = 0;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get a sorted list of memdevs
|
||
|
|
array = mem_get_memdevs(ctx);
|
||
|
|
if (array == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain list of memdevs\n");
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
printf("Name Enabled Mode Size Host Endpoint Decoder Region FW Version\n");
|
||
|
|
printf("------ ------- ------ -------------- ------------ ----------- ----------- ------------ -------------------\n");
|
||
|
|
for ( i = 0 ; i < num ; i++)
|
||
|
|
{
|
||
|
|
memdev = array[i];
|
||
|
|
|
||
|
|
if (memdev_name != NULL && strcmp(memdev_name, cxl_memdev_get_devname(memdev)))
|
||
|
|
continue;
|
||
|
|
|
||
|
|
endpoint = cxl_memdev_get_endpoint(memdev);
|
||
|
|
port = cxl_endpoint_get_port(endpoint);
|
||
|
|
decoder = cxl_decoder_get_first(port);
|
||
|
|
region = cxl_decoder_get_region(decoder);
|
||
|
|
|
||
|
|
int mode = cxl_decoder_get_mode(decoder);
|
||
|
|
unsigned long long size = cxl_memdev_get_ram_size(memdev);
|
||
|
|
const char *host = cxl_memdev_get_host(memdev);
|
||
|
|
const char *reg_name = NULL;
|
||
|
|
|
||
|
|
if (region != NULL)
|
||
|
|
{
|
||
|
|
reg_name = cxl_region_get_devname(region);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
reg_name ="-";
|
||
|
|
|
||
|
|
if (region_name != NULL && strcmp(reg_name, region_name))
|
||
|
|
continue;
|
||
|
|
|
||
|
|
printf("%-6s %7d %6s ",
|
||
|
|
cxl_memdev_get_devname(memdev),
|
||
|
|
cxl_memdev_is_enabled(memdev),
|
||
|
|
cxl_decoder_mode_name(mode));
|
||
|
|
|
||
|
|
if (human)
|
||
|
|
{
|
||
|
|
char units[] = {' ', 'K', 'M', 'G', 'T'};
|
||
|
|
double d = (double) size;
|
||
|
|
int i = 0;
|
||
|
|
while ((d > 1024) && i++ < 5)
|
||
|
|
d /= 1024;
|
||
|
|
printf("%12.2f %c ", d, units[i]);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
printf("%14llu ", size);
|
||
|
|
|
||
|
|
printf("%12s %11s %11s %12s %-20s\n",
|
||
|
|
host,
|
||
|
|
cxl_endpoint_get_devname(endpoint),
|
||
|
|
cxl_decoder_get_devname(decoder),
|
||
|
|
reg_name,
|
||
|
|
cxl_memdev_get_firmware_verison(memdev)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Free the sorted array of memdevs
|
||
|
|
if (array != NULL)
|
||
|
|
free(array);
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_num_blocks(int online, int offline, char *region_name)
|
||
|
|
{
|
||
|
|
int rv, num;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_region *region;
|
||
|
|
|
||
|
|
// Initialize variables
|
||
|
|
num = 0;
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
if (region_name != NULL)
|
||
|
|
{
|
||
|
|
region = mem_get_region(ctx, region_name);
|
||
|
|
if (region == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain region: %s\n", region_name);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (online)
|
||
|
|
num = mem_region_num_blocks_online(ctx, region);
|
||
|
|
else if (offline)
|
||
|
|
num = mem_region_num_blocks_offline(ctx, region);
|
||
|
|
else
|
||
|
|
num = mem_region_num_blocks(ctx, region);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (online)
|
||
|
|
num = mem_system_num_blocks_online(ctx);
|
||
|
|
else if (offline)
|
||
|
|
num = mem_system_num_blocks_offline(ctx);
|
||
|
|
else
|
||
|
|
num = mem_system_num_blocks(ctx);
|
||
|
|
}
|
||
|
|
|
||
|
|
printf("%d\n", num);
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_num_blocks_offline()
|
||
|
|
{
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
int rv;
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
printf("%d\n", mem_system_num_blocks_offline(ctx));
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_num_blocks_online()
|
||
|
|
{
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
int rv;
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
printf("%d\n", mem_system_num_blocks_online(ctx));
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_num_devices()
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Get mem context
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
printf("%d\n", mem_num_memdevs(ctx));
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_num_regions()
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Get mem cntext
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
printf("%d\n", mem_num_regions(ctx));
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_region_blk_state(char *name, int offset)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_region *region;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (name == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing region\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (offset < 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing block index\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
region = mem_get_region(ctx, name);
|
||
|
|
if (region == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain region\n");
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = mem_region_get_blk_state(ctx, region, offset);
|
||
|
|
if (rv < 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain state of block %d in region %s: %d\n", offset, cxl_region_get_devname(region), rv);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
printf("%s\n", mem_lmpl(rv));
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_region_isenabled(char *name)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_region *region;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Validate Inputs
|
||
|
|
if (name == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Missing region\n");
|
||
|
|
rv = -EINVAL;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mem context
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
region = mem_get_region(ctx, name);
|
||
|
|
if (region == NULL)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Could not obtain region: %s\n", name);
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = cxl_region_is_enabled(region);
|
||
|
|
printf("%d\n", rv);
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_regions(char *name, int human)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
struct cxl_decoder *d;
|
||
|
|
struct cxl_region **regions, *region;
|
||
|
|
struct cxl_memdev *memdev;
|
||
|
|
int i, j, num, num_regions;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Get mem context
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
num_regions = mem_num_regions(ctx);
|
||
|
|
regions = mem_get_regions(ctx);
|
||
|
|
|
||
|
|
if (num_regions <= 0 || regions == NULL)
|
||
|
|
{
|
||
|
|
rv = 0;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
printf("Name Enabled Dax Mode Size Ways Granularity Num Blocks Blocks Online Devices\n");
|
||
|
|
printf("--------- ------- --- ------ -------------- ---- ----------- ---------- ------------- -------\n");
|
||
|
|
|
||
|
|
for ( i = 0 ; i < num_regions ; i++)
|
||
|
|
{
|
||
|
|
region = regions[i];
|
||
|
|
|
||
|
|
// Skip if a region name was provided and doesn't match this region name
|
||
|
|
if (name != NULL && strcmp(name, cxl_region_get_devname(region)))
|
||
|
|
continue;
|
||
|
|
|
||
|
|
printf("%-9s %7d %3d %6s ",
|
||
|
|
cxl_region_get_devname(region),
|
||
|
|
cxl_region_is_enabled(region),
|
||
|
|
mem_region_is_daxmode(ctx, region),
|
||
|
|
cxl_decoder_mode_name(cxl_region_get_mode(region)));
|
||
|
|
|
||
|
|
if (human)
|
||
|
|
{
|
||
|
|
char units[] = {' ', 'K', 'M', 'G', 'T'};
|
||
|
|
double d = (double) cxl_region_get_size(region);
|
||
|
|
int i = 0;
|
||
|
|
while ((d > 1024) && i++ < 5)
|
||
|
|
d /= 1024;
|
||
|
|
printf("%12.2f %c ", d, units[i]);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
printf("%14llu ", cxl_region_get_size(region));
|
||
|
|
|
||
|
|
printf("%4d %11d %10d %13d ",
|
||
|
|
cxl_region_get_interleave_ways(region),
|
||
|
|
cxl_region_get_interleave_granularity(region),
|
||
|
|
mem_region_num_blocks(ctx, region),
|
||
|
|
mem_region_num_blocks_online(ctx, region)
|
||
|
|
);
|
||
|
|
|
||
|
|
num = cxl_region_get_interleave_ways(region);
|
||
|
|
if (cxl_region_decode_is_committed(region))
|
||
|
|
{
|
||
|
|
for ( j = 0 ; j < num ; j++)
|
||
|
|
{
|
||
|
|
d = cxl_region_get_target_decoder(region, j);
|
||
|
|
if (d == NULL)
|
||
|
|
{
|
||
|
|
printf("%d:%s ", j, "-");
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
memdev = cxl_decoder_get_memdev(d);
|
||
|
|
if (memdev != NULL)
|
||
|
|
printf("%d:%s ", j, cxl_memdev_get_devname(memdev));
|
||
|
|
else
|
||
|
|
printf("%d:%s ", j, "-");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
printf(" -");
|
||
|
|
printf("\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_system_blocksize(int human)
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
unsigned long long size;
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
size = mem_system_get_blocksize(ctx);
|
||
|
|
|
||
|
|
if (human)
|
||
|
|
{
|
||
|
|
char units[] = {' ', 'K', 'M', 'G', 'T'};
|
||
|
|
double d = (double) size;
|
||
|
|
int i = 0;
|
||
|
|
while ((d > 1024) && i++ < 5)
|
||
|
|
d /= 1024;
|
||
|
|
printf("%0.2f %c\n", d, units[i]);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
printf("%llu\n", size);
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int cmd_show_system_policy()
|
||
|
|
{
|
||
|
|
struct mem_ctx *ctx;
|
||
|
|
int rv;
|
||
|
|
|
||
|
|
// Get mem contex
|
||
|
|
rv = mem_new(&ctx);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to obtain mem context: %d\n", rv);
|
||
|
|
rv = 1;
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
mem_log_set_destination(ctx, CLI_LOG_DST, NULL);
|
||
|
|
mem_log_set_priority(ctx, CLI_LOG_LEVEL);
|
||
|
|
|
||
|
|
rv = mem_system_get_policy(ctx);
|
||
|
|
printf("%s\n", mem_lmpl(rv));
|
||
|
|
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
mem_unref(ctx);
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int run()
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
switch(opts[CLOP_CMD].val)
|
||
|
|
{
|
||
|
|
case CLCM_INFO:
|
||
|
|
rv = cmd_info();
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_LIST:
|
||
|
|
rv = cmd_list(opts[CLOP_ONLINE].set, opts[CLOP_OFFLINE].set, opts[CLOP_REGION].str);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_BLOCK_ONLINE:
|
||
|
|
if (opts[CLOP_ALL].set)
|
||
|
|
rv = cmd_blk_online(-1, 0);
|
||
|
|
else if (opts[CLOP_BLOCK].num == 0)
|
||
|
|
rv = cmd_blk_online(1, opts[CLOP_BLOCK].val);
|
||
|
|
else if (opts[CLOP_BLOCK].num >= 0)
|
||
|
|
rv = cmd_blk_online(opts[CLOP_BLOCK].num, *((int*)opts[CLOP_BLOCK].buf));
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_BLOCK_OFFLINE:
|
||
|
|
if (opts[CLOP_BLOCK].num == 0)
|
||
|
|
rv = cmd_blk_offline(1, opts[CLOP_BLOCK].val);
|
||
|
|
else if (opts[CLOP_BLOCK].num > 0)
|
||
|
|
rv = cmd_blk_offline(opts[CLOP_BLOCK].num, *((int*)opts[CLOP_BLOCK].buf));
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_REGION_CREATE:
|
||
|
|
if (opts[CLOP_ALL].set)
|
||
|
|
rv = cmd_region_create(opts[CLOP_GRANULARITY].u32, 0, NULL);
|
||
|
|
else
|
||
|
|
rv = cmd_region_create(opts[CLOP_GRANULARITY].u32, opts[CLOP_DEVICE].num, (char**)opts[CLOP_DEVICE].buf);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_REGION_DAXMODE:
|
||
|
|
rv = cmd_region_daxmode(opts[CLOP_REGION].str);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_REGION_RAMMODE:
|
||
|
|
rv = cmd_region_rammode(opts[CLOP_REGION].str);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_REGION_DELETE:
|
||
|
|
if (opts[CLOP_ALL].set)
|
||
|
|
rv = cmd_region_delete(NULL);
|
||
|
|
else
|
||
|
|
rv = cmd_region_delete(opts[CLOP_REGION].str);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_REGION_DISABLE:
|
||
|
|
rv = cmd_region_disable(opts[CLOP_REGION].str);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_REGION_ENABLE:
|
||
|
|
rv = cmd_region_enable(opts[CLOP_REGION].str);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SET_BLOCK_STATE:
|
||
|
|
if (opts[CLOP_ALL].set && (opts[CLOP_ONLINE].set || opts[CLOP_MOVABLE].set))
|
||
|
|
rv = cmd_blk_online(-1, 0);
|
||
|
|
else if (opts[CLOP_ONLINE].set || opts[CLOP_MOVABLE].set)
|
||
|
|
rv = cmd_set_blk_state(opts[CLOP_BLOCK].val, LMPL_MOVABLE);
|
||
|
|
else if (opts[CLOP_KERNEL].set)
|
||
|
|
rv = cmd_set_blk_state(opts[CLOP_BLOCK].val, LMPL_KERNEL);
|
||
|
|
else
|
||
|
|
rv = cmd_set_blk_state(opts[CLOP_BLOCK].val, LMPL_OFFLINE);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SET_REGION_BLOCK_STATE:
|
||
|
|
{
|
||
|
|
int mode;
|
||
|
|
|
||
|
|
if (opts[CLOP_ONLINE].set || opts[CLOP_MOVABLE].set)
|
||
|
|
mode = LMPL_MOVABLE;
|
||
|
|
else if (opts[CLOP_KERNEL].set)
|
||
|
|
mode = LMPL_KERNEL;
|
||
|
|
else
|
||
|
|
mode = LMPL_OFFLINE;
|
||
|
|
|
||
|
|
if (opts[CLOP_BLOCK].num > 0)
|
||
|
|
{
|
||
|
|
rv = 0;
|
||
|
|
int start = *((int*)opts[CLOP_BLOCK].buf);
|
||
|
|
for (int i = 0 ; i < (int) opts[CLOP_BLOCK].num ; i++)
|
||
|
|
rv += cmd_region_set_blk_state(opts[CLOP_REGION].str, start+i, mode);
|
||
|
|
}
|
||
|
|
else if (opts[CLOP_ALL].set)
|
||
|
|
{
|
||
|
|
rv = cmd_region_set_blk_state(opts[CLOP_REGION].str, -1, mode);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
rv = cmd_region_set_blk_state(opts[CLOP_REGION].str, opts[CLOP_BLOCK].val, mode);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SET_SYSTEM_POLICY:
|
||
|
|
if (opts[CLOP_ONLINE].set)
|
||
|
|
rv = cmd_set_system_policy(LMPL_ONLINE);
|
||
|
|
else if (opts[CLOP_MOVABLE].set)
|
||
|
|
rv = cmd_set_system_policy(LMPL_MOVABLE);
|
||
|
|
else if (opts[CLOP_KERNEL].set)
|
||
|
|
rv = cmd_set_system_policy(LMPL_KERNEL);
|
||
|
|
else
|
||
|
|
rv = cmd_set_system_policy(LMPL_OFFLINE);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_BLK_ISONLINE:
|
||
|
|
rv = cmd_show_blk_isonline(opts[CLOP_BLOCK].val);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_BLK_ISREMOVABLE:
|
||
|
|
rv = cmd_show_blk_isremovable(opts[CLOP_BLOCK].val);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_BLK_NODE:
|
||
|
|
rv = cmd_show_blk_node(opts[CLOP_BLOCK].val);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_BLK_PHYSDEVICE:
|
||
|
|
rv = cmd_show_blk_node(opts[CLOP_BLOCK].val);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_BLK_STATE:
|
||
|
|
if (opts[CLOP_REGION].set)
|
||
|
|
rv = cmd_show_region_blk_state(opts[CLOP_REGION].str, opts[CLOP_BLOCK].val);
|
||
|
|
else
|
||
|
|
rv = cmd_show_blk_state(opts[CLOP_BLOCK].val);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_BLK_ZONES:
|
||
|
|
rv = cmd_show_blk_zones(opts[CLOP_BLOCK].val);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_BLOCKS:
|
||
|
|
rv = cmd_show_blocks(opts[CLOP_ONLINE].set, opts[CLOP_OFFLINE].set, opts[CLOP_REGION].str);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_CAPACITY:
|
||
|
|
rv = cmd_show_capacity(opts[CLOP_ONLINE].set, opts[CLOP_OFFLINE].set, opts[CLOP_REGION].str, opts[CLOP_HUMAN].set);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_DEVICES:
|
||
|
|
rv = cmd_show_memdevs(opts[CLOP_DEVICE].str, opts[CLOP_REGION].str, opts[CLOP_HUMAN].set);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_DEVICE_ISAVAILABLE:
|
||
|
|
rv = cmd_show_memdev_isavailable(opts[CLOP_DEVICE].str);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_DEVICE_INTERLEAVE_GRANULARITY:
|
||
|
|
rv = cmd_show_memdev_interleave_granulariy(opts[CLOP_DEVICE].str);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_REGIONS:
|
||
|
|
rv = cmd_show_regions(opts[CLOP_REGION].str, opts[CLOP_HUMAN].set);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_NUM_BLOCKS:
|
||
|
|
rv = cmd_show_num_blocks(opts[CLOP_ONLINE].set, opts[CLOP_OFFLINE].set, opts[CLOP_REGION].str);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_NUM_DEVICES:
|
||
|
|
rv = cmd_show_num_devices();
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_NUM_REGIONS:
|
||
|
|
rv = cmd_show_num_regions();
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_REGION_ISENABLED:
|
||
|
|
rv = cmd_show_region_isenabled(opts[CLOP_REGION].str);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_SYSTEM_BLOCKSIZE:
|
||
|
|
rv = cmd_show_system_blocksize(opts[CLOP_HUMAN].set);;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CLCM_SHOW_SYSTEM_POLICY:
|
||
|
|
rv = cmd_show_system_policy();
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
rv = 1;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
int main(int argc, char *argv[])
|
||
|
|
{
|
||
|
|
int rv;
|
||
|
|
|
||
|
|
// Initialize variables
|
||
|
|
rv = 1;
|
||
|
|
|
||
|
|
// Parse options
|
||
|
|
rv = options_parse(argc, argv);
|
||
|
|
if (rv != 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: Failed to parse command line parameters: %d\n", rv);
|
||
|
|
goto end;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Verify command was specified
|
||
|
|
if (opts[CLOP_CMD].set == 0)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Error: No command specified\n");
|
||
|
|
rv = 1;
|
||
|
|
goto err;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Execute command
|
||
|
|
rv = run();
|
||
|
|
if (rv != 0)
|
||
|
|
fprintf(stderr, "Error: Command failed: %d\n", rv);
|
||
|
|
|
||
|
|
err:
|
||
|
|
|
||
|
|
options_free();
|
||
|
|
|
||
|
|
end:
|
||
|
|
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|