ocf/src/utils/utils_cache_line.h
Robert Baldyga a8e1ce8cc5 Initial commit
Signed-off-by: Robert Baldyga <robert.baldyga@intel.com>
2018-11-29 15:14:21 +01:00

373 lines
9.3 KiB
C

/*
* Copyright(c) 2012-2018 Intel Corporation
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef UTILS_CACHE_LINE_H_
#define UTILS_CACHE_LINE_H_
#include "../metadata/metadata.h"
#include "../eviction/eviction.h"
#include "../eviction/ops.h"
#include "../concurrency/ocf_cache_concurrency.h"
#include "../engine/cache_engine.h"
#include "../ocf_request.h"
#include "../ocf_def_priv.h"
/**
* @file utils_cache_line.h
* @brief OCF utilities for cache line operations
*/
static inline ocf_cache_line_size_t ocf_line_size(
struct ocf_cache *cache)
{
return cache->metadata.settings.size;
}
static inline uint64_t ocf_line_pages(struct ocf_cache *cache)
{
return cache->metadata.settings.size / PAGE_SIZE;
}
static inline uint64_t ocf_line_sectors(struct ocf_cache *cache)
{
return cache->metadata.settings.sector_count;
}
static inline uint64_t ocf_line_end_sector(struct ocf_cache *cache)
{
return cache->metadata.settings.sector_end;
}
static inline uint64_t ocf_line_start_sector(struct ocf_cache *cache)
{
return cache->metadata.settings.sector_start;
}
static inline uint64_t ocf_bytes_round_lines(struct ocf_cache *cache,
uint64_t bytes)
{
return (bytes + ocf_line_size(cache) - 1) / ocf_line_size(cache);
}
static inline uint64_t ocf_bytes_2_lines(struct ocf_cache *cache,
uint64_t bytes)
{
return bytes / ocf_line_size(cache);
}
static inline uint64_t ocf_bytes_2_lines_round_up(
struct ocf_cache *cache, uint64_t bytes)
{
return DIV_ROUND_UP(bytes, ocf_line_size(cache));
}
static inline uint64_t ocf_lines_2_bytes(struct ocf_cache *cache,
uint64_t lines)
{
return lines * ocf_line_size(cache);
}
/**
* @brief Set cache line invalid
*
* @param cache Cache instance
* @param start_bit Start bit of cache line for which state will be set
* @param end_bit End bit of cache line for which state will be set
* @param rq OCF request
* @param map_idx Array index to map containing cache line to invalid
*/
void set_cache_line_invalid(struct ocf_cache *cache, uint8_t start_bit,
uint8_t end_bit, struct ocf_request *rq, uint32_t map_idx);
/**
* @brief Set cache line invalid without flush
*
* @param cache Cache instance
* @param start_bit Start bit of cache line for which state will be set
* @param end_bit End bit of cache line for which state will be set
* @param line Cache line to invalid
*/
void set_cache_line_invalid_no_flush(struct ocf_cache *cache, uint8_t start_bit,
uint8_t end_bit, ocf_cache_line_t line);
/**
* @brief Set cache line valid
*
* @param cache Cache instance
* @param start_bit Start bit of cache line for which state will be set
* @param end_bit End bit of cache line for which state will be set
* @param rq OCF request
* @param map_idx Array index to map containing cache line to invalid
*/
void set_cache_line_valid(struct ocf_cache *cache, uint8_t start_bit,
uint8_t end_bit, struct ocf_request *rq, uint32_t map_idx);
/**
* @brief Set cache line clean
*
* @param cache Cache instance
* @param start_bit Start bit of cache line for which state will be set
* @param end_bit End bit of cache line for which state will be set
* @param rq OCF request
* @param map_idx Array index to map containing cache line to invalid
*/
void set_cache_line_clean(struct ocf_cache *cache, uint8_t start_bit,
uint8_t end_bit, struct ocf_request *rq, uint32_t map_idx);
/**
* @brief Set cache line dirty
*
* @param cache Cache instance
* @param start_bit Start bit of cache line for which state will be set
* @param end_bit End bit of cache line for which state will be set
* @param rq OCF request
* @param map_idx Array index to map containing cache line to invalid
*/
void set_cache_line_dirty(struct ocf_cache *cache, uint8_t start_bit,
uint8_t end_bit, struct ocf_request *rq, uint32_t map_idx);
/**
* @brief Remove cache line from cleaning policy
*
* @param cache - cache instance
* @param line - cache line to be removed
*
*/
static inline void ocf_purge_cleaning_policy(struct ocf_cache *cache,
ocf_cache_line_t line)
{
ocf_cleaning_t clean_type = cache->conf_meta->cleaning_policy_type;
ENV_BUG_ON(clean_type >= ocf_cleaning_max);
/* Remove from cleaning policy */
if (cleaning_policy_ops[clean_type].purge_cache_block != NULL)
cleaning_policy_ops[clean_type].purge_cache_block(cache, line);
}
/**
* @brief Remove cache line from eviction policy
*
* @param cache - cache instance
* @param line - cache line to be removed
*/
static inline void ocf_purge_eviction_policy(struct ocf_cache *cache,
ocf_cache_line_t line)
{
ocf_eviction_purge_cache_line(cache, line);
}
/**
* @brief Set cache line clean and invalid and remove form lists
*
* @param cache Cache instance
* @param start Start bit of range in cache line to purge
* @param end End bit of range in cache line to purge
* @param rq OCF request
* @param map_idx Array index to map containing cache line to purge
*/
static inline void _ocf_purge_cache_line_sec(struct ocf_cache *cache,
uint8_t start, uint8_t stop, struct ocf_request *rq,
uint32_t map_idx)
{
set_cache_line_clean(cache, start, stop, rq, map_idx);
set_cache_line_invalid(cache, start, stop, rq, map_idx);
}
/**
* @brief Purge cache line (remove completely, form collision, move to free
* partition, from cleaning policy and eviction policy)
*
* @param rq - OCF request to purge
*/
static inline void ocf_purge_map_info(struct ocf_request *rq)
{
uint32_t map_idx = 0;
uint8_t start_bit;
uint8_t end_bit;
struct ocf_map_info *map = rq->map;
struct ocf_cache *cache = rq->cache;
uint32_t count = rq->core_line_count;
/* Purge range on the basis of map info
*
* | 01234567 | 01234567 | ... | 01234567 | 01234567 |
* | -----+++ | ++++++++ | +++ | ++++++++ | +++++--- |
* | first | Middle | last |
*/
for (map_idx = 0; map_idx < count; map_idx++) {
if (map[map_idx].status == LOOKUP_MISS)
continue;
start_bit = 0;
end_bit = ocf_line_end_sector(cache);
if (map_idx == 0) {
/* First */
start_bit = BYTES_TO_SECTORS(rq->byte_position)
% ocf_line_sectors(cache);
}
if (map_idx == (count - 1)) {
/* Last */
end_bit = BYTES_TO_SECTORS(rq->byte_position +
rq->byte_length - 1) %
ocf_line_sectors(cache);
}
_ocf_purge_cache_line_sec(cache, start_bit, end_bit, rq,
map_idx);
}
}
static inline void ocf_set_valid_map_info(struct ocf_request *rq)
{
uint32_t map_idx = 0;
uint8_t start_bit;
uint8_t end_bit;
struct ocf_cache *cache = rq->cache;
uint32_t count = rq->core_line_count;
struct ocf_map_info *map = rq->map;
/* Set valid bits for sectors on the basis of map info
*
* | 01234567 | 01234567 | ... | 01234567 | 01234567 |
* | -----+++ | ++++++++ | +++ | ++++++++ | +++++--- |
* | first | Middle | last |
*/
for (map_idx = 0; map_idx < count; map_idx++) {
ENV_BUG_ON(map[map_idx].status == LOOKUP_MISS);
start_bit = 0;
end_bit = ocf_line_end_sector(cache);
if (map_idx == 0) {
/* First */
start_bit = BYTES_TO_SECTORS(rq->byte_position)
% ocf_line_sectors(cache);
}
if (map_idx == (count - 1)) {
/* Last */
end_bit = BYTES_TO_SECTORS(rq->byte_position +
rq->byte_length - 1)
% ocf_line_sectors(cache);
}
set_cache_line_valid(cache, start_bit, end_bit, rq, map_idx);
}
}
static inline void ocf_set_dirty_map_info(struct ocf_request *rq)
{
uint32_t map_idx = 0;
uint8_t start_bit;
uint8_t end_bit;
struct ocf_cache *cache = rq->cache;
uint32_t count = rq->core_line_count;
/* Set valid bits for sectors on the basis of map info
*
* | 01234567 | 01234567 | ... | 01234567 | 01234567 |
* | -----+++ | ++++++++ | +++ | ++++++++ | +++++--- |
* | first | Middle | last |
*/
for (map_idx = 0; map_idx < count; map_idx++) {
start_bit = 0;
end_bit = ocf_line_end_sector(cache);
if (map_idx == 0) {
/* First */
start_bit = BYTES_TO_SECTORS(rq->byte_position)
% ocf_line_sectors(cache);
}
if (map_idx == (count - 1)) {
/* Last */
end_bit = BYTES_TO_SECTORS(rq->byte_position +
rq->byte_length - 1) %
ocf_line_sectors(cache);
}
set_cache_line_dirty(cache, start_bit, end_bit, rq, map_idx);
}
}
static inline void ocf_set_clean_map_info(struct ocf_request *rq)
{
uint32_t map_idx = 0;
uint8_t start_bit;
uint8_t end_bit;
struct ocf_cache *cache = rq->cache;
uint32_t count = rq->core_line_count;
/* Set valid bits for sectors on the basis of map info
*
* | 01234567 | 01234567 | ... | 01234567 | 01234567 |
* | -----+++ | ++++++++ | +++ | ++++++++ | +++++--- |
* | first | Middle | last |
*/
for (map_idx = 0; map_idx < count; map_idx++) {
start_bit = 0;
end_bit = ocf_line_end_sector(cache);
if (map_idx == 0) {
/* First */
start_bit = BYTES_TO_SECTORS(rq->byte_position)
% ocf_line_sectors(cache);
}
if (map_idx == (count - 1)) {
/* Last */
end_bit = BYTES_TO_SECTORS(rq->byte_position +
rq->byte_length - 1) %
ocf_line_sectors(cache);
}
set_cache_line_clean(cache, start_bit, end_bit, rq, map_idx);
}
}
/**
* @brief Validate cache line size
*
* @param[in] size Cache line size
*
* @retval true cache line size is valid
* @retval false cache line is invalid
*/
static inline bool ocf_cache_line_size_is_valid(uint64_t size)
{
switch (size) {
case 4 * KiB:
case 8 * KiB:
case 16 * KiB:
case 32 * KiB:
case 64 * KiB:
return true;
default:
return false;
}
}
#endif /* UTILS_CACHE_LINE_H_ */