00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00041
00042 #include <stdio.h>
00043 #include <stdint.h>
00044 #include <stdlib.h>
00045
00046 #include <result.h>
00047 #include "phlog_tornbit.h"
00048 #include "hal/pcm_i.h"
00049 #include <smmintrin.h>
00050
00051
00052 uint64_t load_nt_word(void *addr)
00053 {
00054 union {
00055 __m128i x;
00056 char b[16];
00057 } u;
00058
00059 uintptr_t aladdr;
00060 uintptr_t offset;
00061
00062 aladdr = ((uintptr_t) addr) & ~0xF;
00063 offset = ((uintptr_t) addr) & 0xF;
00064
00065 u.x = _mm_stream_load_si128((__m128i *) aladdr);
00066
00067 return *((uint64_t *) &u.b[offset]);
00068 }
00069
00070
00071
00076 m_result_t
00077 m_phlog_tornbit_check_consistency(m_phlog_tornbit_nvmd_t *nvmd,
00078 pcm_word_t *nvphlog,
00079 uint64_t *stable_tail)
00080 {
00081 uint64_t head_index;
00082 uint64_t i;
00083 uint64_t tornbit;
00084 uint64_t valid_tornbit;
00085 int flip_tornbit = 0;
00086
00087 valid_tornbit = LF_TORNBIT & nvmd->flags;
00088 i = head_index = nvmd->flags & LF_HEAD_MASK;
00089 while(1) {
00090 tornbit = (TORN_MASK & nvphlog[i]);
00091 if (tornbit != valid_tornbit) {
00092 *stable_tail = i;
00093 break;
00094 }
00095 i = (i + 1) & (PHYSICAL_LOG_NUM_ENTRIES - 1);
00096 if (i==0) {
00097 flip_tornbit = 1;
00098 valid_tornbit = TORN_MASK & ~valid_tornbit;
00099 }
00100 if (i==head_index) {
00101 break;
00102 }
00103 }
00104
00105 return M_R_SUCCESS;
00106 }
00107
00108
00109 static
00110 m_result_t
00111 tornbit_format_nvlog (pcm_storeset_t *set,
00112 uint32_t head_index,
00113 uint64_t tornbit,
00114 m_phlog_tornbit_nvmd_t *nvmd,
00115 pcm_word_t *nvphlog)
00116 {
00117 int i;
00118
00119 PCM_NT_STORE(set, (volatile pcm_word_t *) &nvmd->flags, head_index | tornbit);
00120 for (i=0; i<PHYSICAL_LOG_NUM_ENTRIES; i++) {
00121 if (i<head_index) {
00122 if ((nvphlog[i] & TORN_MASK) != tornbit) {
00123 PCM_NT_STORE(set, (volatile pcm_word_t *) &nvphlog[i], tornbit);
00124 }
00125 } else {
00126 if ((nvphlog[i] & TORN_MASK) == tornbit) {
00127 PCM_NT_STORE(set, (volatile pcm_word_t *) &nvphlog[i], ~tornbit & TORN_MASK);
00128 }
00129 }
00130 }
00131 PCM_NT_FLUSH(set);
00132
00133 return M_R_SUCCESS;
00134 }
00135
00136
00140 m_result_t
00141 m_phlog_tornbit_format (pcm_storeset_t *set,
00142 m_phlog_tornbit_nvmd_t *nvmd,
00143 pcm_word_t *nvphlog,
00144 int type)
00145 {
00146 m_result_t rv = M_R_FAILURE;
00147
00148 if ((nvmd->generic_flags & LF_TYPE_MASK) == type) {
00149
00150
00151
00152
00153 rv = tornbit_format_nvlog (set, 0, TORNBIT_ONE, nvmd, nvphlog);
00154 if (rv != M_R_SUCCESS) {
00155 goto out;
00156 }
00157 } else {
00158 rv = tornbit_format_nvlog (set, 0, TORNBIT_ONE, nvmd, nvphlog);
00159 if (rv != M_R_SUCCESS) {
00160 goto out;
00161 }
00162 }
00163 rv = M_R_SUCCESS;
00164 out:
00165 return rv;
00166 }
00167
00168
00172 m_result_t
00173 m_phlog_tornbit_alloc (m_phlog_tornbit_t **phlog_tornbitp)
00174 {
00175 m_phlog_tornbit_t *phlog_tornbit;
00176
00177 if (posix_memalign((void **) &phlog_tornbit, sizeof(uint64_t),sizeof(m_phlog_tornbit_t)) != 0)
00178 {
00179 return M_R_FAILURE;
00180 }
00181 *phlog_tornbitp = phlog_tornbit;
00182
00183 return M_R_SUCCESS;
00184 }
00185
00186
00191 m_result_t
00192 m_phlog_tornbit_init (m_phlog_tornbit_t *phlog,
00193 m_phlog_tornbit_nvmd_t *nvmd,
00194 pcm_word_t *nvphlog)
00195 {
00196 pcm_word_t tornbit;
00197
00198 phlog->nvmd = nvmd;
00199 phlog->nvphlog = nvphlog;
00200 tornbit = LF_TORNBIT & phlog->nvmd->flags;
00201 phlog->tornbit = tornbit;
00202 phlog->buffer_count = 0;
00203 phlog->write_remainder = 0x0;
00204 phlog->write_remainder_nbits = 0;
00205 phlog->read_remainder = 0x0;
00206 phlog->read_remainder_nbits = 0;
00207 phlog->head = phlog->tail = phlog->stable_tail = phlog->read_index = phlog->nvmd->flags & LF_HEAD_MASK;
00208
00209
00210 phlog->stat_wait_for_trunc = 0;
00211 phlog->stat_wait_time_for_trunc = 0;
00212 return M_R_SUCCESS;
00213 }
00214
00215
00219 m_result_t
00220 m_phlog_tornbit_truncate_async(pcm_storeset_t *set, m_phlog_tornbit_t *phlog)
00221 {
00222 pcm_word_t tornbit;
00223
00224 tornbit = LF_TORNBIT & phlog->nvmd->flags;
00225
00226
00227
00228
00229
00230 if (phlog->head > phlog->read_index) {
00231 tornbit = ~tornbit & TORN_MASK;
00232 }
00233
00234 phlog->head = phlog->read_index;
00235
00236
00237 PCM_NT_STORE(set, (volatile pcm_word_t *) &phlog->nvmd->flags, (pcm_word_t) (phlog->head | tornbit));
00238 PCM_NT_FLUSH(set);
00239
00240 return M_R_SUCCESS;
00241 }
00242
00243
00244 void m_phlog_print_buffer(m_phlog_tornbit_t *log)
00245 {
00246 int i;
00247 for (i=0; i<log->buffer_count; i++) {
00248 printf("buffer[%d] = %lX (", i, log->buffer[i]);
00249 print_binary64(log->buffer[i]);
00250 printf(")\n");
00251 }
00252 }