aboutsummaryrefslogtreecommitdiffstats
path: root/Projects/Webserver/Lib/FATFs/diskio.c
blob: 64daad9cdbbd7c47f84ecbb29ce63146e9268852 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2007        */
/*-----------------------------------------------------------------------*/
/* This is a stub disk I/O module that acts as front end of the existing */
/* disk I/O modules and attach it to FatFs module with common interface. */
/*-----------------------------------------------------------------------*/

#include "diskio.h"

/*-----------------------------------------------------------------------*/
/* Initialize a Drive                                                    */

DSTATUS disk_initialize (
	BYTE drv				/* Physical drive number (0..) */
)
{
	return FR_OK;
}



/*-----------------------------------------------------------------------*/
/* Return Disk Status                                                    */

DSTATUS disk_status (
	BYTE drv		/* Physical drive number (0..) */
)
{
	return FR_OK;
}



/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */

DRESULT disk_read (
	BYTE drv,		/* Physical drive number (0..) */
	BYTE *buff,		/* Data buffer to store read data */
	DWORD sector,	/* Sector address (LBA) */
	BYTE count		/* Number of sectors to read (1..255) */
)
{
	DataflashManager_ReadBlocks_RAM(sector, count, buff);
	return RES_OK;
}



/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */

#if _READONLY == 0
DRESULT disk_write (
	BYTE drv,			/* Physical drive number (0..) */
	const BYTE *buff,	/* Data to be written */
	DWORD sector,		/* Sector address (LBA) */
	BYTE count			/* Number of sectors to write (1..255) */
)
{
	DataflashManager_WriteBlocks_RAM(sector, count, buff);
	return RES_OK;
}
#endif /* _READONLY */
an> #include <xen/smp.h> #include <xen/percpu.h> #include <asm/hvm/asid.h> /* * ASIDs partition the physical TLB. In the current implementation ASIDs are * introduced to reduce the number of TLB flushes. Each time the guest's * virtual address space changes (e.g. due to an INVLPG, MOV-TO-{CR3, CR4} * operation), instead of flushing the TLB, a new ASID is assigned. This * reduces the number of TLB flushes to at most 1/#ASIDs. The biggest * advantage is that hot parts of the hypervisor's code and data retain in * the TLB. * * Sketch of the Implementation: * * ASIDs are a CPU-local resource. As preemption of ASIDs is not possible, * ASIDs are assigned in a round-robin scheme. To minimize the overhead of * ASID invalidation, at the time of a TLB flush, ASIDs are tagged with a * 64-bit generation. Only on a generation overflow the code needs to * invalidate all ASID information stored at the VCPUs with are run on the * specific physical processor. This overflow appears after about 2^80 * host processor cycles, so we do not optimize this case, but simply disable * ASID useage to retain correctness. */ /* Per-CPU ASID management. */ struct hvm_asid_data { u64 core_asid_generation; u32 next_asid; u32 max_asid; bool_t disabled; bool_t initialised; }; static DEFINE_PER_CPU(struct hvm_asid_data, hvm_asid_data); void hvm_asid_init(int nasids) { static s8 g_disabled = -1; struct hvm_asid_data *data = &this_cpu(hvm_asid_data); /* * If already initialised, we just bump the generation to force a TLB * flush. Resetting the generation could be dangerous, if VCPUs still * exist that reference earlier generations on this CPU. */ if ( test_and_set_bool(data->initialised) ) return hvm_asid_flush_core(); data->max_asid = nasids - 1; data->disabled = (nasids <= 1); if ( g_disabled != data->disabled ) { printk("HVM: ASIDs %sabled.\n", data->disabled ? "dis" : "en"); if ( g_disabled < 0 ) g_disabled = data->disabled; } /* Zero indicates 'invalid generation', so we start the count at one. */ data->core_asid_generation = 1; /* Zero indicates 'ASIDs disabled', so we start the count at one. */ data->next_asid = 1; } void hvm_asid_flush_vcpu(struct vcpu *v) { v->arch.hvm_vcpu.asid_generation = 0; } void hvm_asid_flush_core(void) { struct hvm_asid_data *data = &this_cpu(hvm_asid_data); if ( data->disabled ) return; if ( likely(++data->core_asid_generation != 0) ) { data->next_asid = 1; return; } /* * ASID generations are 64 bit. Overflow of generations never happens. * For safety, we simply disable ASIDs, so correctness is established; it * only runs a bit slower. */ printk("HVM: ASID generation overrun. Disabling ASIDs.\n"); data->disabled = 1; } bool_t hvm_asid_handle_vmenter(void) { struct vcpu *curr = current; struct hvm_asid_data *data = &this_cpu(hvm_asid_data); /* On erratum #170 systems we must flush the TLB. * Generation overruns are taken here, too. */ if ( data->disabled ) { curr->arch.hvm_vcpu.asid = 0; return 0; } /* Test if VCPU has valid ASID. */ if ( curr->arch.hvm_vcpu.asid_generation == data->core_asid_generation ) return 0; /* If there are no free ASIDs, need to go to a new generation */ if ( unlikely(data->next_asid > data->max_asid) ) hvm_asid_flush_core(); /* Now guaranteed to be a free ASID. */ curr->arch.hvm_vcpu.asid = data->next_asid++; curr->arch.hvm_vcpu.asid_generation = data->core_asid_generation; /* * When we assign ASID 1, flush all TLB entries as we are starting a new * generation, and all old ASID allocations are now stale. */ return (curr->arch.hvm_vcpu.asid == 1); } /* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */