legacy_platform_drv: update quotas on 'attach_dma_mem'

'Platform::Device_pd::attach_dma_mem' may lead to insufficient resources
for meta data, which is reflected to the client via 'Out_of_caps' or
'Out_of_ram'. In case the client upgrades its session the quotas need to
be passed to core as done by
'Platform::Device_pd::Expanding_region_map_client::attach'.

issue #4451
This commit is contained in:
Sebastian Sumpf 2022-04-05 14:26:34 +02:00 committed by Christian Helmuth
parent abc0bf3220
commit 7a06a6ac59
2 changed files with 43 additions and 28 deletions

View File

@ -31,28 +31,40 @@ void Platform::Device_pd::attach_dma_mem(Dataspace_capability ds_cap,
addr_t page = ~0UL;
using Attach_dma_error = Pd_session::Attach_dma_error;
_pd.attach_dma(ds_cap, dma_addr).with_result(
bool retry = false;
[&] (Pd_session::Attach_dma_ok) {
do {
_pd.attach_dma(ds_cap, dma_addr).with_result(
page = dma_addr;
[&] (Pd_session::Attach_dma_ok) {
/* trigger eager mapping of memory */
_pd.map(page, size);
},
[&] (Attach_dma_error e) {
switch (e) {
case Attach_dma_error::OUT_OF_RAM: throw Out_of_ram();
case Attach_dma_error::OUT_OF_CAPS: throw Out_of_caps();
case Attach_dma_error::DENIED:
warning("Pd_session::attach_dma denied");
page = dma_addr;
break;
/* trigger eager mapping of memory */
_pd.map(page, size);
retry = false;
},
[&] (Attach_dma_error e) {
switch (e) {
case Attach_dma_error::OUT_OF_RAM:
_address_space.upgrade_ram();
retry = true;
break;
case Attach_dma_error::OUT_OF_CAPS:
_address_space.upgrade_caps();
retry = true;
break;
case Attach_dma_error::DENIED:
warning("Pd_session::attach_dma denied");
page = dma_addr;
retry = false;
break;
}
}
});
);
} while (retry);
/* sanity check */
if ((page == ~0UL) || (page != dma_addr)) {

View File

@ -75,28 +75,31 @@ class Platform::Device_pd
executable,
writeable); },
[&] () {
enum { UPGRADE_CAP_QUOTA = 2 };
Cap_quota const caps { UPGRADE_CAP_QUOTA };
_cap_guard.withdraw(caps);
_env.pd().transfer_quota(_pd.rpc_cap(), caps);
upgrade_caps();
}
);
},
[&] () {
enum { UPGRADE_RAM_QUOTA = 4096 };
Ram_quota const ram { UPGRADE_RAM_QUOTA };
_ram_guard.withdraw(ram);
_env.pd().transfer_quota(_pd.rpc_cap(), ram);
upgrade_ram();
}
);
}
Local_addr attach_at(Dataspace_capability ds,
addr_t local_addr,
size_t size = 0,
off_t offset = 0) {
return attach(ds, size, offset, true, local_addr); };
void upgrade_ram()
{
enum { UPGRADE_RAM_QUOTA = 4096 };
Ram_quota const ram { UPGRADE_RAM_QUOTA };
_ram_guard.withdraw(ram);
_env.pd().transfer_quota(_pd.rpc_cap(), ram);
}
void upgrade_caps()
{
enum { UPGRADE_CAP_QUOTA = 2 };
Cap_quota const caps { UPGRADE_CAP_QUOTA };
_cap_guard.withdraw(caps);
_env.pd().transfer_quota(_pd.rpc_cap(), caps);
}
} _address_space;
public: